Skip to content

Commit

Permalink
feat(root): multisig eddsa root keys test
Browse files Browse the repository at this point in the history
test

WP-0000
  • Loading branch information
alebusse committed Feb 9, 2024
1 parent 52ca701 commit 7ea8c5b
Show file tree
Hide file tree
Showing 84 changed files with 555 additions and 410 deletions.
2 changes: 1 addition & 1 deletion examples/js/backup-key-creation.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const coin = 'btc';
// Create the wallet
Promise.coroutine(function* () {
// this function takes one parameter - seed - if you want to create from your own entropy (recommended)
const backupKey = bitgo.coin(coin).keychains().create();
const backupKey = yield bitgo.coin(coin).keychains().create();

console.log('BACK THIS UP: ');
console.log(`Pub - this is what you add in the browser under the I have a backup key option: ${backupKey.pub}`);
Expand Down
2 changes: 1 addition & 1 deletion examples/ts/backup-key-creation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ bitgo.register(coin, Tbtc.createInstance);
// Create the wallet
async function main() {
// this function takes one parameter - seed - if you want to create from your own entropy (recommended)
const backupKey = bitgo.coin(coin).keychains().create();
const backupKey = await bitgo.coin(coin).keychains().create();

console.log('BACK THIS UP: ');
console.log(`Pub - this is what you add in the browser under the I have a backup key option: ${backupKey.pub}`);
Expand Down
2 changes: 1 addition & 1 deletion modules/abstract-cosmos/src/cosmosCoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ export class CosmosCoin extends BaseCoin {
}

/** @inheritDoc **/
generateKeyPair(seed?: Buffer): KeyPair {
async generateKeyPair(seed?: Buffer): Promise<KeyPair> {
if (!seed) {
// An extended private key has both a normal 256 bit private key and a 256
// bit chain code, both of which must be random. 512 bits is therefore the
Expand Down
2 changes: 1 addition & 1 deletion modules/abstract-eth/src/abstractEthLikeCoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export abstract class AbstractEthLikeCoin extends BaseCoin {
return isValidEthAddress(address);
}

generateKeyPair(seed?: Buffer): KeyPair {
async generateKeyPair(seed?: Buffer): Promise<KeyPair> {
const extendedKey = bip32.fromSeed(seed || randomBytes(32));
const xpub = extendedKey.neutered().toBase58();

Expand Down
4 changes: 2 additions & 2 deletions modules/abstract-eth/src/abstractEthLikeNewCoins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2011,7 +2011,7 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
const walletPassphrase = buildParams.walletPassphrase;

const userKeychain = await this.keychains().get({ id: wallet.keyIds()[0] });
const userPrv = wallet.getUserPrv({ keychain: userKeychain, walletPassphrase });
const userPrv = await wallet.getUserPrv({ keychain: userKeychain, walletPassphrase });
const userPrvBuffer = bip32.fromBase58(userPrv).privateKey;
if (!userPrvBuffer) {
throw new Error('invalid userPrv');
Expand Down Expand Up @@ -2222,7 +2222,7 @@ export abstract class AbstractEthLikeNewCoins extends AbstractEthLikeCoin {
* @param {Buffer} seed
* @returns {KeyPair} object with generated pub and prv
*/
generateKeyPair(seed: Buffer): KeyPair {
async generateKeyPair(seed?: Buffer): Promise<KeyPair> {
if (!seed) {
// An extended private key has both a normal 256 bit private key and a 256
// bit chain code, both of which must be random. 512 bits is therefore the
Expand Down
2 changes: 1 addition & 1 deletion modules/abstract-utxo/src/abstractUtxoCoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1450,7 +1450,7 @@ export abstract class AbstractUtxoCoin extends BaseCoin {
* @param seed
* @returns {Object} object with generated pub and prv
*/
generateKeyPair(seed: Buffer): { pub: string; prv: string } {
async generateKeyPair(seed?: Buffer): Promise<{ pub: string; prv: string }> {
if (!seed) {
// An extended private key has both a normal 256 bit private key and a 256
// bit chain code, both of which must be random. 512 bits is therefore the
Expand Down
17 changes: 17 additions & 0 deletions modules/account-lib/test/resources/eddsaKeyDeriver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const data = {
seed: {
validSeed:
'e3e670f488500f300790bee3fc2fb075d82d279459fa53024168664aec73054f2f5a0abfcd5889100604b0c22a430c4f9e1ac92b43675ca7cef0f9550acd2afa',
expectedRootKeys: {
prv: 'rprvb047f0d8b29083e1933102983d3c611cbf3364039cf3c985730e242488936070:2f5a0abfcd5889100604b0c22a430c4f9e1ac92b43675ca7cef0f9550acd2afa:049aa12f8beaf88eb1a404e4fc5a7ad290accd5b6bb37fa497f2e3bd56fa5990',
pub: 'rpubf008e38df59581e2851939f035bebbb18755fcb9d3864eb2aaa22be060ede6:2f5a0abfcd5889100604b0c22a430c4f9e1ac92b43675ca7cef0f9550acd2afa',
},
},
rootKeys1: {
prv: 'rprvb00584090478b47d1d1bf45ee8bbd012ec3634ec5eb40fb944c22602daac8979:427b2e97eeab94519d08e651b48d3df9326e9b22615f7655ad8c256659ec45af:838b4de99dcaf2392cec3222b29146816b1d3dfc1a7cad0695959a53ec23fa77',
pub: 'rpub6b0de9d546d71d95a04a9cfe0b6b8cd2f5da4961c6170ff5e8b7d27098e3a909:427b2e97eeab94519d08e651b48d3df9326e9b22615f7655ad8c256659ec45af',
derivedPub: '8beba02ca52fcb799134bc5698ee7f2b9e4e254749ea6baa65d7ddfbab82e330',
derivedPrv:
'dd6122533efd21fece9248f54e82b812d16996b47726f8cadc2a20f1ddac89098beba02ca52fcb799134bc5698ee7f2b9e4e254749ea6baa65d7ddfbab82e330',
},
};
74 changes: 74 additions & 0 deletions modules/account-lib/test/unit/utils/eddsaKeyDeriver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import assert from 'assert';
import { EddsaKeyDeriver } from '@bitgo/sdk-core';
import { data } from '../../resources/eddsaKeyDeriver';

describe('EddsaKeyDeriver', () => {
describe('createRootKeys', () => {
it('should create root keys without seed', async () => {
const rootKeys = await EddsaKeyDeriver.createRootKeys();

assert.ok(rootKeys.prv);
assert.equal(rootKeys.prv.length, data.rootKeys1.prv.length);
assert.ok(rootKeys.prv.startsWith(EddsaKeyDeriver.ROOT_PRV_KEY_PREFIX));
assert.ok(rootKeys.pub);
assert.equal(rootKeys.pub.length, data.rootKeys1.pub.length);
assert.ok(rootKeys.pub.startsWith(EddsaKeyDeriver.ROOT_PUB_KEY_PREFIX));
});

it('should create root keys with seed', async () => {
const seed = Buffer.from(data.seed.validSeed, 'hex');
const rootKeys = await EddsaKeyDeriver.createRootKeys(seed);

assert.ok(rootKeys.prv);
assert.equal(rootKeys.prv, data.seed.expectedRootKeys.prv);
assert.ok(rootKeys.pub);
assert.equal(rootKeys.pub, data.seed.expectedRootKeys.pub);
});

it('should throw for invalid seed', async () => {
const seed = Buffer.from('asdf12f1', 'hex');

assert.rejects(
async () => {
await EddsaKeyDeriver.createRootKeys(seed);
},
{ message: 'Invalid seed' },
);
});
});

describe('deriveKeyWithSeed', () => {
const seed = 'seed123';
const expectedPath = 'm/999999/240510315/85914100';
it('should derive a pub key and path from for root public key with seed', async () => {
const rootPubKey = data.rootKeys1.pub;

const derivedKey = await EddsaKeyDeriver.deriveKeyWithSeed(rootPubKey, seed);

assert.equal(derivedKey.key.length, 64);
assert.equal(derivedKey.key, data.rootKeys1.derivedPub);
assert.equal(derivedKey.derivationPath, expectedPath);
});

it('should derive a private key and path from for root private key with seed', async () => {
const rootPrvKey = data.rootKeys1.prv;

const derivedKey = await EddsaKeyDeriver.deriveKeyWithSeed(rootPrvKey, seed);

assert.equal(derivedKey.key.length, 128);
assert.equal(derivedKey.key, data.rootKeys1.derivedPrv);
assert.equal(derivedKey.derivationPath, expectedPath);
});

it('should throw an error for invalid key format', async () => {
const invalidKey = 'invalid:key:format';

await assert.rejects(
async () => {
await EddsaKeyDeriver.deriveKeyWithSeed(invalidKey, seed);
},
{ message: 'Invalid key format' },
);
});
});
});
8 changes: 4 additions & 4 deletions modules/bitgo/test/ecdh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ describe('ECDH utils', () => {
});

describe('signMessageWithDerivedEcdhKey and verifyEcdhSignature', function () {
it('signMessageWithDerivedEcdhKey and verifyEcdhSignature are able to sign/verify the same message', function () {
it('signMessageWithDerivedEcdhKey and verifyEcdhSignature are able to sign/verify the same message', async function () {
const bitgo = TestBitGo.decorate(BitGo, { env: 'mock' });
const myEcdhKeychain = bitgo.keychains().create();
const myEcdhKeychain = await bitgo.keychains().create();
const message = {
ntilde: 'bla',
h1: 'bla',
Expand All @@ -56,9 +56,9 @@ describe('ECDH utils', () => {
});
});

it('verifyEcdhSignature fails if the message/signature or pub key is diff than the one used for signing', function () {
it('verifyEcdhSignature fails if the message/signature or pub key is diff than the one used for signing', async function () {
const bitgo = TestBitGo.decorate(BitGo, { env: 'mock' });
const myEcdhKeychain = bitgo.keychains().create();
const myEcdhKeychain = await bitgo.keychains().create();
const message = {
ntilde: 'bla',
h1: 'bla',
Expand Down
26 changes: 13 additions & 13 deletions modules/bitgo/test/integration/keychains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,18 @@ describe('Keychains', function () {
);
});

it('create', function () {
it('create', async function () {
// must use seed of at least 128 bits
// standard test vector taken from bip32 spec
const seed = Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex');
assert.equal(
keychains.create({ seed: seed }).xprv,
await keychains.create({ seed: seed }).xprv,
'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi'
);

// two keys created one after the other with no seed should have
// non-equivalent xprivs, i.e. check that the RNG is actually working.
assert.notEqual(keychains.create().xprv, keychains.create().xprv);
assert.notEqual(await keychains.create().xprv, await keychains.create().xprv);
});

it('deriveLocal', function () {
Expand Down Expand Up @@ -180,8 +180,8 @@ describe('Keychains', function () {
});
});

it('non existent keychain', function (done) {
const newKey = keychains.create();
it('non existent keychain', async function (done) {
const newKey = await keychains.create();
const options = {
xpub: newKey.xpub,
};
Expand All @@ -194,8 +194,8 @@ describe('Keychains', function () {

describe('Add', function () {
it('arguments', function () {
assert.throws(function () {
keychains.create('invalid');
assert.rejects(async function () {
await keychains.create('invalid');
});
assert.throws(function () {
keychains.add();
Expand All @@ -211,9 +211,9 @@ describe('Keychains', function () {
describe('public', function () {
let extendedKey;

before(function (done) {
before(async function (done) {
// Generate a new keychain
extendedKey = keychains.create();
extendedKey = await keychains.create();

bitgo.unlock({ otp: bitgo.testUserOTP() }, function (err) {
assert.equal(err, null);
Expand Down Expand Up @@ -249,9 +249,9 @@ describe('Keychains', function () {
describe('private', function () {
let extendedKey;

before(function () {
before(async function () {
// Generate a new keychain
extendedKey = keychains.create();
extendedKey = await keychains.create();
});

it('add', function (done) {
Expand Down Expand Up @@ -325,8 +325,8 @@ describe('Keychains', function () {
describe('Update', function () {
let newKey;

before(function () {
newKey = keychains.create();
before(async function () {
newKey = await keychains.create();
});

it('arguments', function () {
Expand Down
6 changes: 3 additions & 3 deletions modules/bitgo/test/integration/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,9 @@ describe('Wallet API', function () {
});
});

it('get sharing key for a user', function (done) {
it('get sharing key for a user', async function (done) {
const keychains = bitgo.keychains();
keychains.create();
await keychains.create();

bitgo.getSharingKey({ email: TestBitGo.TEST_SHARED_KEY_USER }).done(function (result) {
result.should.have.property('userId');
Expand Down Expand Up @@ -1370,7 +1370,7 @@ describe('Wallet API', function () {
});
});

it('spend from wallet with no unspents', function () {
it('spend from wallet with no unspents', async function () {
let wallet;

return bitgo
Expand Down
Loading

0 comments on commit 7ea8c5b

Please sign in to comment.