Skip to content

Commit 11a4ed5

Browse files
Merge pull request #6064 from BitGo/WP-4242/audit-key-method
feat(root): add key validation function
2 parents f4b146b + 1a885ab commit 11a4ed5

File tree

52 files changed

+841
-14
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+841
-14
lines changed

modules/abstract-cosmos/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
},
4040
"dependencies": {
4141
"@bitgo/sdk-core": "^35.0.0",
42+
"@bitgo/sdk-lib-mpc": "^10.3.0",
4243
"@bitgo/secp256k1": "^1.3.3",
4344
"@bitgo/statics": "^54.0.0",
4445
"@cosmjs/amino": "^0.29.5",

modules/abstract-cosmos/src/cosmosCoin.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
AuditDecryptedKeyParams,
23
BaseCoin,
34
BaseTransaction,
45
BitGoBase,
@@ -43,6 +44,7 @@ import {
4344
} from './lib';
4445
import { ROOT_PATH } from './lib/constants';
4546
import utils from './lib/utils';
47+
import { auditEcdsaPrivateKey } from '@bitgo/sdk-lib-mpc';
4648

4749
/**
4850
* Cosmos accounts support memo Id based addresses
@@ -665,4 +667,13 @@ export class CosmosCoin<CustomMessage = never> extends BaseCoin {
665667
getKeyPair(publicKey: string): CosmosKeyPair {
666668
throw new Error('Method not implemented');
667669
}
670+
671+
/** @inheritDoc **/
672+
auditDecryptedKey({ multiSigType, publicKey, prv }: AuditDecryptedKeyParams) {
673+
if (multiSigType !== 'tss') {
674+
throw new Error('Unsupported multiSigType');
675+
} else {
676+
auditEcdsaPrivateKey(prv as string, publicKey as string);
677+
}
678+
}
668679
}

modules/abstract-eth/src/abstractEthLikeCoin.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@ import { CoinFamily, BaseCoin as StaticsBaseCoin } from '@bitgo/statics';
66
import { bip32 } from '@bitgo/secp256k1';
77
import { randomBytes } from 'crypto';
88
import {
9+
AuditDecryptedKeyParams,
910
BaseCoin,
11+
bitcoin,
1012
BitGoBase,
1113
FullySignedTransaction,
1214
HalfSignedAccountTransaction,
15+
isValidPrv,
16+
isValidXprv,
1317
KeyPair,
1418
MethodNotImplementedError,
1519
ParsedTransaction,
@@ -25,6 +29,7 @@ import BigNumber from 'bignumber.js';
2529

2630
import { isValidEthAddress, KeyPair as EthKeyPair, TransactionBuilder } from './lib';
2731
import { VerifyEthAddressOptions } from './abstractEthLikeNewCoins';
32+
import { auditEcdsaPrivateKey } from '@bitgo/sdk-lib-mpc';
2833

2934
export interface EthSignTransactionOptions extends SignTransactionOptions {
3035
txPrebuild: TransactionPrebuild;
@@ -226,4 +231,21 @@ export abstract class AbstractEthLikeCoin extends BaseCoin {
226231
* @return a new transaction builder
227232
*/
228233
protected abstract getTransactionBuilder(common?: EthLikeCommon.default): TransactionBuilder;
234+
235+
/** @inheritDoc */
236+
auditDecryptedKey({ multiSigType, publicKey, prv }: AuditDecryptedKeyParams): void {
237+
if (multiSigType === 'tss') {
238+
auditEcdsaPrivateKey(prv as string, publicKey as string);
239+
} else {
240+
if (!isValidPrv(prv) && !isValidXprv(prv)) {
241+
throw new Error('Invalid private key');
242+
}
243+
if (publicKey) {
244+
const genPubKey = bitcoin.HDNode.fromBase58(prv).neutered().toBase58();
245+
if (genPubKey !== publicKey) {
246+
throw new Error('Incorrect xpub');
247+
}
248+
}
249+
}
250+
}
229251
}

modules/abstract-lightning/src/abstractLightningCoin.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
AuditDecryptedKeyParams,
23
BaseCoin,
34
BitGoBase,
45
KeyPair,
@@ -61,4 +62,9 @@ export abstract class AbstractLightningCoin extends BaseCoin {
6162
signTransaction(params: SignTransactionOptions): Promise<SignedTransaction> {
6263
throw new Error('Method not implemented.');
6364
}
65+
66+
/** @inheritDoc */
67+
auditDecryptedKey(params: AuditDecryptedKeyParams) {
68+
throw new Error('Method not implemented.');
69+
}
6470
}

modules/abstract-substrate/src/abstractSubstrateCoin.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
AuditDecryptedKeyParams,
23
BaseCoin,
34
BitGoBase,
45
EDDSAMethods,
@@ -27,7 +28,7 @@ import { KeyPair as SubstrateKeyPair, Transaction } from './lib';
2728
import { DEFAULT_SUBSTRATE_PREFIX } from './lib/constants';
2829
import { SignTransactionOptions, VerifiedTransactionParameters, Material } from './lib/iface';
2930
import utils from './lib/utils';
30-
import { getDerivationPath } from '@bitgo/sdk-lib-mpc';
31+
import { auditEddsaPrivateKey, getDerivationPath } from '@bitgo/sdk-lib-mpc';
3132
import BigNumber from 'bignumber.js';
3233
import { ApiPromise } from '@polkadot/api';
3334

@@ -519,4 +520,12 @@ export class SubstrateCoin extends BaseCoin {
519520
}
520521
return { transactions: broadcastableTransactions, lastScanIndex };
521522
}
523+
524+
/** inherited doc */
525+
auditDecryptedKey({ publicKey, prv, multiSigType }: AuditDecryptedKeyParams) {
526+
if (multiSigType !== 'tss') {
527+
throw new Error('Unsupported multiSigType');
528+
}
529+
auditEddsaPrivateKey(prv, publicKey ?? '');
530+
}
522531
}

