Skip to content

Commit f2db18f

Browse files
feat(sdk-core): support hardcoding bitgo pgp keys in external signer
TICKET: HSM-432
1 parent 7dda747 commit f2db18f

File tree

4 files changed

+51
-21
lines changed

4 files changed

+51
-21
lines changed

modules/sdk-core/src/bitgo/utils/tss/baseTSSUtils.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,29 +69,41 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
6969
this.bitgoPublicGpgKey = mpcV1;
7070
this.bitgoMPCv2PublicGpgKey = mpcV2;
7171
}
72-
73-
protected async pickBitgoPubGpgKeyForSigning(isMpcv2: boolean, reqId: IRequestTracer, enterpriseId?: string): Promise<openpgp.Key> {
72+
73+
protected async pickBitgoPubGpgKeyForSigning(
74+
isMpcv2: boolean,
75+
reqId?: IRequestTracer,
76+
enterpriseId?: string
77+
): Promise<openpgp.Key> {
7478
let bitgoGpgPubKey;
7579
try {
76-
const bitgoKeyChain = await this.baseCoin.keychains().get({ id: this.wallet.keyIds()[KeyIndices.BITGO], reqId });
80+
const bitgoKeyChain = await this.baseCoin.keychains().get({ id: this.wallet.keyIds()[KeyIndices.BITGO], reqId });
7781
if (!bitgoKeyChain || !bitgoKeyChain.hsmType) {
7882
throw new Error('Missing Bitgo GPG Pub Key Type.');
7983
}
8084
bitgoGpgPubKey = await openpgp.readKey({
81-
armoredKey: getBitgoMpcGpgPubKey(this.bitgo.getEnv(), bitgoKeyChain.hsmType === 'nitro' ? 'nitro' : 'onprem', isMpcv2 ? 'mpcv2' : 'mpcv1'),
85+
armoredKey: getBitgoMpcGpgPubKey(
86+
this.bitgo.getEnv(),
87+
bitgoKeyChain.hsmType === 'nitro' ? 'nitro' : 'onprem',
88+
isMpcv2 ? 'mpcv2' : 'mpcv1'
89+
),
8290
});
8391
} catch (e) {
8492
if (!envRequiresBitgoPubGpgKeyConfig(this.bitgo.getEnv())) {
8593
console.warn(
8694
`Unable to get BitGo GPG key based on key data with error: ${e}. Fetching BitGo GPG key based on feature flags.`
8795
);
88-
bitgoGpgPubKey = await this.getBitgoGpgPubkeyBasedOnFeatureFlags(
89-
enterpriseId,
90-
isMpcv2,
91-
reqId
92-
).then(async (pubKey) => pubKey ?? (isMpcv2 ? await this.getBitgoMpcv2PublicGpgKey() : await this.getBitgoPublicGpgKey()));
96+
// First try to get the key based on feature flags, if that fails, fallback to the default key from constants api.
97+
bitgoGpgPubKey = await this.getBitgoGpgPubkeyBasedOnFeatureFlags(enterpriseId, isMpcv2, reqId)
98+
.then(
99+
async (pubKey) =>
100+
pubKey ?? (isMpcv2 ? await this.getBitgoMpcv2PublicGpgKey() : await this.getBitgoPublicGpgKey())
101+
)
102+
.catch(async (e) => (isMpcv2 ? await this.getBitgoMpcv2PublicGpgKey() : await this.getBitgoPublicGpgKey()));
93103
} else {
94-
throw new Error(`Environment "${this.bitgo.getEnv()}" requires a BitGo GPG Pub Key Config in BitGoJS for TSS. Error thrown while getting the key from config: ${e}`);
104+
throw new Error(
105+
`Environment "${this.bitgo.getEnv()}" requires a BitGo GPG Pub Key Config in BitGoJS for TSS. Error thrown while getting the key from config: ${e}`
106+
);
95107
}
96108
}
97109
return bitgoGpgPubKey;
@@ -119,7 +131,7 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
119131
}
120132

121133
return this.bitgoMPCv2PublicGpgKey;
122-
}
134+
}
123135

