PHP WebShell

Текущая директория: /opt/BitGoJS/modules/sdk-core/src/bitgo/tss/ecdsa

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

import { SignatureShareRecord, SignatureShareType } from '../../utils';
import openpgp from 'openpgp';
import { DklsComms, DklsTypes } from '@bitgo/sdk-lib-mpc';
import {
  MPCv2SignatureShareRound1Input,
  MPCv2SignatureShareRound1Output,
  MPCv2SignatureShareRound2Input,
  MPCv2SignatureShareRound2Output,
  MPCv2SignatureShareRound3Input,
  MPCv2PartyFromStringOrNumber,
} from '@bitgo/public-types';
import assert from 'assert';

function partyIdToSignatureShareType(partyId: 0 | 1 | 2): SignatureShareType {
  assert(partyId === 0 || partyId === 1 || partyId === 2, 'Invalid partyId for MPCv2 signing');
  switch (partyId) {
    case 0:
      return SignatureShareType.USER;
    case 1:
      return SignatureShareType.BACKUP;
    case 2:
      return SignatureShareType.BITGO;
  }
}

/**
 Helpers in this take care of all interaction with WP API's
**/

export async function getSignatureShareRoundOne(
  round1Message: DklsTypes.DeserializedBroadcastMessage,
  userGpgKey: openpgp.SerializedKeyPair<string>,
  partyId: 0 | 1 = 0,
  otherSignerPartyId: 0 | 1 | 2 = 2
): Promise<SignatureShareRecord> {
  const serializedMessages = DklsTypes.serializeMessages({
    broadcastMessages: [round1Message],
    p2pMessages: [],
  });
  const authEncBroadcastMessage = (
    await DklsComms.encryptAndAuthOutgoingMessages(
      serializedMessages,
      [], // Broadcast message so doesn't need to encrypt to BitGo's GPG key
      [getUserPartyGpgKey(userGpgKey, partyId)]
    )
  ).broadcastMessages[0];
  // Share type expected by Wallet Platform's API
  assert(MPCv2PartyFromStringOrNumber.is(authEncBroadcastMessage.from));
  const share: MPCv2SignatureShareRound1Input = {
    type: 'round1Input',
    data: {
      msg1: {
        from: authEncBroadcastMessage.from,
        message: authEncBroadcastMessage.payload.message,
        signature: authEncBroadcastMessage.payload.signature,
      },
    },
  };
  const serializedShare = JSON.stringify(share);
  return {
    from: partyIdToSignatureShareType(partyId),
    to: partyIdToSignatureShareType(otherSignerPartyId),
    share: serializedShare,
  };
}

export async function getSignatureShareRoundTwo(
  userToBitGoMessages2: DklsTypes.DeserializedMessages,
  userToBitGoMessages3: DklsTypes.DeserializedMessages,
  userGpgKey: openpgp.SerializedKeyPair<string>,
  otherPartyGpgKey: openpgp.Key,
  partyId: 0 | 1 = 0,
  otherSignerPartyId: 0 | 1 | 2 = 2
): Promise<SignatureShareRecord> {
  const userToBitGoEncryptedMsg2 = await DklsComms.encryptAndAuthOutgoingMessages(
    DklsTypes.serializeMessages(userToBitGoMessages2),
    [getBitGoPartyGpgKey(otherPartyGpgKey, otherSignerPartyId)],
    [getUserPartyGpgKey(userGpgKey, partyId)]
  );

  const userToBitGoEncryptedMsg3 = await DklsComms.encryptAndAuthOutgoingMessages(
    DklsTypes.serializeMessages(userToBitGoMessages3),
    [getBitGoPartyGpgKey(otherPartyGpgKey, otherSignerPartyId)],
    [getUserPartyGpgKey(userGpgKey, partyId)]
  );
  assert(userToBitGoEncryptedMsg2.p2pMessages.length, 'User to BitGo messages 2 not present.');
  assert(userToBitGoEncryptedMsg3.p2pMessages.length, 'User to BitGo messages 3 not present.');
  assert(MPCv2PartyFromStringOrNumber.is(userToBitGoEncryptedMsg2.p2pMessages[0].from));
  assert(MPCv2PartyFromStringOrNumber.is(userToBitGoEncryptedMsg2.p2pMessages[0].to));
  assert(MPCv2PartyFromStringOrNumber.is(userToBitGoEncryptedMsg3.p2pMessages[0].from));
  assert(MPCv2PartyFromStringOrNumber.is(userToBitGoEncryptedMsg3.p2pMessages[0].to));
  const share: MPCv2SignatureShareRound2Input = {
    type: 'round2Input',
    data: {
      msg2: {
        from: userToBitGoEncryptedMsg2.p2pMessages[0].from,
        to: userToBitGoEncryptedMsg2.p2pMessages[0].to,
        encryptedMessage: userToBitGoEncryptedMsg2.p2pMessages[0].payload.encryptedMessage,
        signature: userToBitGoEncryptedMsg2.p2pMessages[0].payload.signature,
      },
      msg3: {
        from: userToBitGoEncryptedMsg3.p2pMessages[0].from,
        to: userToBitGoEncryptedMsg3.p2pMessages[0].to,
        encryptedMessage: userToBitGoEncryptedMsg3.p2pMessages[0].payload.encryptedMessage,
        signature: userToBitGoEncryptedMsg3.p2pMessages[0].payload.signature,
      },
    },
  };
  return {
    from: partyIdToSignatureShareType(partyId),
    to: partyIdToSignatureShareType(otherSignerPartyId),
    share: JSON.stringify(share),
  };
}