modules/abstract-utxo/src/abstractUtxoCoin.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ import {
4444
VerifyAddressOptions as BaseVerifyAddressOptions,
4545
VerifyTransactionOptions as BaseVerifyTransactionOptions,
4646
Wallet,
47+
isValidPrv,
48+
isValidXprv,
49+
bitcoin,
4750
} from '@bitgo/sdk-core';
4851

4952
import {
@@ -1136,4 +1139,20 @@ export abstract class AbstractUtxoCoin extends BaseCoin {
11361139
getRecoveryProvider(apiToken?: string): RecoveryProvider {
11371140
return forCoin(this.getChain(), apiToken);
11381141
}
1142+
1143+
/** @inheritDoc */
1144+
auditDecryptedKey({ multiSigType, publicKey, prv }) {
1145+
if (multiSigType === 'tss') {
1146+
throw new Error('tss auditing is not supported for this coin');
1147+
}
1148+
if (!isValidPrv(prv) && !isValidXprv(prv)) {
1149+
throw new Error('invalid private key');
1150+
}
1151+
if (publicKey) {
1152+
const genPubKey = bitcoin.HDNode.fromBase58(prv).neutered().toBase58();
1153+
if (genPubKey !== publicKey) {
1154+
throw new Error('public key does not match private key');
1155+
}
1156+
}
1157+
}
11391158
}

modules/sdk-coin-ada/src/ada.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,14 @@ import {
3131
PrebuildTransactionWithIntentOptions,
3232
MultisigType,
3333
multisigTypes,
34+
AuditDecryptedKeyParams,
3435
} from '@bitgo/sdk-core';
3536
import { KeyPair as AdaKeyPair, Transaction, TransactionBuilderFactory, Utils } from './lib';
3637
import { BaseCoin as StaticsBaseCoin, CoinFamily, coins } from '@bitgo/statics';
3738
import adaUtils from './lib/utils';
3839
import * as request from 'superagent';
3940
import BigNumber from 'bignumber.js';
40-
import { getDerivationPath } from '@bitgo/sdk-lib-mpc';
41+
import { auditEddsaPrivateKey, getDerivationPath } from '@bitgo/sdk-lib-mpc';
4142

4243
export const DEFAULT_SCAN_FACTOR = 20; // default number of receive addresses to scan for funds
4344

@@ -628,4 +629,13 @@ export class Ada extends BaseCoin {
628629
intent.unspents = params.unspents;
629630
intent.senderAddress = params.senderAddress;
630631
}
632+
633+
/** inherited doc */
634+
auditDecryptedKey({ publicKey, prv, multiSigType }: AuditDecryptedKeyParams) {
635+
if (multiSigType !== 'tss') {
636+
throw new Error('Unsupported multiSigType');
637+
}
638+
639+
auditEddsaPrivateKey(prv, publicKey ?? '');
640+
}
631641
}

modules/sdk-coin-algo/src/algo.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
NotSupported,
3030
MultisigType,
3131
multisigTypes,
32+
AuditDecryptedKeyParams,
3233
} from '@bitgo/sdk-core';
3334
import stellar from 'stellar-sdk';
3435
import BigNumber from 'bignumber.js';
@@ -846,4 +847,23 @@ export class Algo extends BaseCoin {
846847
private getBuilder(): AlgoLib.TransactionBuilderFactory {
847848
return new AlgoLib.TransactionBuilderFactory(coins.get(this.getBaseChain()));
848849
}
850+
851+
/** @inheritDoc */
852+
auditDecryptedKey({ publicKey, prv, multiSigType }: AuditDecryptedKeyParams) {
853+
if (multiSigType === 'tss') {
854+
throw new Error('Unsupported multiSigType');
855+
}
856+
857+
let algoKey;
858+
try {
859+
algoKey = new AlgoLib.KeyPair({ prv });
860+
} catch (e) {
861+
throw new Error('Invalid private key');
862+
}
863+
if (publicKey && publicKey !== algoKey.getKeys().pub) {
864+
throw new Error('Invalid public key');
865+
}
866+
867+
return;
868+
}
849869
}