124136
async createBitgoHeldBackupKeyShare(
125137
userGpgKey: SerializedKeyPair<string>,
@@ -251,7 +263,12 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
251263
*
252264
* @returns {Promise<{ userToBitgoCommitment: CommitmentShareRecor, encryptedSignerShare: EncryptedSignerShareRecord }>} - Commitment Share and the Encrypted Signer Share to BitGo
253265
*/
254-
createCommitmentShareFromTxRequest(params: { txRequest: TxRequest; prv: string; walletPassphrase: string }): Promise<{
266+
createCommitmentShareFromTxRequest(params: {
267+
txRequest: TxRequest;
268+
prv: string;
269+
walletPassphrase: string;
270+
bitgoGpgPubKey: string;
271+
}): Promise<{
255272
userToBitgoCommitment: CommitmentShareRecord;
256273
encryptedSignerShare: EncryptedSignerShareRecord;
257274
encryptedUserToBitgoRShare: EncryptedSignerShareRecord;

modules/sdk-core/src/bitgo/utils/tss/baseTypes.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export interface CustomSShareGeneratingFunction {
8989
}
9090

9191
export interface CustomCommitmentGeneratingFunction {
92-
(params: { txRequest: TxRequest }): Promise<{
92+
(params: { txRequest: TxRequest; bitgoGpgPubKey?: string }): Promise<{
9393
userToBitgoCommitment: CommitmentShareRecord;
9494
encryptedSignerShare: EncryptedSignerShareRecord;
9595
encryptedUserToBitgoRShare: EncryptedSignerShareRecord;
@@ -592,7 +592,12 @@ export interface ITssUtils<KeyShare = EDDSA.KeyShare> {
592592
externalSignerMuDeltaShareGenerator: CustomMuDeltaShareGeneratingFunction,
593593
externalSignerSShareGenerator: CustomSShareGeneratingFunction
594594
): Promise<TxRequest>;
595-
createCommitmentShareFromTxRequest(params: { txRequest: TxRequest; prv: string; walletPassphrase: string }): Promise<{
595+
createCommitmentShareFromTxRequest(params: {
596+
txRequest: TxRequest;
597+
prv: string;
598+
walletPassphrase: string;
599+
bitgoGpgPubKey: string;
600+
}): Promise<{
596601
userToBitgoCommitment: CommitmentShareRecord;
597602
encryptedSignerShare: EncryptedSignerShareRecord;
598603
encryptedUserToBitgoRShare: EncryptedSignerShareRecord;

modules/sdk-core/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
6767
const bitgoPublicGpgKey = (
6868
(await this.getBitgoGpgPubkeyBasedOnFeatureFlags(params.enterprise, true)) ?? this.bitgoMPCv2PublicGpgKey
6969
).armor();
70-
70+
7171
if (envRequiresBitgoPubGpgKeyConfig(this.bitgo.getEnv())) {
7272
// Ensure the public key is one of the expected BitGo public keys when in test or prod.
7373
assert(isBitgoMpcPubKey(bitgoPublicGpgKey, 'mpcv2'), 'Invalid BitGo GPG public key');
@@ -1010,9 +1010,12 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
10101010
txRequestResolved = txRequest;
10111011
}
10121012

1013-
const bitgoPublicGpgKey =
1014-
(await this.getBitgoGpgPubkeyBasedOnFeatureFlags(txRequestResolved.enterpriseId, true, reqId)) ??
1015-
this.bitgoMPCv2PublicGpgKey;
1013+
const bitgoPublicGpgKey = await this.pickBitgoPubGpgKeyForSigning(
1014+
true,
1015+
params.reqId,
1016+
txRequestResolved.enterpriseId
1017+
);
1018+
10161019
if (!bitgoPublicGpgKey) {
10171020
throw new Error('Missing BitGo GPG key for MPCv2');
10181021
}

modules/sdk-core/src/bitgo/utils/tss/eddsa/eddsa.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ export class EddsaUtils extends baseTSSUtils<KeyShare> {
371371
txRequest: TxRequest;
372372
prv: string;
373373
walletPassphrase: string;
374+
bitgoGpgPubKey: string;
374375
}): Promise<{
375376
userToBitgoCommitment: CommitmentShareRecord;
376377
encryptedSignerShare: EncryptedSignerShareRecord;
@@ -408,8 +409,11 @@ export class EddsaUtils extends baseTSSUtils<KeyShare> {
408409
const userToBitgoCommitment = this.createUserToBitgoCommitmentShare(commitment);
409410

410411
const signerShare = signingKey.yShares[bitgoIndex].u + signingKey.yShares[bitgoIndex].chaincode;
411-
const bitgoGpgKey = (await getBitgoGpgPubKey(this.bitgo)).mpcV1;
412-
const userToBitgoEncryptedSignerShare = await encryptText(signerShare, bitgoGpgKey);
412+
413+
const userToBitgoEncryptedSignerShare = await encryptText(
414+
signerShare,
415+
await openpgp.readKey({ armoredKey: params.bitgoGpgPubKey })
416+
);
413417

414418
const encryptedSignerShare = this.createUserToBitgoEncryptedSignerShare(userToBitgoEncryptedSignerShare);
415419
const stringifiedRShare = JSON.stringify(userSignShare);
@@ -496,9 +500,10 @@ export class EddsaUtils extends baseTSSUtils<KeyShare> {
496500
}
497501

498502
const { apiVersion } = txRequestResolved;
503+
const bitgoGpgKey = await this.pickBitgoPubGpgKeyForSigning(false, reqId, txRequestResolved.enterpriseId);
499504

500505
const { userToBitgoCommitment, encryptedSignerShare, encryptedUserToBitgoRShare } =
501-
await externalSignerCommitmentGenerator({ txRequest: txRequestResolved });
506+
await externalSignerCommitmentGenerator({ txRequest: txRequestResolved, bitgoGpgPubKey: bitgoGpgKey.armor() });
502507

503508
const { commitmentShare: bitgoToUserCommitment } = await exchangeEddsaCommitments(
504509
this.bitgo,

0 commit comments

Comments
 (0)