bitgo
Version:
BitGo JavaScript SDK
639 lines • 149 kB
JavaScript
"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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