PHP WebShell

Текущая директория: /opt/BitGoJS/modules/sdk-lib-mpc/test/unit/tss/ecdsa

Просмотр файла: dklsDsg.ts

import { DklsDsg, DklsUtils } from '../../../../src/tss/ecdsa-dkls';
import * as fs from 'fs';
import * as crypto from 'crypto';
import should from 'should';
import assert from 'assert';

import { Keyshare } from '@silencelaboratories/dkls-wasm-ll-node';
import { decode } from 'cbor-x';
import * as mpcv2KeyCardData from './fixtures/mpcv2keycarddata';
import * as sjcl from 'sjcl';
import {
  DeserializedBroadcastMessage,
  DeserializedDklsSignature,
  DeserializedMessages,
  getDecodedReducedKeyShare,
  ReducedKeyShare,
  RetrofitData,
} from '../../../../src/tss/ecdsa-dkls/types';
import {
  executeTillRound,
  generate2of2KeyShares,
  verifyAndConvertDklsSignature,
} from '../../../../src/tss/ecdsa-dkls/util';

describe('DKLS Dsg 2x3', function () {
  const vectors = [
    {
      party1: 0,
      party2: 1,
      msgToSign: 'ffff',
      derivationPath: 'm',
    },
    {
      party1: 0,
      party2: 2,
      msgToSign: 'ffff',
      derivationPath: 'm/0',
    },
    {
      party1: 1,
      party2: 2,
      msgToSign: 'ffff',
      derivationPath: 'm/0/0/0',
    },
    {
      party1: 1,
      party2: 2,
      msgToSign: 'ffff',
      derivationPath: 'm/0/9/10',
    },
  ];
  // To generate the fixtures, run DKG as in the dklsDkg.ts tests and save the resulting party.getKeyShare in a file by doing fs.writeSync(party.getKeyShare()).
  const shareFiles = [
    `${__dirname}/fixtures/userShare`,
    `${__dirname}/fixtures/backupShare`,
    `${__dirname}/fixtures/bitgoShare`,
  ];
  vectors.forEach(async function (vector) {
    it(`should create signatures for parties ${vector.party1} and ${vector.party2} with derivation`, async function () {
      const party1 = new DklsDsg.Dsg(
        fs.readFileSync(shareFiles[vector.party1]),
        vector.party1,
        vector.derivationPath,
        crypto.createHash('sha256').update(Buffer.from(vector.msgToSign, 'hex')).digest()
      );
      const party2 = new DklsDsg.Dsg(
        fs.readFileSync(shareFiles[vector.party2]),
        vector.party2,
        vector.derivationPath,
        crypto.createHash('sha256').update(Buffer.from(vector.msgToSign, 'hex')).digest()
      );
      const round4Messages = await executeTillRound(4, party1, party2);
      party1.handleIncomingMessages({
        p2pMessages: [],
        broadcastMessages: round4Messages[1].broadcastMessages,
      });
      party2.handleIncomingMessages({
        p2pMessages: [],
        broadcastMessages: round4Messages[0].broadcastMessages,
      });
      party1.signature.should.deepEqual(party2.signature);
      const signature = party1.signature;

      const combinedSigUsingUtil = DklsUtils.combinePartialSignatures(
        [round4Messages[0].broadcastMessages[0].payload, round4Messages[1].broadcastMessages[0].payload],
        Buffer.from(round4Messages[0]?.broadcastMessages[0]?.signatureR).toString('hex')
      );
      (
        (combinedSigUsingUtil.R.every((p) => signature.R.includes(p)) &&
          signature.R.every((p) => combinedSigUsingUtil.R.includes(p))) ||
        (signature.S.every((p) => combinedSigUsingUtil.S.includes(p)) &&
          combinedSigUsingUtil.S.every((p) => signature.S.includes(p)))
      ).should.equal(true);

      const keyShare: Keyshare = Keyshare.fromBytes(fs.readFileSync(shareFiles[vector.party1]));
      const convertedSignature = verifyAndConvertDklsSignature(
        Buffer.from(vector.msgToSign, 'hex'),
        party1.signature,
        Buffer.from(keyShare.publicKey).toString('hex') +
          Buffer.from(decode(keyShare.toBytes()).root_chain_code).toString('hex'),
        vector.derivationPath
      );
      should.exist(convertedSignature);
      convertedSignature.split(':').length.should.equal(4);
    });
  });

  it(`should pass when doing key refresh on compressed key cards then signing`, async function () {
    // Fixtures generated through web-demo keycard generation example for DKLS.
    const userCompressedPrv = Buffer.from(sjcl.decrypt('t3stSicretly!', mpcv2KeyCardData.userEncryptedPrv), 'base64');
    const bakcupCompressedPrv = Buffer.from(
      sjcl.decrypt('t3stSicretly!', mpcv2KeyCardData.backupEncryptedPrv),
      'base64'
    );
    const userPrvJSON: ReducedKeyShare = getDecodedReducedKeyShare(userCompressedPrv);
    const backupPrvJSON: ReducedKeyShare = getDecodedReducedKeyShare(bakcupCompressedPrv);
    const userKeyRetrofit: RetrofitData = {
      xShare: {
        x: Buffer.from(userPrvJSON.prv).toString('hex'),
        y: Buffer.from(userPrvJSON.pub).toString('hex'),
        chaincode: Buffer.from(userPrvJSON.rootChainCode).toString('hex'),
      },
      xiList: userPrvJSON.xList.slice(0, 2),
    };
    const backupKeyRetrofit: RetrofitData = {
      xShare: {
        x: Buffer.from(backupPrvJSON.prv).toString('hex'),
        y: Buffer.from(backupPrvJSON.pub).toString('hex'),
        chaincode: Buffer.from(backupPrvJSON.rootChainCode).toString('hex'),
      },
      xiList: backupPrvJSON.xList.slice(0, 2),
    };
    const [user, backup] = await generate2of2KeyShares(userKeyRetrofit, backupKeyRetrofit);
    const userKeyShare = user.getKeyShare();
    const backupKeyShare = backup.getKeyShare();
    const party1 = new DklsDsg.Dsg(
      userKeyShare,
      0,
      'm',
      crypto.createHash('sha256').update(Buffer.from('ffff', 'hex')).digest()
    );
    const party2 = new DklsDsg.Dsg(
      backupKeyShare,
      1,
      'm',
      crypto.createHash('sha256').update(Buffer.from('ffff', 'hex')).digest()
    );
    // Round 1 ////
    const party1Round1Message = await party1.init();
    const party2Round1Message = await party2.init();
    const party2Round2Messages = party2.handleIncomingMessages({
      p2pMessages: [],
      broadcastMessages: [party1Round1Message],
    });
    // ////////////
    // Round 2
    const party1Round2Messages = party1.handleIncomingMessages({
      p2pMessages: [],
      broadcastMessages: [party2Round1Message],
    });
    const party1Round3Messages = party1.handleIncomingMessages({
      p2pMessages: party2Round2Messages.p2pMessages,
      broadcastMessages: [],
    });
    const party2Round3Messages = party2.handleIncomingMessages({
      p2pMessages: party1Round2Messages.p2pMessages,
      broadcastMessages: [],
    });
    const party2Round4Messages = party2.handleIncomingMessages({
      p2pMessages: party1Round3Messages.p2pMessages,
      broadcastMessages: [],
    });
    // ////////////
    // / Produce Signature
    const party1Round4Messages = party1.handleIncomingMessages({
      p2pMessages: party2Round3Messages.p2pMessages,
      broadcastMessages: [],
    });
    party1.handleIncomingMessages({
      p2pMessages: [],
      broadcastMessages: party2Round4Messages.broadcastMessages,
    });
    should.exist(party1.signature);
    should.exist(party1Round4Messages.broadcastMessages[0].signatureR);
    const combinedSigUsingUtil = DklsUtils.combinePartialSignatures(
      [party1Round4Messages.broadcastMessages[0].payload, party2Round4Messages.broadcastMessages[0].payload],
      Buffer.from(party1Round4Messages.broadcastMessages[0].signatureR!).toString('hex')
    );
    (
      (combinedSigUsingUtil.R.every((p) => party1.signature.R.includes(p)) &&
        party1.signature.R.every((p) => combinedSigUsingUtil.R.includes(p))) ||
      (party1.signature.S.every((p) => combinedSigUsingUtil.S.includes(p)) &&
        combinedSigUsingUtil.S.every((p) => party1.signature.S.includes(p)))
    ).should.equal(true);
    // ////////////
    party2.handleIncomingMessages({
      p2pMessages: [],
      broadcastMessages: party1Round4Messages.broadcastMessages,
    });
    party1.signature.should.deepEqual(party2.signature);
    const convertedSignature = verifyAndConvertDklsSignature(
      Buffer.from('ffff', 'hex'),
      party1.signature,
      Buffer.from(userPrvJSON.pub).toString('hex') + Buffer.from(userPrvJSON.rootChainCode).toString('hex'),
      'm'
    );
    should.exist(convertedSignature);
  });

  it(`should fail when signing two different messages`, async function () {
    const party1 = new DklsDsg.Dsg(
      fs.readFileSync(`${__dirname}/fixtures/userShare`),
      0,
      'm',
      crypto.createHash('sha256').update(Buffer.from('ffff', 'hex')).digest()
    );
    const party2 = new DklsDsg.Dsg(
      fs.readFileSync(`${__dirname}/fixtures/bitgoShare`),
      2,
      'm',
      crypto.createHash('sha256').update(Buffer.from('fffa', 'hex')).digest()
    );
    // Round 1 ////
    const party1Round1Message = await party1.init();
    const party2Round1Message = await party2.init();
    const party2Round2Messages = party2.handleIncomingMessages({
      p2pMessages: [],
      broadcastMessages: [party1Round1Message],
    });
    // ////////////
    // Round 2
    const party1Round2Messages = party1.handleIncomingMessages({
      p2pMessages: [],
      broadcastMessages: [party2Round1Message],
    });
    const party1Round3Messages = party1.handleIncomingMessages({
      p2pMessages: party2Round2Messages.p2pMessages,
      broadcastMessages: [],
    });
    const party2Round3Messages = party2.handleIncomingMessages({
      p2pMessages: party1Round2Messages.p2pMessages,
      broadcastMessages: [],
    });
    const party2Round4Messages = party2.handleIncomingMessages({
      p2pMessages: party1Round3Messages.p2pMessages,
      broadcastMessages: [],
    });
    // ////////////
    // / Produce Signature
    party1.handleIncomingMessages({
      p2pMessages: party2Round3Messages.p2pMessages,
      broadcastMessages: [],
    });
    let err = '';
    try {
      party1.handleIncomingMessages({
        p2pMessages: [],
        broadcastMessages: party2Round4Messages.broadcastMessages,
      });
    } catch (e) {
      err = e;
    }
    err.should.deepEqual(
      Error('Error while creating messages from party 0, round 5: Error: k256 error: signature error')
    );
  });

  it(`should get and set sesssion corretly for all rounds`, async function () {
    const vector = vectors[0];

    const party2 = new DklsDsg.Dsg(
      fs.readFileSync(shareFiles[vector.party2]),
      vector.party2,
      vector.derivationPath,
      crypto.createHash('sha256').update(Buffer.from(vector.msgToSign, 'hex')).digest()
    );

    // round 1
    let party1Round1Message: DeserializedBroadcastMessage,
      party2Round1Message: DeserializedBroadcastMessage,
      party1Round1Session: string;
    {
      const party1 = new DklsDsg.Dsg(
        fs.readFileSync(shareFiles[vector.party1]),
        vector.party1,
        vector.derivationPath,
        crypto.createHash('sha256').update(Buffer.from(vector.msgToSign, 'hex')).digest()
      );
      party1Round1Message = await party1.init();
      party1Round1Session = party1.getSession();

      party2Round1Message = await party2.init();
    }

    // round 2
    let party1Round2Messages: DeserializedMessages,
      party2Round2Messages: DeserializedMessages,
      party1Round2Session: string;
    {
      const party1Round2DSG = new DklsDsg.Dsg(
        fs.readFileSync(shareFiles[vector.party1]),
        vector.party1,
        vector.derivationPath,
        crypto.createHash('sha256').update(Buffer.from(vector.msgToSign, 'hex')).digest()
      );
      await party1Round2DSG.setSession(party1Round1Session);
      party1Round2Messages = party1Round2DSG.handleIncomingMessages({
        p2pMessages: [],
        broadcastMessages: [party2Round1Message],
      });
      party1Round2Session = party1Round2DSG.getSession();

      party2Round2Messages = party2.handleIncomingMessages({
        p2pMessages: [],
        broadcastMessages: [party1Round1Message],
      });
    }

    // round 3
    let party1Round3Messages: DeserializedMessages,
      party2Round3Messages: DeserializedMessages,
      party1Round3Session: string;
    {
      const party1Round3DSG = new DklsDsg.Dsg(
        fs.readFileSync(shareFiles[vector.party1]),
        vector.party1,
        vector.derivationPath,
        crypto.createHash('sha256').update(Buffer.from(vector.msgToSign, 'hex')).digest()
      );
      await party1Round3DSG.setSession(party1Round2Session);
      party1Round3Messages = party1Round3DSG.handleIncomingMessages({
        p2pMessages: party2Round2Messages.p2pMessages,
        broadcastMessages: [],
      });
      party1Round3Session = party1Round3DSG.getSession();

      party2Round3Messages = party2.handleIncomingMessages({
        p2pMessages: party1Round2Messages.p2pMessages,
        broadcastMessages: [],
      });
    }

    // round 4
    let party1Round4Messages: DeserializedMessages,
      party2Round4Messages: DeserializedMessages,
      party1Round4Session: string;
    {
      const party1Round4DSG = new DklsDsg.Dsg(
        fs.readFileSync(shareFiles[vector.party1]),
        vector.party1,
        vector.derivationPath,
        crypto.createHash('sha256').update(Buffer.from(vector.msgToSign, 'hex')).digest()
      );
      await party1Round4DSG.setSession(party1Round3Session);
      party1Round4Messages = party1Round4DSG.handleIncomingMessages({
        p2pMessages: party2Round3Messages.p2pMessages,
        broadcastMessages: [],
      });
      party1Round4Session = party1Round4DSG.getSession();

      party2Round4Messages = party2.handleIncomingMessages({
        p2pMessages: party1Round3Messages.p2pMessages,
        broadcastMessages: [],
      });
    }

    // round 5
    let signature: DeserializedDklsSignature;
    {
      const party1Round5DSG = new DklsDsg.Dsg(
        fs.readFileSync(shareFiles[vector.party1]),
        vector.party1,
        vector.derivationPath,
        crypto.createHash('sha256').update(Buffer.from(vector.msgToSign, 'hex')).digest()
      );
      await party1Round5DSG.setSession(party1Round4Session);
      party1Round5DSG.handleIncomingMessages({
        p2pMessages: [],
        broadcastMessages: party2Round4Messages.broadcastMessages,
      });
      party2.handleIncomingMessages({
        p2pMessages: [],
        broadcastMessages: party1Round4Messages.broadcastMessages,
      });
      party1Round5DSG.signature.should.deepEqual(party2.signature);
      signature = party1Round5DSG.signature;
    }

    assert(party1Round4Messages.broadcastMessages[0].signatureR);
    const combinedSigUsingUtil = DklsUtils.combinePartialSignatures(
      [party1Round4Messages.broadcastMessages[0].payload, party2Round4Messages.broadcastMessages[0].payload],
      Buffer.from(party1Round4Messages.broadcastMessages[0].signatureR as Uint8Array).toString('hex')
    );
    (
      (combinedSigUsingUtil.R.every((p) => signature.R.includes(p)) &&
        signature.R.every((p) => combinedSigUsingUtil.R.includes(p))) ||
      (signature.S.every((p) => combinedSigUsingUtil.S.includes(p)) &&
        combinedSigUsingUtil.S.every((p) => signature.S.includes(p)))
    ).should.equal(true);

    const keyShare: Keyshare = Keyshare.fromBytes(fs.readFileSync(shareFiles[vector.party1]));
    const convertedSignature = verifyAndConvertDklsSignature(
      Buffer.from(vector.msgToSign, 'hex'),
      signature,
      Buffer.from(keyShare.publicKey).toString('hex') +
        Buffer.from(decode(keyShare.toBytes()).root_chain_code).toString('hex'),
      vector.derivationPath
    );
    should.exist(convertedSignature);
    convertedSignature.split(':').length.should.equal(4);
  });
});

Выполнить команду


Для локальной разработки. Не используйте в интернете!