modules/sdk-coin-algo/test/unit/algo.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { AlgoLib, Talgo } from '../../src';
22
import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test';
3-
import { BitGoAPI } from '@bitgo/sdk-api';
3+
import { BitGoAPI, encrypt } from '@bitgo/sdk-api';
44
import * as AlgoResources from '../fixtures/algo';
55
import { randomBytes } from 'crypto';
66
import { coins } from '@bitgo/statics';
@@ -10,6 +10,7 @@ import { Algo } from '../../src/algo';
1010
import BigNumber from 'bignumber.js';
1111
import { TransactionBuilderFactory } from '../../src/lib';
1212
import { KeyPair } from '@bitgo/sdk-core';
13+
import { algoBackupKey } from './fixtures/algoBackupKey';
1314

1415
describe('ALGO:', function () {
1516
let bitgo: TestBitGoAPI;
@@ -1128,4 +1129,55 @@ describe('ALGO:', function () {
11281129
});
11291130
});
11301131
});
1132+
1133+
describe('AuditKey', () => {
1134+
const { key } = algoBackupKey;
1135+
const walletPassphrase = 'ZQ8MhxT84m4P';
1136+
1137+
it('should return for valid inputs', () => {
1138+
basecoin.assertIsValidKey({
1139+
encryptedPrv: key,
1140+
walletPassphrase,
1141+
});
1142+
});
1143+
1144+
it('should throw error if the walletPassphrase is incorrect', () => {
1145+
assert.throws(
1146+
() => {
1147+
basecoin.assertIsValidKey({
1148+
encryptedPrv: key,
1149+
walletPassphrase: 'foo',
1150+
});
1151+
},
1152+
{ message: "failed to decrypt prv: ccm: tag doesn't match" }
1153+
);
1154+
});
1155+
1156+
it('should throw error if the key is altered', () => {
1157+
const alteredKey = key.replace(/[0-9]/g, '0');
1158+
assert.throws(
1159+
() => {
1160+
basecoin.assertIsValidKey({
1161+
encryptedPrv: alteredKey,
1162+
walletPassphrase,
1163+
});
1164+
},
1165+
{ message: 'failed to decrypt prv: json decrypt: invalid parameters' }
1166+
);
1167+
});
1168+
1169+
it('should throw error if the key is not a valid key', () => {
1170+
const invalidKey = '#@)$#($*@)#($*';
1171+
const encryptedPrv = encrypt(walletPassphrase, invalidKey);
1172+
assert.throws(
1173+
() => {
1174+
basecoin.assertIsValidKey({
1175+
encryptedPrv,
1176+
walletPassphrase,
1177+
});
1178+
},
1179+
{ message: 'Invalid private key' }
1180+
);
1181+
});
1182+
});
11311183
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const algoBackupKey = {
2+
key:
3+
'{"iv":"ZdWrTtponn9Q4wK9VOkJdw==","v":1,"iter":10000,"ks":256,"ts":64,"mode"' +
4+
':"ccm","adata":"","cipher":"aes","salt":"dQ6rGI+qnmk=","ct":"Y4oLG6d+w3Apo+' +
5+
'nQdH2YfNcXZrA9RCrMw5M8r7GHgxsUoZ62ZHzhjk7CpOLi4YCFIwSf40pqShGrELQkA+VkGnFD"' +
6+
'}',
7+
};

modules/sdk-coin-apt/src/apt.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
AuditDecryptedKeyParams,
23
BaseCoin,
34
BaseTransaction,
45
BitGoBase,
@@ -21,6 +22,7 @@ import * as _ from 'lodash';
2122
import BigNumber from 'bignumber.js';
2223
import { ExplainTransactionOptions } from './lib/types';
2324
import { AptTransactionExplanation } from './lib/iface';
25+
import { auditEddsaPrivateKey } from '@bitgo/sdk-lib-mpc';
2426

2527
export interface AptParseTransactionOptions extends ParseTransactionOptions {
2628
txHex: string;
@@ -197,4 +199,12 @@ export class Apt extends BaseCoin {
197199
throw new Error('Failed to rebuild transaction');
198200
}
199201
}
202+
203+
/** @inheritDoc */
204+
auditDecryptedKey({ multiSigType, prv, publicKey }: AuditDecryptedKeyParams): void {
205+
if (multiSigType !== 'tss') {
206+
throw new Error('Unsupported multiSigType');
207+
}
208+
auditEddsaPrivateKey(prv, publicKey ?? '');
209+
}
200210
}

modules/sdk-coin-avaxp/src/avaxp.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {
1616
ParsedTransaction,
1717
MultisigType,
1818
multisigTypes,
19+
AuditDecryptedKeyParams,
20+
MethodNotImplementedError,
1921
} from '@bitgo/sdk-core';
2022
import * as AvaxpLib from './lib';
2123
import {
@@ -364,4 +366,9 @@ export class AvaxP extends BaseCoin {
364366
private getBuilder(): AvaxpLib.TransactionBuilderFactory {
365367
return new AvaxpLib.TransactionBuilderFactory(coins.get(this.getChain()));
366368
}
369+
370+
/** @inheritDoc */
371+
auditDecryptedKey(params: AuditDecryptedKeyParams): void {
372+
throw new MethodNotImplementedError();
373+
}
367374
}

0 commit comments

Comments
 (0)