Skip to content

Commit

Permalink
Merge branch 'HSM-432/hardcode-pub-gpg-keys'
Browse files Browse the repository at this point in the history
  • Loading branch information
islamaminBitGo committed Oct 30, 2024
2 parents 1086afc + fbcfcbf commit d0d85f1
Show file tree
Hide file tree
Showing 11 changed files with 365 additions and 40 deletions.
169 changes: 169 additions & 0 deletions modules/bitgo/test/v2/unit/internal/tssUtils/bitgoMpcGpgPubKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import {
BitgoMpcGpgPubKeys,
common,
ECDSAUtils,
EddsaUtils,
EnvironmentName,
IRequestTracer,
Wallet,
} from '@bitgo/sdk-core';
import { TestBitGo } from '@bitgo/sdk-test';

import { BitGo } from '../../../../../src';
import * as openpgp from 'openpgp';
import nock = require('nock');
import assert = require('assert');

class TestEcdsaMpcv2Utils extends ECDSAUtils.EcdsaMPCv2Utils {
public async testPickBitgoPubGpgKeyForSigning(
isMpcv2: boolean,
reqId?: IRequestTracer,
enterpriseId?: string
): Promise<openpgp.Key> {
return this.pickBitgoPubGpgKeyForSigning(isMpcv2, reqId, enterpriseId);
}
}

class TestEddsaMpcv1Utils extends EddsaUtils {
public async testPickBitgoPubGpgKeyForSigning(
isMpcv2: boolean,
reqId?: IRequestTracer,
enterpriseId?: string
): Promise<openpgp.Key> {
return this.pickBitgoPubGpgKeyForSigning(isMpcv2, reqId, enterpriseId);
}
}

