Skip to content

Commit 6c87b40

Browse files
committed
Merge remote-tracking branch 'origin/HSM-1513'
2 parents 1b2470e + e7dfa8e commit 6c87b40

3 files changed

Lines changed: 673 additions & 10 deletions

File tree

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

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ import { EcdsaMPCv2KeyGenSendFn, KeyGenSenderForEnterprise } from './ecdsaMPCv2K
5252
import { envRequiresBitgoPubGpgKeyConfig, isBitgoMpcPubKey } from '../../../tss/bitgoPubKeys';
5353

5454
export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
55+
private static readonly DKLS23_SIGNING_USER_GPG_KEY = 'DKLS23_SIGNING_USER_GPG_KEY';
56+
private static readonly DKLS23_SIGNING_ROUND1_STATE = 'DKLS23_SIGNING_ROUND1_STATE';
57+
private static readonly DKLS23_SIGNING_ROUND2_STATE = 'DKLS23_SIGNING_ROUND2_STATE';
58+
5559
/** @inheritdoc */
5660
async createKeychains(params: {
5761
passphrase: string;
@@ -968,17 +972,20 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
968972
* @param {string} bitgoPublicGpgKey - the BitGo public GPG key
969973
* @param {string} encryptedUserGpgPrvKey - the encrypted user GPG private key
970974
* @param {string} walletPassphrase - the wallet passphrase
975+
* @param {string} adata - the additional data to validate the GPG keys
971976
* @returns {Promise<{ bitgoGpgKey: pgp.Key; userGpgKey: pgp.SerializedKeyPair<string> }>} - the BitGo and user GPG keys
972977
*/
973978
private async getBitgoAndUserGpgKeys(
974979
bitgoPublicGpgKey: string,
975980
encryptedUserGpgPrvKey: string,
976-
walletPassphrase: string
981+
walletPassphrase: string,
982+
adata: string
977983
): Promise<{
978984
bitgoGpgKey: pgp.Key;
979985
userGpgKey: pgp.SerializedKeyPair<string>;
980986
}> {
981987
const bitgoGpgKey = await pgp.readKey({ armoredKey: bitgoPublicGpgKey });
988+
this.validateAdata(adata, encryptedUserGpgPrvKey, EcdsaMPCv2Utils.DKLS23_SIGNING_USER_GPG_KEY);
982989
const userDecryptedKey = await pgp.readKey({
983990
armoredKey: this.bitgo.decrypt({ input: encryptedUserGpgPrvKey, password: walletPassphrase }),
984991
});
@@ -999,15 +1006,18 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
9991006
* @returns void
10001007
* @throws {Error} if the adata or cyphertext is invalid
10011008
*/
1002-
private validateAdata(adata: string, cyphertext: string): void {
1009+
private validateAdata(adata: string, cyphertext: string, roundDomainSeparator: string): void {
10031010
let cypherJson;
10041011
try {
10051012
cypherJson = JSON.parse(cyphertext);
10061013
} catch (e) {
10071014
throw new Error('Failed to parse cyphertext to JSON, got: ' + cyphertext);
10081015
}
10091016
// using decodeURIComponent to handle special characters
1010-
if (decodeURIComponent(cypherJson.adata) !== decodeURIComponent(adata)) {
1017+
if (
1018+
decodeURIComponent(cypherJson.adata) !== decodeURIComponent(`${roundDomainSeparator}:${adata}`) &&
1019+
decodeURIComponent(cypherJson.adata) !== decodeURIComponent(adata)
1020+
) {
10111021
throw new Error('Adata does not match cyphertext adata');
10121022
}
10131023
}
@@ -1128,13 +1138,17 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
11281138
const userSignerBroadcastMsg1 = await userSigner.init();
11291139
const signatureShareRound1 = await getSignatureShareRoundOne(userSignerBroadcastMsg1, userGpgKey);
11301140
const session = userSigner.getSession();
1131-
const encryptedRound1Session = this.bitgo.encrypt({ input: session, password: walletPassphrase, adata });
1141+
const encryptedRound1Session = this.bitgo.encrypt({
1142+
input: session,
1143+
password: walletPassphrase,
1144+
adata: `${EcdsaMPCv2Utils.DKLS23_SIGNING_ROUND1_STATE}:${adata}`,
1145+
});
11321146

11331147
const userGpgPubKey = userGpgKey.publicKey;
11341148
const encryptedUserGpgPrvKey = this.bitgo.encrypt({
11351149
input: userGpgKey.privateKey,
11361150
password: walletPassphrase,
1137-
adata,
1151+
adata: `${EcdsaMPCv2Utils.DKLS23_SIGNING_USER_GPG_KEY}:${adata}`,
11381152
});
11391153

11401154
return { signatureShareRound1, userGpgPubKey, encryptedRound1Session, encryptedUserGpgPrvKey };
@@ -1159,7 +1173,8 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
11591173
const { bitgoGpgKey, userGpgKey } = await this.getBitgoAndUserGpgKeys(
11601174
bitgoPublicGpgKey,
11611175
encryptedUserGpgPrvKey,
1162-
walletPassphrase
1176+
walletPassphrase,
1177+
adata
11631178
);
11641179

11651180
const signatureShares = txRequest.transactions?.[0].signatureShares;
@@ -1176,9 +1191,9 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
11761191
bitgoGpgKey
11771192
);
11781193

1194+
this.validateAdata(adata, encryptedRound1Session, EcdsaMPCv2Utils.DKLS23_SIGNING_ROUND1_STATE);
11791195
const round1Session = this.bitgo.decrypt({ input: encryptedRound1Session, password: walletPassphrase });
11801196

1181-
this.validateAdata(adata, encryptedRound1Session);
11821197
const userKeyShare = Buffer.from(prv, 'base64');
11831198
const userSigner = new DklsDsg.Dsg(userKeyShare, 0, derivationPath, hashBuffer);
11841199
await userSigner.setSession(round1Session);
@@ -1199,7 +1214,11 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
11991214
bitgoGpgKey
12001215
);
12011216
const session = userSigner.getSession();
1202-
const encryptedRound2Session = this.bitgo.encrypt({ input: session, password: walletPassphrase, adata });
1217+
const encryptedRound2Session = this.bitgo.encrypt({
1218+
input: session,
1219+
password: walletPassphrase,
1220+
adata: `${EcdsaMPCv2Utils.DKLS23_SIGNING_ROUND2_STATE}:${adata}`,
1221+
});
12031222

12041223
return {
12051224
signatureShareRound2,
@@ -1227,7 +1246,8 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
12271246
const { bitgoGpgKey, userGpgKey } = await this.getBitgoAndUserGpgKeys(
12281247
bitgoPublicGpgKey,
12291248
encryptedUserGpgPrvKey,
1230-
walletPassphrase
1249+
walletPassphrase,
1250+
adata
12311251
);
12321252

12331253
const signatureShares = txRequest.transactions?.[0].signatureShares;
@@ -1249,8 +1269,9 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
12491269
broadcastMessages: [],
12501270
});
12511271

1272+
this.validateAdata(adata, encryptedRound2Session, EcdsaMPCv2Utils.DKLS23_SIGNING_ROUND2_STATE);
12521273
const round2Session = this.bitgo.decrypt({ input: encryptedRound2Session, password: walletPassphrase });
1253-
this.validateAdata(adata, encryptedRound2Session);
1274+
12541275
const userKeyShare = Buffer.from(prv, 'base64');
12551276
const userSigner = new DklsDsg.Dsg(userKeyShare, 0, derivationPath, hashBuffer);
12561277
await userSigner.setSession(round2Session);

0 commit comments

Comments
 (0)