UNPKG

bitgo

Version:
639 lines • 149 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const sdk_core_1 = require("@bitgo/sdk-core"); const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc"); const openpgp = require("openpgp"); const should = require("should"); const sdk_test_1 = require("@bitgo/sdk-test"); const src_1 = require("../../../../src"); const helpers_1 = require("./helpers"); const ecdsaFixtures_1 = require("../../fixtures/tss/ecdsaFixtures"); const nock = require("nock"); const encryptNShare = sdk_core_1.ECDSAMethods.encryptNShare; const createCombinedKey = sdk_core_1.ECDSAMethods.createCombinedKey; describe('Ecdsa tss helper functions tests', function () { let mpc; let userKeyShare; let backupKeyShare; let bitgoKeyShare; let userKey; let backupKey; let bitgoKey; let userGpgKeypair; let backupGpgKeypair; let bitgoGpgKeypair; let commonKeychain; before(async function () { mpc = new sdk_core_1.Ecdsa(); userKeyShare = ecdsaFixtures_1.keyShares.userKeyShare; backupKeyShare = ecdsaFixtures_1.keyShares.backupKeyShare; bitgoKeyShare = ecdsaFixtures_1.keyShares.bitgoKeyShare; userKey = mpc.keyCombine(userKeyShare.pShare, [backupKeyShare.nShares[1], bitgoKeyShare.nShares[1]]); backupKey = mpc.keyCombine(backupKeyShare.pShare, [userKeyShare.nShares[2], bitgoKeyShare.nShares[2]]); bitgoKey = mpc.keyCombine(bitgoKeyShare.pShare, [backupKeyShare.nShares[3], userKeyShare.nShares[3]]); (userKey.xShare.y + userKey.xShare.chaincode).should.equal(backupKey.xShare.y + backupKey.xShare.chaincode); (userKey.xShare.y + userKey.xShare.chaincode).should.equal(bitgoKey.xShare.y + bitgoKey.xShare.chaincode); commonKeychain = userKey.xShare.y + userKey.xShare.chaincode; const gpgKeypairPromises = [ { name: 'user', email: 'user@bitgo.com' }, { name: 'backup', email: 'backup@bitgo.com' }, { name: 'bitgo', email: 'bitgo@bitgo.com' }, ].map(async (user) => { return openpgp.generateKey({ userIDs: [ { name: user.name, email: user.email, }, ], curve: 'secp256k1', }); }); const gpgKeypairs = await Promise.all(gpgKeypairPromises); userGpgKeypair = gpgKeypairs[0]; backupGpgKeypair = gpgKeypairs[1]; bitgoGpgKeypair = gpgKeypairs[2]; }); after(function () { nock.cleanAll(); }); describe('encryptNShare and decryptNShare', function () { after(function () { nock.cleanAll(); }); it('should encrypt n shares foreach user', async function () { for (let i = 2; i <= 3; i++) { const encryptedNShare = await sdk_core_1.ECDSAMethods.encryptNShare(userKeyShare, i, bitgoGpgKeypair.publicKey, userGpgKeypair); const decryptedNShare = await sdk_core_1.ECDSAMethods.decryptNShare({ nShare: encryptedNShare, senderPublicArmor: userGpgKeypair.publicKey, recipientPrivateArmor: bitgoGpgKeypair.privateKey, }); decryptedNShare.u.should.equal(userKeyShare.nShares[i].u); const publicKey = userKeyShare.pShare.y + userKeyShare.pShare.chaincode; encryptedNShare.i.should.equal(i); encryptedNShare.vssProof.should.equal(userKeyShare.nShares[3].v); encryptedNShare.j.should.equal(1); encryptedNShare.publicShare.should.equal(publicKey); } }); it('should error for invalid recipient', async function () { await encryptNShare(userKeyShare, 1, userGpgKeypair.privateKey, userGpgKeypair).should.be.rejectedWith('Invalid recipient'); await encryptNShare(backupKeyShare, 2, userGpgKeypair.privateKey, userGpgKeypair).should.be.rejectedWith('Invalid recipient'); await encryptNShare(bitgoKeyShare, 3, userGpgKeypair.privateKey, userGpgKeypair).should.be.rejectedWith('Invalid recipient'); }); it('should decrypt n share', async function () { const encryptedNShare = await sdk_core_1.ECDSAMethods.encryptNShare(userKeyShare, 3, bitgoGpgKeypair.publicKey, userGpgKeypair); const decryptedNShare = await sdk_core_1.ECDSAMethods.decryptNShare({ nShare: encryptedNShare, recipientPrivateArmor: bitgoGpgKeypair.privateKey, senderPublicArmor: userGpgKeypair.publicKey, }); decryptedNShare.i.should.equal(userKeyShare.nShares[3].i); decryptedNShare.j.should.equal(userKeyShare.nShares[3].j); decryptedNShare.n.should.equal(userKeyShare.nShares[3].n); decryptedNShare.u.should.equal(userKeyShare.nShares[3].u); decryptedNShare.y.should.equal(userKeyShare.nShares[3].y); }); }); describe('createCombinedKey', function () { after(function () { nock.cleanAll(); }); it('should create combined user key', async function () { const bitgoToUserShare = await sdk_core_1.ECDSAMethods.encryptNShare(bitgoKeyShare, 1, userGpgKeypair.publicKey, userGpgKeypair, false); const backupToUserShare = await sdk_core_1.ECDSAMethods.encryptNShare(backupKeyShare, 1, userGpgKeypair.publicKey, userGpgKeypair, false); const combinedUserKey = await createCombinedKey(userKeyShare, [ { nShare: bitgoToUserShare, recipientPrivateArmor: userGpgKeypair.privateKey, senderPublicArmor: bitgoGpgKeypair.publicKey, isbs58Encoded: false, }, { nShare: backupToUserShare, recipientPrivateArmor: userGpgKeypair.privateKey, senderPublicArmor: backupGpgKeypair.publicKey, isbs58Encoded: false, }, ], commonKeychain); combinedUserKey.commonKeychain.should.equal(commonKeychain); combinedUserKey.signingMaterial.pShare.should.deepEqual(userKeyShare.pShare); should.exist(combinedUserKey.signingMaterial.backupNShare); combinedUserKey.signingMaterial.backupNShare?.should.deepEqual(backupKeyShare.nShares[1]); combinedUserKey.signingMaterial.bitgoNShare.should.deepEqual(bitgoKeyShare.nShares[1]); should.not.exist(combinedUserKey.signingMaterial.userNShare); }); it('should create combined backup key', async function () { const bitgoToBackupShare = await encryptNShare(bitgoKeyShare, 2, backupGpgKeypair.publicKey, userGpgKeypair); const userToBackupShare = await encryptNShare(userKeyShare, 2, backupGpgKeypair.publicKey, userGpgKeypair); const combinedBackupKey = await createCombinedKey(backupKeyShare, [ { nShare: bitgoToBackupShare, recipientPrivateArmor: backupGpgKeypair.privateKey, senderPublicArmor: bitgoGpgKeypair.publicKey, }, { nShare: userToBackupShare, recipientPrivateArmor: backupGpgKeypair.privateKey, senderPublicArmor: userGpgKeypair.publicKey, }, ], commonKeychain); combinedBackupKey.commonKeychain.should.equal(commonKeychain); combinedBackupKey.signingMaterial.pShare.should.deepEqual(backupKeyShare.pShare); should.exist(combinedBackupKey.signingMaterial.userNShare); combinedBackupKey.signingMaterial.userNShare?.should.deepEqual(userKeyShare.nShares[2]); combinedBackupKey.signingMaterial.bitgoNShare.should.deepEqual(bitgoKeyShare.nShares[2]); should.not.exist(combinedBackupKey.signingMaterial.backupNShare); }); it('should fail if common keychains do not match', async function () { const bitgoToUserShare = await encryptNShare(bitgoKeyShare, 1, userGpgKeypair.publicKey, userGpgKeypair); const backupToUserShare = await encryptNShare(backupKeyShare, 1, userGpgKeypair.publicKey, userGpgKeypair); // this should fail to combine the keys because we pass in invalid common key chain await createCombinedKey(userKeyShare, [ { nShare: bitgoToUserShare, recipientPrivateArmor: userGpgKeypair.privateKey, senderPublicArmor: bitgoGpgKeypair.publicKey, }, { nShare: backupToUserShare, recipientPrivateArmor: userGpgKeypair.privateKey, senderPublicArmor: backupGpgKeypair.publicKey, }, ], 'nottherightkeychain').should.be.rejectedWith('Common keychains do not match'); }); it('should fail if gpg keys are mismatched', async function () { const bitgoToUserShare = await encryptNShare(bitgoKeyShare, 1, userGpgKeypair.publicKey, userGpgKeypair); const backupToUserShare = await encryptNShare(backupKeyShare, 1, userGpgKeypair.publicKey, userGpgKeypair); await createCombinedKey(userKeyShare, [ { nShare: bitgoToUserShare, recipientPrivateArmor: backupGpgKeypair.privateKey, senderPublicArmor: bitgoGpgKeypair.publicKey, }, { nShare: backupToUserShare, recipientPrivateArmor: userGpgKeypair.privateKey, senderPublicArmor: backupGpgKeypair.publicKey, }, ], 'nottherightkeychain').should.be.rejectedWith('Error decrypting message: Session key decryption failed.'); }); }); describe('tss signing helper function', async function () { const bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' }); bitgo.initializeTestVars(); let wallet; const txRequest = { txRequestId: 'randomId', unsignedTxs: [{ signableHex: 'TOO MANY SECRETS', serializedTxHex: 'randomhex2' }], signatureShares: [ { from: 'bitgo', to: 'user', share: '', }, ], }; const signablePayload = Buffer.from(txRequest.unsignedTxs[0].signableHex, 'hex'); before('initializes', async function () { const baseCoin = bitgo.coin('hteth'); const walletData = { id: '5b34252f1bf349930e34020a00000000', coin: 'hteth', keys: [ '5b3424f91bf349930e34017500000000', '5b3424f91bf349930e34017600000000', '5b3424f91bf349930e34017700000000', ], coinSpecific: {}, }; wallet = new sdk_core_1.Wallet(bitgo, baseCoin, walletData); }); describe('createUserSignShare:', async function () { let userToBitGoPaillierChallenge; let bitgoToUserPaillierChallenge; before(async function () { userToBitGoPaillierChallenge = sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: await sdk_lib_mpc_1.EcdsaPaillierProof.generateP((0, sdk_core_1.hexToBigInt)(userKey.yShares[3].n)), }); bitgoToUserPaillierChallenge = sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: await sdk_lib_mpc_1.EcdsaPaillierProof.generateP((0, sdk_core_1.hexToBigInt)(userKey.xShare.n)), }); }); it('should succeed to create User SignShare', async function () { const xShare = mpc.appendChallenge(userKey.xShare, sdk_test_1.mockSerializedChallengeWithProofs, userToBitGoPaillierChallenge); const yShare = mpc.appendChallenge(userKey.yShares[3], { ntilde: xShare.ntilde, h1: xShare.h1, h2: xShare.h2 }, bitgoToUserPaillierChallenge); const userSignShare = await sdk_core_1.ECDSAMethods.createUserSignShare(xShare, yShare); userSignShare.should.have.properties(['wShare', 'kShare']); const { wShare, kShare } = userSignShare; wShare.should.have.property('gamma').and.be.a.String(); wShare.should.have.property('w').and.be.a.String(); wShare.should.have.property('k').and.be.a.String(); wShare.should.have.property('ck').and.be.a.String(); wShare.should.have.property('h2').and.be.a.String(); wShare.should.have.property('h1').and.be.a.String(); wShare.should.have.property('ntilde').and.be.a.String(); wShare.should.have.property('y').and.be.a.String(); wShare.should.have.property('n').and.be.a.String(); wShare.should.have.property('m').and.be.a.String(); wShare.should.have.property('l').and.be.a.String(); wShare.should.have.property('i').and.be.a.Number(); kShare['i'].should.equal(3); kShare['j'].should.equal(1); kShare.should.have.property('n').and.be.a.String(); kShare.should.have.property('k').and.be.a.String(); kShare.should.have.property('ntilde').and.be.a.String(); kShare.should.have.property('h1').and.be.a.String(); kShare.should.have.property('h2').and.be.a.String(); }); it('should fail if the Xshare doesnt belong to the User', async function () { let xShare = mpc.appendChallenge(userKey.xShare, sdk_test_1.mockSerializedChallengeWithProofs, userToBitGoPaillierChallenge); xShare = { ...xShare, i: 3 }; const yShare = mpc.appendChallenge(userKey.yShares[3], { ntilde: xShare.ntilde, h1: xShare.h1, h2: xShare.h2, }, bitgoToUserPaillierChallenge); await sdk_core_1.ECDSAMethods.createUserSignShare(xShare, yShare).should.be.rejectedWith(`Invalid XShare, XShare doesn't belong to the User`); }); }); describe('createUserGammaAndMuShare:', async function () { it('should succeed to create User Gamma Share and MuShare', async function () { const userShare = await sdk_core_1.ECDSAMethods.createUserGammaAndMuShare(ecdsaFixtures_1.gammaAndMuShareCreationParams.wShare, ecdsaFixtures_1.gammaAndMuShareCreationParams.aShare); userShare.should.have.properties(['muShare', 'gShare']); const { muShare, gShare } = userShare; muShare?.i?.should.equal(3); muShare?.j?.should.equal(1); muShare?.should.have.property('alpha').and.be.a.String(); muShare?.should.have.property('mu').and.be.a.String(); gShare?.should.have.property('beta').and.be.a.String(); gShare?.should.have.property('nu').and.be.a.String(); }); it('should fail if the Wshare / AShare doesnt belong to the User', async function () { const invalidWShare = { ...ecdsaFixtures_1.gammaAndMuShareCreationParams.wShare, i: 3 }; const invalidAShare = { ...ecdsaFixtures_1.gammaAndMuShareCreationParams.aShare, i: 3 }; await sdk_core_1.ECDSAMethods.createUserGammaAndMuShare(invalidWShare, ecdsaFixtures_1.gammaAndMuShareCreationParams.aShare).should.be.rejectedWith(`Invalid WShare, doesn't belong to the User`); await sdk_core_1.ECDSAMethods.createUserGammaAndMuShare(ecdsaFixtures_1.gammaAndMuShareCreationParams.wShare, invalidAShare).should.be.rejectedWith(`Invalid AShare, is not from Bitgo to User`); }); }); describe('createUserOmicronAndDeltaShare:', async function () { it('should succeed to create User Omicron and Mu Shares', async function () { const userShare = await sdk_core_1.ECDSAMethods.createUserOmicronAndDeltaShare(ecdsaFixtures_1.omicronAndDeltaShareCreationParams.gShare); userShare.should.have.properties(['dShare', 'oShare']); const { dShare, oShare } = userShare; dShare?.i?.should.equal(3); dShare?.j?.should.equal(1); dShare?.should.have.property('delta').and.be.a.String(); dShare?.should.have.property('Gamma').and.be.a.String(); oShare?.should.have.property('omicron').and.be.a.String(); oShare?.should.have.property('delta').and.be.a.String(); }); it(`should fail if the gShare doesn't belong to the User`, async function () { const invalidGShare = { ...ecdsaFixtures_1.omicronAndDeltaShareCreationParams.gShare, i: 3 }; await sdk_core_1.ECDSAMethods.createUserOmicronAndDeltaShare(invalidGShare).should.be.rejectedWith(`Invalid GShare, doesn't belong to the User`); }); }); describe('createUserSignatureShare:', async function () { afterEach(function () { nock.cleanAll(); }); it('should succeed to create User Signature Share', async function () { const userSignatureShare = await sdk_core_1.ECDSAMethods.createUserSignatureShare(ecdsaFixtures_1.createUserSignatureParams.oShare, ecdsaFixtures_1.createUserSignatureParams.dShare, signablePayload); const { R, s, y, i } = userSignatureShare; i.should.be.Number(); R.should.be.a.String(); s.should.be.a.String(); y.should.be.a.String(); }); it(`should fail if the OShare / dShare doesn't belong to the User`, async function () { const invalidOShare = { ...ecdsaFixtures_1.createUserSignatureParams.oShare, i: 3 }; await sdk_core_1.ECDSAMethods.createUserSignatureShare(invalidOShare, ecdsaFixtures_1.createUserSignatureParams.dShare, signablePayload).should.be.rejectedWith(`Invalid OShare, doesn't belong to the User`); const invalidDShare = { ...ecdsaFixtures_1.createUserSignatureParams.dShare, i: 3 }; await sdk_core_1.ECDSAMethods.createUserSignatureShare(ecdsaFixtures_1.createUserSignatureParams.oShare, invalidDShare, signablePayload).should.be.rejectedWith(`Invalid DShare, doesn't seem to be from BitGo`); }); }); describe('sendSignatureShare Tests', async function () { afterEach(function () { nock.cleanAll(); }); const mockAShareString = sdk_core_1.ECDSAMethods.convertAShare(ecdsaFixtures_1.mockAShare).share; const mockDShareString = sdk_core_1.ECDSAMethods.convertDShare(ecdsaFixtures_1.mockDShare).share; const config = [ { shareToSend: 'KShare', mockShareToSend: ecdsaFixtures_1.mockSignRT.kShare, mockShareToSendString: sdk_core_1.ECDSAMethods.convertKShare(ecdsaFixtures_1.mockSignRT.kShare).share, sendType: sdk_core_1.ECDSAMethodTypes.SendShareType.KShare, mockShareAsResponse: ecdsaFixtures_1.mockAShare, mockShareAsResponseString: mockAShareString, shareReceived: 'AShare', incorrectReceivedShareString: ecdsaFixtures_1.mockAShare.k, signerShare: 'a valid signer share', }, { shareToSend: 'MUShare', mockShareToSend: { muShare: ecdsaFixtures_1.mockMuShare, dShare: ecdsaFixtures_1.mockDShareToBitgo, i: ecdsaFixtures_1.mockMuShare.i }, mockShareToSendString: `${sdk_core_1.ECDSAMethods.convertMuShare(ecdsaFixtures_1.mockMuShare).share}${sdk_core_1.ECDSAMethods.secondaryDelimeter}${sdk_core_1.ECDSAMethods.convertDShare(ecdsaFixtures_1.mockDShareToBitgo).share}`, sendType: sdk_core_1.ECDSAMethodTypes.SendShareType.MUShare, mockShareAsResponse: ecdsaFixtures_1.mockDShare, mockShareAsResponseString: mockDShareString, shareReceived: 'DShare', incorrectReceivedShareString: ecdsaFixtures_1.mockDShare.Gamma, }, ]; for (let index = 0; index < config.length; index++) { describe(`sendSignatureShare: ${config[index].shareToSend}`, async function () { it(`should succeed to send ${config[index].shareToSend}`, async function () { const mockSendReq = { from: 'user', to: 'bitgo', share: config[index].mockShareToSendString, }; const shareRecord = { from: 'bitgo', to: 'user', share: config[index].mockShareAsResponseString, }; await (0, helpers_1.nockSendSignatureShare)({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, signatureShare: mockSendReq, response: shareRecord, tssType: 'ecdsa', signerShare: config[index].signerShare, }); txRequest.signatureShares = [shareRecord]; const response = { txRequests: [{ transactions: [{ ...txRequest }] }] }; await (0, helpers_1.nockGetTxRequest)({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response: response }); const responseAShare = await sdk_core_1.ECDSAMethods.sendShareToBitgo(bitgo, wallet.id(), txRequest.txRequestId, sdk_core_1.RequestType.tx, config[index].sendType, config[index].mockShareToSend, config[index].signerShare); responseAShare.should.deepEqual(config[index].mockShareAsResponse); }); it(`should fail if we get an invalid ${config[index].shareReceived} as response`, async function () { const mockSendReq = { from: 'user', to: 'bitgo', share: config[index].mockShareToSendString, }; const invalidSignatureShare = { from: 'bitgo', to: 'user', share: JSON.stringify(config[index].incorrectReceivedShareString), }; const nock = await (0, helpers_1.nockSendSignatureShare)({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, signatureShare: mockSendReq, response: invalidSignatureShare, tssType: 'ecdsa', signerShare: config[index].signerShare, }, 200); txRequest.signatureShares = [invalidSignatureShare]; const response = { txRequests: [{ transactions: [{ ...txRequest }] }] }; await (0, helpers_1.nockGetTxRequest)({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response: response }); await sdk_core_1.ECDSAMethods.sendShareToBitgo(bitgo, wallet.id(), txRequest.txRequestId, sdk_core_1.RequestType.tx, config[index].sendType, config[index].mockShareToSend, config[index].signerShare).should.be.rejectedWith(/Invalid .* share/g); // `Invalid ${shareName} share` nock.isDone().should.equal(true); }); }); } }); describe('getTxRequest:', async function () { afterEach(function () { nock.cleanAll(); }); it('should succeed to get txRequest by id', async function () { const response = { txRequests: [txRequest] }; const nock = await (0, helpers_1.nockGetTxRequest)({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response }); const txReq = await (0, sdk_core_1.getTxRequest)(bitgo, wallet.id(), txRequest.txRequestId); txReq.should.deepEqual(txRequest); nock.isDone().should.equal(true); }); it('should fail if there are no txRequests', async function () { const response = { txRequests: [] }; const nock = await (0, helpers_1.nockGetTxRequest)({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response }); await (0, sdk_core_1.getTxRequest)(bitgo, wallet.id(), txRequest.txRequestId).should.be.rejectedWith('Unable to find TxRequest with id randomId'); nock.isDone().should.equal(true); }); }); describe('signing share parsers and converters', function () { afterEach(function () { nock.cleanAll(); }); it('should successfully parse K share', function () { const bitgoKShare = ecdsaFixtures_1.mockSignWithPaillierChallengeRT.kShare; const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.USER, share: sdk_core_1.ECDSAMethods.convertKShare(ecdsaFixtures_1.mockSignWithPaillierChallengeRT.kShare).share, }; const kShare = sdk_core_1.ECDSAMethods.parseKShare(share); kShare.should.deepEqual(bitgoKShare); }); it('should successfully convert K share to signature share record', function () { const bitgoKShare = ecdsaFixtures_1.mockSignWithPaillierChallengeRT.kShare; const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.USER, share: `${ecdsaFixtures_1.mockSignRT.kShare.k}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSignRT.kShare.n}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSignRT.kShare.ntilde}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSignRT.kShare.h1}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSignRT.kShare.h2}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSignRT.kShare.proof?.z || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSignRT.kShare.proof?.u || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSignRT.kShare.proof?.w || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSignRT.kShare.proof?.s || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSignRT.kShare.proof?.s1 || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSignRT.kShare.proof?.s2 || ''}${sdk_core_1.ECDSAMethods.delimeter}${bitgoKShare.p.join(sdk_core_1.ECDSAMethods.delimeter)}${sdk_core_1.ECDSAMethods.delimeter}${bitgoKShare.sigma.join(sdk_core_1.ECDSAMethods.delimeter)}`, }; const kshare = sdk_core_1.ECDSAMethods.convertKShare(bitgoKShare); kshare.from.should.equal(share.from); kshare.to.should.equal(share.to); kshare.share.should.equal(share.share); }); it('should successfully parse A share without paillier challenge', function () { const share = { to: sdk_core_1.SignatureShareType.USER, from: sdk_core_1.SignatureShareType.BITGO, share: sdk_core_1.ECDSAMethods.convertAShare(ecdsaFixtures_1.mockAShare).share, }; const aShare = sdk_core_1.ECDSAMethods.parseAShare(share); should.exist(aShare); aShare.should.deepEqual(ecdsaFixtures_1.mockAShare); }); it('should successfully parse A share', function () { const share = { to: sdk_core_1.SignatureShareType.USER, from: sdk_core_1.SignatureShareType.BITGO, share: sdk_core_1.ECDSAMethods.convertAShare(ecdsaFixtures_1.mockAShare).share, }; const aShare = sdk_core_1.ECDSAMethods.parseAShare(share); should.exist(aShare); aShare.should.deepEqual(ecdsaFixtures_1.mockAShare); }); it('should successfully convert A share to signature share record', function () { const mockShare = ecdsaFixtures_1.mockAShare; const share = { to: sdk_core_1.SignatureShareType.USER, from: sdk_core_1.SignatureShareType.BITGO, share: `${mockShare.k}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.alpha}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.mu}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.n}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.ntilde}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.h1}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.h2}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.proof?.z || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.proof?.u || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.proof?.w || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.proof?.s || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.proof?.s1 || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.proof?.s2 || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.gammaProof?.z || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.gammaProof?.zprm || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.gammaProof?.t || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.gammaProof?.v || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.gammaProof?.w || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.gammaProof?.s || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.gammaProof?.s1 || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.gammaProof?.s2 || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.gammaProof?.t1 || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.gammaProof?.t2 || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.gammaProof?.u || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.gammaProof?.x || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.wProof?.z || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.wProof?.zprm || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.wProof?.t || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.wProof?.v || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.wProof?.w || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.wProof?.s || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.wProof?.s1 || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.wProof?.s2 || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.wProof?.t1 || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.wProof?.t2 || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.wProof?.u || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.wProof?.x || ''}${sdk_core_1.ECDSAMethods.delimeter}${mockShare.sigma.join(sdk_core_1.ECDSAMethods.delimeter)}`, }; const aShare = sdk_core_1.ECDSAMethods.convertAShare(mockShare); aShare.from.should.equal(share.from); aShare.to.should.equal(share.to); aShare.share.should.equal(share.share); }); it('should successfully parse Mu share', function () { const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.USER, share: sdk_core_1.ECDSAMethods.convertMuShare(ecdsaFixtures_1.mockMuShare).share, }; const muShare = sdk_core_1.ECDSAMethods.parseMuShare(share); muShare.i.should.equal(ecdsaFixtures_1.mockMuShare.i); muShare.j.should.equal(ecdsaFixtures_1.mockMuShare.j); muShare.alpha.should.equal(ecdsaFixtures_1.mockMuShare.alpha); muShare.mu.should.equal(ecdsaFixtures_1.mockMuShare.mu); }); it('should successfully convert Mu share to signature share record', function () { const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.USER, share: `${ecdsaFixtures_1.mockMuShare.alpha}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.mu}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.gammaProof?.z || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.gammaProof?.zprm || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.gammaProof?.t || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.gammaProof?.v || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.gammaProof?.w || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.gammaProof?.s || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.gammaProof?.s1 || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.gammaProof?.s2 || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.gammaProof?.t1 || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.gammaProof?.t2 || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.gammaProof?.u || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.gammaProof?.x || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.wProof?.z || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.wProof?.zprm || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.wProof?.t || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.wProof?.v || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.wProof?.w || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.wProof?.s || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.wProof?.s1 || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.wProof?.s2 || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.wProof?.t1 || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.wProof?.t2 || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.wProof?.u || ''}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockMuShare.wProof?.x || ''}`, }; const muShare = sdk_core_1.ECDSAMethods.convertMuShare(ecdsaFixtures_1.mockMuShare); muShare.from.should.equal(share.from); muShare.to.should.equal(share.to); muShare.share.should.equal(share.share); }); it('should successfully parse D share', function () { const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.USER, share: sdk_core_1.ECDSAMethods.convertDShare(ecdsaFixtures_1.mockDShareToBitgo).share, }; const dShare = sdk_core_1.ECDSAMethods.parseDShare(share); dShare.i.should.equal(ecdsaFixtures_1.mockDShareToBitgo.i); dShare.j.should.equal(ecdsaFixtures_1.mockDShareToBitgo.j); dShare.delta.should.equal(ecdsaFixtures_1.mockDShareToBitgo.delta); dShare.Gamma.should.equal(ecdsaFixtures_1.mockDShareToBitgo.Gamma); }); it('should successfully convert D share to signature share record', function () { const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.USER, share: `${ecdsaFixtures_1.mockDShareToBitgo.delta}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockDShareToBitgo.Gamma}`, }; const dShare = sdk_core_1.ECDSAMethods.convertDShare(ecdsaFixtures_1.mockDShareToBitgo); dShare.from.should.equal(share.from); dShare.to.should.equal(share.to); dShare.share.should.equal(share.share); }); it('should successfully parse S and D share', function () { const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.USER, share: `${ecdsaFixtures_1.mockSShareFromUser.R}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSShareFromUser.s}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSShareFromUser.y}${sdk_core_1.ECDSAMethods.secondaryDelimeter}${ecdsaFixtures_1.mockDShareToBitgo.delta}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockDShareToBitgo.Gamma}`, }; const { sShare, dShare } = sdk_core_1.ECDSAMethods.parseSDShare(share); sShare.i.should.equal(3); sShare.R.should.equal(ecdsaFixtures_1.mockSShareFromUser.R); sShare.s.should.equal(ecdsaFixtures_1.mockSShareFromUser.s); sShare.y.should.equal(ecdsaFixtures_1.mockSShareFromUser.y); dShare.i.should.equal(ecdsaFixtures_1.mockDShareToBitgo.i); dShare.j.should.equal(ecdsaFixtures_1.mockDShareToBitgo.j); dShare.delta.should.equal(ecdsaFixtures_1.mockDShareToBitgo.delta); dShare.Gamma.should.equal(ecdsaFixtures_1.mockDShareToBitgo.Gamma); }); it('should successfully convert S and D share to signature share record', function () { const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.USER, share: `${ecdsaFixtures_1.mockSShareFromUser.R}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSShareFromUser.s}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSShareFromUser.y}${sdk_core_1.ECDSAMethods.secondaryDelimeter}${ecdsaFixtures_1.mockDShareToBitgo.delta}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockDShareToBitgo.Gamma}`, }; const sdShare = sdk_core_1.ECDSAMethods.convertSDShare({ sShare: ecdsaFixtures_1.mockSShareFromUser, dShare: ecdsaFixtures_1.mockDShareToBitgo }); sdShare.from.should.equal(share.from); sdShare.to.should.equal(share.to); sdShare.share.should.equal(share.share); }); it('should successfully parse signature share', function () { const share = { to: sdk_core_1.SignatureShareType.USER, from: sdk_core_1.SignatureShareType.BITGO, share: `${ecdsaFixtures_1.mockSShareFromUser.R}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSShareFromUser.s}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSShareFromUser.y}`, }; const signature = sdk_core_1.ECDSAMethods.parseSignatureShare(share); signature.i.should.equal(1); signature.R.should.equal(ecdsaFixtures_1.mockSShareFromUser.R); signature.s.should.equal(ecdsaFixtures_1.mockSShareFromUser.s); signature.y.should.equal(ecdsaFixtures_1.mockSShareFromUser.y); }); it('should succuesfully parse combined signature', function () { const mockCombinedSignature = mpc.constructSignature([ecdsaFixtures_1.mockSShareFromUser, ecdsaFixtures_1.mockSShare]); const share = { to: sdk_core_1.SignatureShareType.USER, from: sdk_core_1.SignatureShareType.BITGO, share: `${mockCombinedSignature.recid}${sdk_core_1.ECDSAMethods.delimeter}${mockCombinedSignature.r}${sdk_core_1.ECDSAMethods.delimeter}${mockCombinedSignature.s}${sdk_core_1.ECDSAMethods.delimeter}${mockCombinedSignature.y}`, }; const signature = sdk_core_1.ECDSAMethods.parseCombinedSignature(share); signature.recid.should.equal(mockCombinedSignature.recid); signature.r.should.equal(mockCombinedSignature.r); signature.s.should.equal(mockCombinedSignature.s); signature.y.should.equal(mockCombinedSignature.y); }); it('should successfully convert signature share to signature share record', function () { const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.USER, share: `${ecdsaFixtures_1.mockSShareFromUser.R}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSShareFromUser.s}${sdk_core_1.ECDSAMethods.delimeter}${ecdsaFixtures_1.mockSShareFromUser.y}`, }; const signatureShare = sdk_core_1.ECDSAMethods.convertSignatureShare(ecdsaFixtures_1.mockSShareFromUser, sdk_core_1.ECDSAMethods.getParticipantIndex('user'), sdk_core_1.ECDSAMethods.getParticipantIndex('bitgo')); signatureShare.from.should.equal(share.from); signatureShare.to.should.equal(share.to); signatureShare.share.should.equal(share.share); }); it('should successfully convert B share to signature share record', function () { const bShare = ecdsaFixtures_1.mockedBitgoBShare.bShare; const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.BITGO, share: `${bShare.beta}${sdk_core_1.ECDSAMethods.delimeter}${bShare.gamma}${sdk_core_1.ECDSAMethods.delimeter}${bShare.k}${sdk_core_1.ECDSAMethods.delimeter}${bShare.nu}${sdk_core_1.ECDSAMethods.delimeter}${bShare.w}${sdk_core_1.ECDSAMethods.delimeter}${bShare.y}${sdk_core_1.ECDSAMethods.delimeter}${bShare.l}${sdk_core_1.ECDSAMethods.delimeter}${bShare.m}${sdk_core_1.ECDSAMethods.delimeter}${bShare.n}${sdk_core_1.ECDSAMethods.delimeter}${bShare.ntilde}${sdk_core_1.ECDSAMethods.delimeter}${bShare.h1}${sdk_core_1.ECDSAMethods.delimeter}${bShare.h2}${sdk_core_1.ECDSAMethods.delimeter}${bShare.ck}${sdk_core_1.ECDSAMethods.delimeter}${bShare.p.join(sdk_core_1.ECDSAMethods.delimeter)}`, }; const signatureShare = sdk_core_1.ECDSAMethods.convertBShare(bShare); signatureShare.from.should.equal(share.from); signatureShare.to.should.equal(share.to); signatureShare.share.should.equal(share.share); }); it('should successfully parse B share', function () { const bShare = ecdsaFixtures_1.mockedBitgoBShare.bShare; const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.BITGO, share: sdk_core_1.ECDSAMethods.convertBShare(ecdsaFixtures_1.mockedBitgoBShare.bShare).share, }; const parsedBShare = sdk_core_1.ECDSAMethods.parseBShare(share); parsedBShare.should.deepEqual(bShare); }); it('should successfully convert O share to signature share record', function () { const oShare = ecdsaFixtures_1.mockedBitgoOAndDShare.oShare; const delimeter = sdk_core_1.ECDSAMethods.delimeter; const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.BITGO, share: `${oShare.Gamma}${delimeter}${oShare.delta}${delimeter}${oShare.k}${delimeter}${oShare.omicron}${delimeter}${oShare.y}`, }; const oShareSigRecord = sdk_core_1.ECDSAMethods.convertOShare(oShare); oShareSigRecord.from.should.equal(share.from); oShareSigRecord.to.should.equal(share.to); oShareSigRecord.share.should.equal(share.share); }); it('should successfully parse O share', function () { const oShare = ecdsaFixtures_1.mockedBitgoOAndDShare.oShare; const delimeter = sdk_core_1.ECDSAMethods.delimeter; const share = { to: sdk_core_1.SignatureShareType.BITGO, from: sdk_core_1.SignatureShareType.BITGO, share: `${oShare.Gamma}${delimeter}${oShare.delta}${delimeter}${oShare.k}${delimeter}${oShare.omicron}${delimeter}${oShare.y}`, }; const parsedOShare = sdk_core_1.ECDSAMethods.parseOShare(share); parsedOShare.i.should.equal(oShare.i); parsedOShare.y.should.equal(oShare.y); parsedOShare.k.should.equal(oShare.k); parsedOShare.omicron.should.equal(oShare.omicron); parsedOShare.delta.should.equal(oShare.delta); parsedOShare.Gamma.should.equal(oShare.Gamma); }); }); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNkc2EuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi90ZXN0L3YyL3VuaXQvdHNzL2VjZHNhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsOENBV3lCO0FBQ3pCLG9EQUFvRTtBQUNwRSxtQ0FBbUM7QUFDbkMsaUNBQWtDO0FBQ2xDLDhDQUErRTtBQUMvRSx5Q0FBd0M7QUFDeEMsdUNBQXFFO0FBQ3JFLG9FQWUwQztBQUUxQyw2QkFBOEI7QUFHOUIsTUFBTSxhQUFhLEdBQUcsdUJBQVksQ0FBQyxhQUFhLENBQUM7QUFDakQsTUFBTSxpQkFBaUIsR0FBRyx1QkFBWSxDQUFDLGlCQUFpQixDQUFDO0FBTXpELFFBQVEsQ0FBQyxrQ0FBa0MsRUFBRTtJQUMzQyxJQUFJLEdBQVUsQ0FBQztJQUVmLElBQUksWUFBc0IsQ0FBQztJQUMzQixJQUFJLGNBQXdCLENBQUM7SUFDN0IsSUFBSSxhQUF1QixDQUFDO0lBRTVCLElBQUksT0FBMEIsQ0FBQztJQUMvQixJQUFJLFNBQTRCLENBQUM7SUFDakMsSUFBSSxRQUEyQixDQUFDO0lBRWhDLElBQUksY0FBMEIsQ0FBQztJQUMvQixJQUFJLGdCQUE0QixDQUFDO0lBQ2pDLElBQUksZUFBMkIsQ0FBQztJQUNoQyxJQUFJLGNBQXNCLENBQUM7SUFFM0IsTUFBTSxDQUFDLEtBQUs7UUFDVixHQUFHLEdBQUcsSUFBSSxnQkFBSyxFQUFFLENBQUM7UUFDbEIsWUFBWSxHQUFHLHlCQUFTLENBQUMsWUFBWSxDQUFDO1FBQ3RDLGNBQWMsR0FBRyx5QkFBUyxDQUFDLGNBQWMsQ0FBQztRQUMxQyxhQUFhLEdBQUcseUJBQVMsQ0FBQyxhQUFhLENBQUM7UUFFeEMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxD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