describe('TSS MPC Pick BitGo GPG Pub Key Utils:', function () {
const walletId = '5b34252f1bf349930e34020a00000000';
const enterpriseId = '6449153a6f6bc20006d66771cdbe15d3';
const ecdsaCoinName = 'hteth';
const eddsaCoinName = 'tsol';
const ecdsaWalletData = {
id: walletId,
enterprise: enterpriseId,
coin: ecdsaCoinName,
coinSpecific: {},
multisigType: 'tss',
keys: ['key1', 'key2', 'key3'],
};
const eddsaWalletData = {
id: walletId,
enterprise: enterpriseId,
coin: eddsaCoinName,
coinSpecific: {},
multisigType: 'tss',
keys: ['key1', 'key2', 'key3'],
};
const envs: EnvironmentName[] = ['test', 'staging', 'prod'];
const ecdsaMpcv2Utils: TestEcdsaMpcv2Utils[] = [];
const eddsaMpcv1Utils: TestEddsaMpcv1Utils[] = [];

before(async function () {
nock.cleanAll();
for (const env of envs) {
const bitgoInstance = TestBitGo.decorate(BitGo, { env });
bitgoInstance.initializeTestVars();
let coinInstance = bitgoInstance.coin(ecdsaCoinName);
ecdsaMpcv2Utils.push(
new TestEcdsaMpcv2Utils(bitgoInstance, coinInstance, new Wallet(bitgoInstance, coinInstance, ecdsaWalletData))
);
coinInstance = bitgoInstance.coin(eddsaCoinName);
eddsaMpcv1Utils.push(
new TestEddsaMpcv1Utils(bitgoInstance, coinInstance, new Wallet(bitgoInstance, coinInstance, eddsaWalletData))
);
}
});

beforeEach(async function () {
for (const env of envs) {
const bgUrl = common.Environments[env].uri;
nock(bgUrl).get(`/api/v2/${ecdsaCoinName}/key/key3`).times(envs.length).reply(200, { hsmType: 'onprem' });
nock(bgUrl).get(`/api/v2/${eddsaCoinName}/key/key3`).times(envs.length).reply(200, { hsmType: 'nitro' });
}
});

envs.forEach(async function (env, index) {
it(`should pick correct Mpcv2 BitGo GPG Pub Key for ${env} env`, async function () {
const bitgoGpgPubKey = await ecdsaMpcv2Utils[index].testPickBitgoPubGpgKeyForSigning(true);
bitgoGpgPubKey
.armor()
.should.equal(BitgoMpcGpgPubKeys.bitgoMpcGpgPubKeys['mpcv2']['onprem'][env === 'staging' ? 'test' : env]);
});
});

envs.forEach(async function (env, index) {
it(`should pick correct Mpcv1 BitGo GPG Pub Key for ${env} env`, async function () {
const bitgoGpgPubKey = await eddsaMpcv1Utils[index].testPickBitgoPubGpgKeyForSigning(false);
bitgoGpgPubKey
.armor()
.should.equal(BitgoMpcGpgPubKeys.bitgoMpcGpgPubKeys['mpcv1']['nitro'][env === 'staging' ? 'test' : env]);
});
});

it(`should pick BitGo GPG Pub Key based on enterprise flag for mock env`, async function () {
const bgUrl = common.Environments['mock'].uri;
const testBitgo = TestBitGo.decorate(BitGo, { env: 'mock' });
const testCoin = testBitgo.coin(ecdsaCoinName);
const bitgoGPGKey = await openpgp.generateKey({
userIDs: [
{
name: 'bitgo',
email: '[email protected]',
},
],
});
nock(bgUrl)
.get(`/api/v2/${ecdsaCoinName}/tss/pubkey`)
.query({ enterpriseId })
.reply(200, { mpcv2PublicKey: bitgoGPGKey.publicKey });
const ecdsaMpcv2Util = new TestEcdsaMpcv2Utils(
testBitgo,
testCoin,
new Wallet(testBitgo, testCoin, ecdsaWalletData)
);
const bitgoGpgPubKey = await ecdsaMpcv2Util.testPickBitgoPubGpgKeyForSigning(true, undefined, enterpriseId);
bitgoGpgPubKey.armor().should.equal(bitgoGPGKey.publicKey);
});

it(`should pick BitGo GPG Pub Key based on constants api for mock env if enterprise flag based fetch fails`, async function () {
nock.cleanAll();
const bgUrl = common.Environments['mock'].uri;
const testBitgo = TestBitGo.decorate(BitGo, { env: 'mock' });
const testCoin = testBitgo.coin(ecdsaCoinName);
const bitgoGPGKey = await openpgp.generateKey({
userIDs: [
{
name: 'bitgo',
email: '[email protected]',
},
],
});
const constants = {
mpc: {
bitgoMPCv2PublicKey: bitgoGPGKey.publicKey,
bitgoPublicKey: bitgoGPGKey.publicKey,
},
};
nock(bgUrl).get('/api/v1/client/constants').times(2).reply(200, { ttl: 3600, constants });
const ecdsaMpcv2Util = new TestEcdsaMpcv2Utils(
testBitgo,
testCoin,
new Wallet(testBitgo, testCoin, ecdsaWalletData)
);
const bitgoGpgPubKey = await ecdsaMpcv2Util.testPickBitgoPubGpgKeyForSigning(true, undefined, enterpriseId);
bitgoGpgPubKey.armor().should.equal(bitgoGPGKey.publicKey);
});

it(`should throw an error if config is not available in one of test, staging, or prod`, async function () {
nock.cleanAll();
const testBitgo = TestBitGo.decorate(BitGo, { env: 'test' });
const testCoin = testBitgo.coin(ecdsaCoinName);
const ecdsaMpcv2Util = new TestEcdsaMpcv2Utils(
testBitgo,
testCoin,
new Wallet(testBitgo, testCoin, ecdsaWalletData)
);
await assert.rejects(async () => await ecdsaMpcv2Util.testPickBitgoPubGpgKeyForSigning(true));
});
});
1 change: 1 addition & 0 deletions modules/express/test/unit/clientRoutes/externalSign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ describe('External signer', () => {
const reqCommitment = {
bitgo: bgTest,
body: {
bitgoGpgPubKey: bitgoGpgKey.public,
txRequest: {
apiVersion: 'full',
walletId: walletID,
Expand Down
2 changes: 2 additions & 0 deletions modules/sdk-core/src/bitgo/keychain/iKeychains.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IRequestTracer } from '../../api';
import { KeychainsTriplet, KeyPair } from '../baseCoin';
import { BitgoPubKeyType } from '../utils/tss/baseTypes';
import { BackupProvider, IWallet } from '../wallet';
import { BitGoKeyFromOvcShares, OvcToBitGoJSON } from './ovcJsonCodec';

Expand Down Expand Up @@ -39,6 +40,7 @@ export interface Keychain {
commonKeychain?: string;
keyShares?: ApiKeyShare[];
walletHSMGPGPublicKeySigs?: string;
hsmType?: BitgoPubKeyType;
type: KeyType;
source?: SourceType;
coinSpecific?: { [coinName: string]: unknown };
Expand Down
66 changes: 66 additions & 0 deletions modules/sdk-core/src/bitgo/tss/bitgoPubKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import assert from 'assert';
import { EnvironmentName } from '../environments';

export const bitgoMpcGpgPubKeys = {
mpcv1: {
nitro: {
test: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxk8EYqEU5hMFK4EEAAoCAwQDdbAIZrsblEXIavyg2go6p9oG0SqWTgFsdHTc\nBhqdIS/WjQ8pj75q+vLqFtV9hlImYGInsIWh97fsigzB2owyzRhoc20gPGhz\nbUB0ZXN0LmJpdGdvLmNvbT7ChAQTEwgAFQUCYqEU5wILCQIVCAIWAAIbAwIe\nAQAhCRCJNRsIDGunexYhBHRL5D/8nRM3opQnXok1GwgMa6d7tg8A/24A9awq\nSCJx7RddiUzFHcKhVvvo3R5N7bHaOGP3TP79AP0TavF2WzhUXmZSjt3IK23O\n7/aknbijVeq52ghbWb1SwsJ1BBATCAAGBQJioRTnACEJEAWuA35KJgtgFiEE\nZttLPR0KcYvjgvJCBa4DfkomC2BsrwD/Z+43zOw+WpfPHxe+ypyVog5fnOKl\nXwleH6zDvqUWmWkA/iaHC6ullYkSG4Mv68k6qbtgR/pms/X7rkfa0QQFJy5p\nzlMEYqEU5hIFK4EEAAoCAwSsLqmfonjMF3o0nZ5JHvLpmfTA1RIVDsAEoRON\ntZA6rAA23pGl6s3Iyt4/fX9Adzoh3EElOjMsgi8Aj3dFpuqiAwEIB8J4BBgT\nCAAJBQJioRTnAhsMACEJEIk1GwgMa6d7FiEEdEvkP/ydEzeilCdeiTUbCAxr\np3vM7AD9GPp6HhYNEh2VVCDtFSt14Bni5FVM5icpVDo6w9ibvWAA/2Ti3Jv4\nIhIxl81/wqAgqigIblrz6vjtagr9/ykXQCW3\n=skCo\n-----END PGP PUBLIC KEY BLOCK-----\n',
prod: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxk8EY4m6ZBMFK4EEAAoCAwRSTwdXgiY+EBNj2JgNzisUygcVGVxp1Fv+pT64\nTsJ64y9Fr5h9ljqMIsmM0MWn9hczpmdAEHpkSg264wAPNcIWzQtCaXRHbyBO\naXRyb8KEBBMTCAA2BQJjibpmAgsJCRDHgvrWqx65HwIVCAIWAAIbAwIeARYh\nBLgnzI9Cn6UamNlJ2MeC+tarHrkfAABEwgD/W0+LXpHEMtSnShf7rSg7tQfG\n1Bb6be2Y1utd+auj/EcA/jGJO8MtejxcVGBpH/ZrODL+D0yS/I2YD3nveLtD\nD5z3wnUEEBMIACcFAmOJumkJEHuS1voAd5fJFiEE1Xxbfbbr5zLGqNJ7e5LW\n+gB3l8kAAPtmAP0WZnW/cgGCWzG1NYbAU1sJUwYdspM1WDLByjmo5JkCrQD+\nOK/6U8zvmQEcoOq0YXArhb+yWQDDHDEkLxRptB+KO8nOUwRjibpkEgUrgQQA\nCgIDBOUvn/oNKZnjEMtnAbB6hoos8vDf8mqyIbtGRjDil1T3t19q2Ke6xFFo\nJ+U2w4gtFxjDER8igas+ja4P3u7EFlMDAQgHwngEGBMIACoFAmOJumgJEMeC\n+tarHrkfAhsMFiEEuCfMj0KfpRqY2UnYx4L61qseuR8AANHPAP96lvwGT3A0\nNNz1WAr+Sn13mR3k8arfeqcvZ1FCmioMogD9GzJIaJlbAbdsRB4QnLkRcKJO\nnMH13PKq9qM6tg4UQFM=\n=SD0h\n-----END PGP PUBLIC KEY BLOCK-----\n',
},
onprem: {
test: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxk8EYqEU5hMFK4EEAAoCAwQDdbAIZrsblEXIavyg2go6p9oG0SqWTgFsdHTc\nBhqdIS/WjQ8pj75q+vLqFtV9hlImYGInsIWh97fsigzB2owyzRhoc20gPGhz\nbUB0ZXN0LmJpdGdvLmNvbT7ChAQTEwgAFQUCYqEU5wILCQIVCAIWAAIbAwIe\nAQAhCRCJNRsIDGunexYhBHRL5D/8nRM3opQnXok1GwgMa6d7tg8A/24A9awq\nSCJx7RddiUzFHcKhVvvo3R5N7bHaOGP3TP79AP0TavF2WzhUXmZSjt3IK23O\n7/aknbijVeq52ghbWb1SwsJ1BBATCAAGBQJioRTnACEJEAWuA35KJgtgFiEE\nZttLPR0KcYvjgvJCBa4DfkomC2BsrwD/Z+43zOw+WpfPHxe+ypyVog5fnOKl\nXwleH6zDvqUWmWkA/iaHC6ullYkSG4Mv68k6qbtgR/pms/X7rkfa0QQFJy5p\nzlMEYqEU5hIFK4EEAAoCAwSsLqmfonjMF3o0nZ5JHvLpmfTA1RIVDsAEoRON\ntZA6rAA23pGl6s3Iyt4/fX9Adzoh3EElOjMsgi8Aj3dFpuqiAwEIB8J4BBgT\nCAAJBQJioRTnAhsMACEJEIk1GwgMa6d7FiEEdEvkP/ydEzeilCdeiTUbCAxr\np3vM7AD9GPp6HhYNEh2VVCDtFSt14Bni5FVM5icpVDo6w9ibvWAA/2Ti3Jv4\nIhIxl81/wqAgqigIblrz6vjtagr9/ykXQCW3\n=skCo\n-----END PGP PUBLIC KEY BLOCK-----\n',
prod: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmE8EYqKKQRMFK4EEAAoCAwROWJbH3UCPdZTPEJXpPZcktwtDJwil4QHlXZELcUbF\nETboq/cY22w+uG0IlRypdbo6+sDuaeg3dfja2ioq6TtJtAVCaXRHb4iEBBMTCAAV\nBQJioopDAgsJAhUIAhYAAhsDAh4BACEJEFXOMjZat5vMFiEEFYS/Xvdht8iMtmyP\nVc4yNlq3m8ym1AD+P9clE3kj764YmrHDOcRPl/+tX2CoUD0rbdSYyJyfCwAA/As0\nF0UFbPzlxPSaZhV/jQxB+PsF4LViwDdh4V4pUtn9iQIzBBABCgAdFiEEycUshFXI\nDdIAN2jlMSDsLY9HGToFAmKqV5gACgkQMSDsLY9HGToeiA/+MQXgfcLlzvNwHhGJ\nkgpSsW3aj2GOA+lZPHAbLVRomltn5GI/5jtLLi0hdVrNr14yuI1K954+ezuAz2DN\nHfDWVihEQaaQ+54fzoy9w8RjGqL+lhgQa/3BrAvIRP/WPFyo9eZcaW+T35x+Es7Z\nqyK50Sc/vpkHtNJ8rVHW1Y1wwAZzuHqdsY2xp1bKeS1hn2NHJ4QRqXZTNUY2zu0M\n3jzCvFdgnqUJC9d/t92QdUAAsENgAIIrVn7qCHoQIrXKrGAO+DTVmSqJp3kkbDI8\nbhR6EeionE6uualIsOR8bx4FlBHLk5JGCtzLVQ8XO/a7+hbJK8eFGUWSRQWiuq/1\nm11+MEjT6jkYDALajbrwYgQSNnqri9kHnGl1jnkNm7r+1PS9lB+J2F/c/t0jQd1C\nsQwIDmrD9adrs6yczbuEB+1kjt8SzJq8SGGPI84hzubQBhIr15mHNw5PK/1zaXlR\nWI0Sc8gOBcQsZshIRmOAvdhQzjU1uV8rYa19WOxpHB/Bss59Gk8oZsQu5aQ7qQ2l\nFBlUnewgPPIkljTrUBZLHSSExoUsoobOTGjs59VvDS5Jdy7rvA7roY1qYG/Dca2t\n1fwTwYTehI/u98qr+4N4d472vdCOqKhmcnbmSYNH35Ig8640yuhq/0IYKWmL8cBS\nO+5E4uMK4iBxSGFjLpGLRK9McMq4UwRioopBEgUrgQQACgIDBCHnAGs6S2ol7gbm\nxtI53LDWufX/US+Q7iGPxHgLdQArsCnPn31duLqO3ekPauF24vUWdLnOHOJhIGSS\nj8HYjDwDAQgHiHgEGBMIAAkFAmKiikQCGwwAIQkQVc4yNlq3m8wWIQQVhL9e92G3\nyIy2bI9VzjI2WrebzKZXAPwPAp119kb5WBC1evOHnbdHCTSOX4TB1xXaHoCIqhX/\ncAD+NX7JLf4pMeTpDz1MZHZB+2lyTBxRMo432m4Z7366Vqc=\n=yDyI\n-----END PGP PUBLIC KEY BLOCK-----',
},
},
mpcv2: {
nitro: {
test: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxk8EZiF3CBMFK4EEAAoCAwQWD7Pa752fAl4z0PxfWVC05d89vfo80PyUQ3Er\nLXlhGLkik+NkAl/DBd8diN7i4kTvRoIo0xrHU+lZgdgt+ct5zRhoc20gPGhz\nbUB0ZXN0LmJpdGdvLmNvbT7ChAQTEwgANgUCZiF3CAILCQkQ5ycuezbbVOkC\nFQgCFgACGwMCHgEWIQRPr6GNiE7tRv0p4afnJy57NttU6QAAbAYA+wRvSLOa\ne0iREOx00HhYWP030GhN98BcZtehT9iTZMV8AP97Otkrtq6jby2f7PdEV7uv\nd4aikTa5BgnpKvl8yqL4ccKEBBATCAA2BQJmIXcKAgsJCRCZRBfch5MUcwIV\nCAIWAAIbAwIeARYhBAmXBS0TYEvmC/3L9JlEF9yHkxRzAABJ1wD+KyI1j9nu\nYWvDxwDB+JBGMt7mic77ajBOgaCabEZ0j1MA/2RCOiV2cOL3x1AOzosqofsh\niA1s9BpS14xAwrKJPwY+zlMEZiF3CBIFK4EEAAoCAwSgLs60kLzhHD3o1sDg\n0fQ/QHw6hgq9PQ5LvilUvuIGYDR79sPwrMuwy7wUcOQgJvwIOJHommDq5nj+\nKfgAtE6uAwEIB8KEBBgTCAA2BQJmIXcJAgsJCRDnJy57NttU6QIVCAIWAAIb\nDAIeARYhBE+voY2ITu1G/Snhp+cnLns221TpAADWmQD/bV9sBkwyYfYfJYTS\nqvTmubCesQDY5Ranv9wYvv7RiLQA/iwX6ZHwdbvQFVui0GrvV2iFaCHut1pn\nF4YCDqpUKidwzk8EZiF3CBMFK4EEAAoCAwTfm/HZxwvubP/rr2KOU88mkDL9\njcWjfQx1uFZ9mlIgMBV3++OgtkVE0eEe+lNWpwgksGOGrBWeQ3K0XRF0YlUp\nwsBKBBgTCAC8BQJmIXcJAgsJCRDnJy57NttU6QIVCAIWAAIbAgIeAYUgBBgT\nCAA2BQJmIXcJAgsJCRBrEMTq2oOYhgIVCAIWAAIbAgIeARYhBLFg1zIcwAmc\nRhGdOmsQxOrag5iGAAAxoAD/YNPhMmf3l4Qh7fprkmOjoU0CvFiiP+kcxTr9\nm9luVhUA/RvhIB4sqrAcSD7ZGVIQcEI14rdAFeok4Higz2cGf9R6FiEET6+h\njYhO7Ub9KeGn5ycuezbbVOkAAPnaAP0dYpya7EzvN5Q6RpIzqLFN9izyGt4Q\n6keZsvnVbW9qJAD9Fj7tAAMUbbstz/Kx9RY8qoIOFTuSwaeDXnJMrI9v84w=\n=uzVB\n-----END PGP PUBLIC KEY BLOCK-----\n',
prod: '',
},
onprem: {
test: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxk8EZiF3CBMFK4EEAAoCAwQWD7Pa752fAl4z0PxfWVC05d89vfo80PyUQ3Er\nLXlhGLkik+NkAl/DBd8diN7i4kTvRoIo0xrHU+lZgdgt+ct5zRhoc20gPGhz\nbUB0ZXN0LmJpdGdvLmNvbT7ChAQTEwgANgUCZiF3CAILCQkQ5ycuezbbVOkC\nFQgCFgACGwMCHgEWIQRPr6GNiE7tRv0p4afnJy57NttU6QAAbAYA+wRvSLOa\ne0iREOx00HhYWP030GhN98BcZtehT9iTZMV8AP97Otkrtq6jby2f7PdEV7uv\nd4aikTa5BgnpKvl8yqL4ccKEBBATCAA2BQJmIXcKAgsJCRCZRBfch5MUcwIV\nCAIWAAIbAwIeARYhBAmXBS0TYEvmC/3L9JlEF9yHkxRzAABJ1wD+KyI1j9nu\nYWvDxwDB+JBGMt7mic77ajBOgaCabEZ0j1MA/2RCOiV2cOL3x1AOzosqofsh\niA1s9BpS14xAwrKJPwY+zlMEZiF3CBIFK4EEAAoCAwSgLs60kLzhHD3o1sDg\n0fQ/QHw6hgq9PQ5LvilUvuIGYDR79sPwrMuwy7wUcOQgJvwIOJHommDq5nj+\nKfgAtE6uAwEIB8KEBBgTCAA2BQJmIXcJAgsJCRDnJy57NttU6QIVCAIWAAIb\nDAIeARYhBE+voY2ITu1G/Snhp+cnLns221TpAADWmQD/bV9sBkwyYfYfJYTS\nqvTmubCesQDY5Ranv9wYvv7RiLQA/iwX6ZHwdbvQFVui0GrvV2iFaCHut1pn\nF4YCDqpUKidwzk8EZiF3CBMFK4EEAAoCAwTfm/HZxwvubP/rr2KOU88mkDL9\njcWjfQx1uFZ9mlIgMBV3++OgtkVE0eEe+lNWpwgksGOGrBWeQ3K0XRF0YlUp\nwsBKBBgTCAC8BQJmIXcJAgsJCRDnJy57NttU6QIVCAIWAAIbAgIeAYUgBBgT\nCAA2BQJmIXcJAgsJCRBrEMTq2oOYhgIVCAIWAAIbAgIeARYhBLFg1zIcwAmc\nRhGdOmsQxOrag5iGAAAxoAD/YNPhMmf3l4Qh7fprkmOjoU0CvFiiP+kcxTr9\nm9luVhUA/RvhIB4sqrAcSD7ZGVIQcEI14rdAFeok4Higz2cGf9R6FiEET6+h\njYhO7Ub9KeGn5ycuezbbVOkAAPnaAP0dYpya7EzvN5Q6RpIzqLFN9izyGt4Q\n6keZsvnVbW9qJAD9Fj7tAAMUbbstz/Kx9RY8qoIOFTuSwaeDXnJMrI9v84w=\n=uzVB\n-----END PGP PUBLIC KEY BLOCK-----\n',
prod: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxk8EZmHyKBMFK4EEAAoCAwS+tBY/2P47G0mgYRhq90jK475f02f3f3W4VbKA\nSwd9s6aI5spk7GeYsjRvP6rBf4vFIjLj7Ty7K2V03rZPQc8bzQVCaXRHb8KE\nBBMTCAA2BQJmYfIpAgsJCRAKMB4ATA5V7QIVCAIWAAIbAwIeARYhBAIdflLB\nK4deHok+gQowHgBMDlXtAACRpAD/UUbTsFEkjt+CCJmVq2v5l6oocR9hXXkT\nzhRQKQIwSigA/RVvS2RsoZLkaL68GUHLy63XVHtG149pN3BYPwb63EcQwoQE\nEBMIADYFAmZh8ioCCwkJEFlh2DLM6IVNAhUIAhYAAhsDAh4BFiEEsb9f1VA0\n9rOLgFM+WWHYMszohU0AAFC8AP4wH0ndmzCSg2O/a+ZfqW2yA465BFvDM1ij\nvMtCJYSxzAD/RjcfDfkN4Ipjaa2LRuHxfHZbvgCgoOChsJLv4KQLTafOUwRm\nYfIoEgUrgQQACgIDBM+W01KEUaAm8a3hMBWG9EShyNrZxbtv9ryd8JIIxeEb\nEckLTVQvIer3YvDUyjeY/v83VCRdm6H5cahV92sydrIDAQgHwoQEGBMIADYF\nAmZh8ikCCwkJEAowHgBMDlXtAhUIAhYAAhsMAh4BFiEEAh1+UsErh14eiT6B\nCjAeAEwOVe0AAEcSAP9H96t/z9uKe9lAoq2d9Dt3Hrq9eM6sLQ2+cVblngP+\nDQD/dCqHYQzDdsuc9Y3HmWbhCK1Um6ewppkct1v5lmbaJ1bOTwRmYfIoEwUr\ngQQACgIDBJDIofWOLj/JkBFkZDh3a++LNEH8TBNlDZvU7tNfURXWApxV2VAb\nFBKYddN03Q1SBpMR0GkPl42rH7whYdeaEBHCwEoEGBMIALwFAmZh8ioCCwkJ\nEAowHgBMDlXtAhUIAhYAAhsCAh4BhSAEGBMIADYFAmZh8ioCCwkJEGAfBsMT\nFzVjAhUIAhYAAhsCAh4BFiEE2zAGHSaLnswqIvBrYB8GwxMXNWMAANroAP0f\ntFPumKFwQrCf7OMHQWsesrQYpKT6Z65VbewBoGaGigD/UkeeygTtlyzTV2YF\nNAjWAzaQtXWmmzRgnOj0IKub39MWIQQCHX5SwSuHXh6JPoEKMB4ATA5V7QAA\nTjMA/jDSVXJNblr/kSLNFTordgDjKP0nN1aElvFUFh/QEVT0AP9lmf2Fc/o7\nyYOGPPg4OvvU6odrTsuNgljvPqBlaCc2EA==\n=ZLkt\n-----END PGP PUBLIC KEY BLOCK-----\n',
},
},
};

export function getBitgoMpcGpgPubKey(
env: EnvironmentName,
pubKeyType: 'nitro' | 'onprem',
mpcVersion: 'mpcv1' | 'mpcv2'
): string {
assert(
mpcVersion in bitgoMpcGpgPubKeys,
`Invalid mpcVersion in getBitgoMpcGpgPubKey, got: ${mpcVersion}, expected: mpcv1 or mpcv2`
);
assert(
pubKeyType in bitgoMpcGpgPubKeys[mpcVersion],
`Invalid pubKeyType in getBitgoMpcGpgPubKey, got: ${pubKeyType}, expected: nitro or onprem`
);
if (env !== 'prod' && env !== 'test' && env !== 'staging' && env !== 'adminProd' && env !== 'adminTest') {
throw new Error('Invalid environment to get a BitGo MPC GPG public key');
}
if (env !== 'prod' && env !== 'adminProd') {
// default to test gpg keys if not in prod
env = 'test';
}
if (env === 'adminProd') {
env = 'prod';
}
if (pubKeyType === 'nitro' && env === 'prod' && mpcVersion === 'mpcv2') {
throw new Error('Nitro mpcv2 pub key is not available in production environments yet.');
}
if (pubKeyType !== 'nitro') {
// This will be the default key type
pubKeyType = 'onprem';
}
return bitgoMpcGpgPubKeys[mpcVersion][pubKeyType][env];
}

export function isBitgoMpcPubKey(key: string, mpcvVersion: 'mpcv1' | 'mpcv2'): boolean {
return Object.values(bitgoMpcGpgPubKeys[mpcvVersion]).some((envKeys) => Object.values(envKeys).includes(key));
}

export function envRequiresBitgoPubGpgKeyConfig(env: EnvironmentName): boolean {
return env === 'prod' || env === 'test' || env === 'staging' || env === 'adminProd' || env === 'adminTest';
}
1 change: 1 addition & 0 deletions modules/sdk-core/src/bitgo/tss/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import ECDSAMethods, { ECDSAMethodTypes, DKLSMethods } from './ecdsa';

export { EDDSAMethods, EDDSAMethodTypes, ECDSAMethods, ECDSAMethodTypes, DKLSMethods };
export { ShareKeyPosition } from './types';
export * as BitgoMpcGpgPubKeys from './bitgoPubKeys';

// exporting this types for backward compatibility.
/** @deprecated Use EDDSAMethods */
Expand Down
5 changes: 5 additions & 0 deletions modules/sdk-core/src/bitgo/utils/mpcUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { AddKeychainOptions, Keychain, KeyType } from '../keychain';
import { BackupProvider } from '../wallet';
import { encryptText, getBitgoGpgPubKey } from './opengpgUtils';
import { IntentRecipient, PopulatedIntent, PrebuildTransactionWithIntentOptions } from './tss/baseTypes';
import { envRequiresBitgoPubGpgKeyConfig, isBitgoMpcPubKey } from '../tss/bitgoPubKeys';

export interface MpcKeyShare {
publicShare: string;
Expand Down Expand Up @@ -52,6 +53,10 @@ export abstract class MpcUtils {
enterprise?: string
): Promise<Keychain> {
const bitgoKey = (await getBitgoGpgPubKey(this.bitgo)).mpcV1;
if (envRequiresBitgoPubGpgKeyConfig(this.bitgo.getEnv())) {
// Ensure the public key is one of the expected BitGo public keys when in test or prod.
assert(isBitgoMpcPubKey(bitgoKey.armor(), 'mpcv1'), 'Invalid BitGo GPG public key');
}
const encUserToBitGoMessage = await encryptText(userKeyShare.privateShare, bitgoKey);
const encBackupToBitGoMessage = await encryptText(backupKeyShare.privateShare, bitgoKey);

Expand Down
Loading

0 comments on commit d0d85f1

Please sign in to comment.