export async function getSignatureShareRoundThree(
  userToBitGoMessages4: DklsTypes.DeserializedMessages,
  userGpgKey: openpgp.SerializedKeyPair<string>,
  bitgoGpgKey: openpgp.Key,
  partyId: 0 | 1 = 0,
  otherSignerPartyId: 0 | 1 | 2 = 2
): Promise<SignatureShareRecord> {
  const userToBitGoEncryptedMsg4 = await DklsComms.encryptAndAuthOutgoingMessages(
    DklsTypes.serializeMessages(userToBitGoMessages4),
    [getBitGoPartyGpgKey(bitgoGpgKey, otherSignerPartyId)],
    [getUserPartyGpgKey(userGpgKey, partyId)]
  );
  assert(MPCv2PartyFromStringOrNumber.is(userToBitGoEncryptedMsg4.broadcastMessages[0].from));
  if (!userToBitGoEncryptedMsg4.broadcastMessages[0].signatureR?.message) {
    throw Error('signatureR should be defined');
  }
  const share: MPCv2SignatureShareRound3Input = {
    type: 'round3Input',
    data: {
      msg4: {
        from: userToBitGoEncryptedMsg4.broadcastMessages[0].from,
        message: userToBitGoEncryptedMsg4.broadcastMessages[0].payload.message,
        signature: userToBitGoEncryptedMsg4.broadcastMessages[0].payload.signature,
        signatureR: userToBitGoEncryptedMsg4.broadcastMessages[0].signatureR.message,
      },
    },
  };
  return {
    from: partyIdToSignatureShareType(partyId),
    to: partyIdToSignatureShareType(otherSignerPartyId),
    share: JSON.stringify(share),
  };
}

export async function verifyBitGoMessagesAndSignaturesRoundOne(
  parsedSignatureShare: MPCv2SignatureShareRound1Output,
  userGpgKey: openpgp.SerializedKeyPair<string>,
  bitgoGpgKey: openpgp.Key,
  partyId: 0 | 1 = 0
): Promise<DklsTypes.SerializedMessages> {
  return await DklsComms.decryptAndVerifyIncomingMessages(
    {
      p2pMessages: [
        {
          from: parsedSignatureShare.data.msg2.from,
          to: parsedSignatureShare.data.msg2.to,
          payload: {
            encryptedMessage: parsedSignatureShare.data.msg2.encryptedMessage,
            signature: parsedSignatureShare.data.msg2.signature,
          },
        },
      ],
      broadcastMessages: [
        {
          from: parsedSignatureShare.data.msg1.from,
          payload: {
            message: parsedSignatureShare.data.msg1.message,
            signature: parsedSignatureShare.data.msg1.signature,
          },
        },
      ],
    },
    [getBitGoPartyGpgKey(bitgoGpgKey)],
    [getUserPartyGpgKey(userGpgKey, partyId)]
  );
}

export async function verifyBitGoMessagesAndSignaturesRoundTwo(
  parsedSignatureShare: MPCv2SignatureShareRound2Output,
  userGpgKey: openpgp.SerializedKeyPair<string>,
  bitgoGpgKey: openpgp.Key,
  partyId: 0 | 1 = 0
): Promise<DklsTypes.SerializedMessages> {
  return await DklsComms.decryptAndVerifyIncomingMessages(
    {
      p2pMessages: [
        {
          from: parsedSignatureShare.data.msg3.from,
          to: parsedSignatureShare.data.msg3.to,
          payload: {
            encryptedMessage: parsedSignatureShare.data.msg3.encryptedMessage,
            signature: parsedSignatureShare.data.msg3.signature,
          },
        },
      ],
      broadcastMessages: [],
    },
    [getBitGoPartyGpgKey(bitgoGpgKey)],
    [getUserPartyGpgKey(userGpgKey, partyId)]
  );
}

export function getBitGoPartyGpgKey(key: openpgp.Key, partyId: 0 | 1 | 2 = 2): DklsTypes.PartyGpgKey {
  return {
    partyId: partyId,
    gpgKey: key.armor(),
  };
}

export function getUserPartyGpgKey(key: openpgp.SerializedKeyPair<string>, partyId: 0 | 1 = 0): DklsTypes.PartyGpgKey {
  return {
    partyId: partyId,
    gpgKey: key.privateKey,
  };
}

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


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