Skip to content

Commit e3bc07c

Browse files
committed
feat: add round domain separator to adata
TICKET: HSM-1513
1 parent 75183ed commit e3bc07c

1 file changed

Lines changed: 31 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
@@ -51,6 +51,10 @@ import { EcdsaMPCv2KeyGenSendFn, KeyGenSenderForEnterprise } from './ecdsaMPCv2K
5151
import { envRequiresBitgoPubGpgKeyConfig, isBitgoMpcPubKey } from '../../../tss/bitgoPubKeys';
5252

5353
export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
54+
private static readonly DKLS23_SIGNING_USER_GPG_KEY = 'DKLS23_SIGNING_USER_GPG_KEY';
55+
private static readonly DKLS23_SIGNING_ROUND1_STATE = 'DKLS23_SIGNING_ROUND1_STATE';
56+
private static readonly DKLS23_SIGNING_ROUND2_STATE = 'DKLS23_SIGNING_ROUND2_STATE';
57+
5458
/** @inheritdoc */
5559
async createKeychains(params: {
5660
passphrase: string;
@@ -964,17 +968,20 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
964968
* @param {string} bitgoPublicGpgKey - the BitGo public GPG key
965969
* @param {string} encryptedUserGpgPrvKey - the encrypted user GPG private key
966970
* @param {string} walletPassphrase - the wallet passphrase
971+
* @param {string} adata - the additional data to validate the GPG keys
967972
* @returns {Promise<{ bitgoGpgKey: pgp.Key; userGpgKey: pgp.SerializedKeyPair<string> }>} - the BitGo and user GPG keys
968973
*/
969974
private async getBitgoAndUserGpgKeys(
970975
bitgoPublicGpgKey: string,
971976
encryptedUserGpgPrvKey: string,
972-
walletPassphrase: string
977+
walletPassphrase: string,
978+
adata: string
973979
): Promise<{
974980
bitgoGpgKey: pgp.Key;
975981
userGpgKey: pgp.SerializedKeyPair<string>;
976982
}> {
977983
const bitgoGpgKey = await pgp.readKey({ armoredKey: bitgoPublicGpgKey });
984+
this.validateAdata(adata, encryptedUserGpgPrvKey, EcdsaMPCv2Utils.DKLS23_SIGNING_USER_GPG_KEY);
978985
const userDecryptedKey = await pgp.readKey({
979986
armoredKey: this.bitgo.decrypt({ input: encryptedUserGpgPrvKey, password: walletPassphrase }),
980987
});
@@ -995,15 +1002,18 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
9951002
* @returns void
9961003
* @throws {Error} if the adata or cyphertext is invalid
9971004
*/
998-
private validateAdata(adata: string, cyphertext: string): void {
1005+
private validateAdata(adata: string, cyphertext: string, roundDomainSeparator: string): void {
9991006
let cypherJson;
10001007
try {
10011008
cypherJson = JSON.parse(cyphertext);
10021009
} catch (e) {
10031010
throw new Error('Failed to parse cyphertext to JSON, got: ' + cyphertext);
10041011
}
10051012
// using decodeURIComponent to handle special characters
1006-
if (decodeURIComponent(cypherJson.adata) !== decodeURIComponent(adata)) {
1013+
if (
1014+
decodeURIComponent(cypherJson.adata) !== decodeURIComponent(`${roundDomainSeparator}:${adata}`) &&
1015+
decodeURIComponent(cypherJson.adata) !== decodeURIComponent(adata)
1016+
) {
10071017
throw new Error('Adata does not match cyphertext adata');
10081018
}
10091019
}
@@ -1124,13 +1134,17 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
11241134
const userSignerBroadcastMsg1 = await userSigner.init();
11251135
const signatureShareRound1 = await getSignatureShareRoundOne(userSignerBroadcastMsg1, userGpgKey);
11261136
const session = userSigner.getSession();
1127-
const encryptedRound1Session = this.bitgo.encrypt({ input: session, password: walletPassphrase, adata });
1137+
const encryptedRound1Session = this.bitgo.encrypt({
1138+
input: session,
1139+
password: walletPassphrase,
1140+
adata: `${EcdsaMPCv2Utils.DKLS23_SIGNING_ROUND1_STATE}:${adata}`,
1141+
});
11281142

11291143
const userGpgPubKey = userGpgKey.publicKey;
11301144
const encryptedUserGpgPrvKey = this.bitgo.encrypt({
11311145
input: userGpgKey.privateKey,
11321146
password: walletPassphrase,
1133-
adata,
1147+
adata: `${EcdsaMPCv2Utils.DKLS23_SIGNING_USER_GPG_KEY}:${adata}`,
11341148
});
11351149

11361150
return { signatureShareRound1, userGpgPubKey, encryptedRound1Session, encryptedUserGpgPrvKey };
@@ -1155,7 +1169,8 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
11551169
const { bitgoGpgKey, userGpgKey } = await this.getBitgoAndUserGpgKeys(
11561170
bitgoPublicGpgKey,
11571171
encryptedUserGpgPrvKey,
1158-
walletPassphrase
1172+
walletPassphrase,
1173+
adata
11591174
);
11601175

11611176
const signatureShares = txRequest.transactions?.[0].signatureShares;
@@ -1172,9 +1187,9 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
11721187
bitgoGpgKey
11731188
);
11741189

1190+
this.validateAdata(adata, encryptedRound1Session, EcdsaMPCv2Utils.DKLS23_SIGNING_ROUND1_STATE);
11751191
const round1Session = this.bitgo.decrypt({ input: encryptedRound1Session, password: walletPassphrase });
11761192

1177-
this.validateAdata(adata, encryptedRound1Session);
11781193
const userKeyShare = Buffer.from(prv, 'base64');
11791194
const userSigner = new DklsDsg.Dsg(userKeyShare, 0, derivationPath, hashBuffer);
11801195
await userSigner.setSession(round1Session);
@@ -1195,7 +1210,11 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
11951210
bitgoGpgKey
11961211
);
11971212
const session = userSigner.getSession();
1198-
const encryptedRound2Session = this.bitgo.encrypt({ input: session, password: walletPassphrase, adata });
1213+
const encryptedRound2Session = this.bitgo.encrypt({
1214+
input: session,
1215+
password: walletPassphrase,
1216+
adata: `${EcdsaMPCv2Utils.DKLS23_SIGNING_ROUND2_STATE}:${adata}`,
1217+
});
11991218

12001219
return {
12011220
signatureShareRound2,
@@ -1223,7 +1242,8 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
12231242
const { bitgoGpgKey, userGpgKey } = await this.getBitgoAndUserGpgKeys(
12241243
bitgoPublicGpgKey,
12251244
encryptedUserGpgPrvKey,
1226-
walletPassphrase
1245+
walletPassphrase,
1246+
adata
12271247
);
12281248

12291249
const signatureShares = txRequest.transactions?.[0].signatureShares;
@@ -1245,8 +1265,9 @@ export class EcdsaMPCv2Utils extends BaseEcdsaUtils {
12451265
broadcastMessages: [],
12461266
});
12471267

1268+
this.validateAdata(adata, encryptedRound2Session, EcdsaMPCv2Utils.DKLS23_SIGNING_ROUND2_STATE);
12481269
const round2Session = this.bitgo.decrypt({ input: encryptedRound2Session, password: walletPassphrase });
1249-
this.validateAdata(adata, encryptedRound2Session);
1270+
12501271
const userKeyShare = Buffer.from(prv, 'base64');
12511272
const userSigner = new DklsDsg.Dsg(userKeyShare, 0, derivationPath, hashBuffer);
12521273
await userSigner.setSession(round2Session);

0 commit comments

Comments
 (0)