|
| 1 | +import { ECDSAUtils } from '@bitgo/sdk-core'; |
| 2 | +import * as crypto from 'crypto'; |
| 3 | +import * as fs from 'fs'; |
| 4 | +import * as secp256k1 from 'secp256k1'; |
| 5 | +import assert = require('assert'); |
| 6 | +import { bigIntFromBufferBE, bigIntToBufferBE, HDTree, Secp256k1Bip32HdTree } from '@bitgo/sdk-lib-mpc'; |
| 7 | + |
| 8 | +const sampleMessage = "Hello, World!"; |
| 9 | +// Replace the following variables with your own values. Moreover, copy the encrypted user and backup keys from the key card into the userKey.txt and backupKey.txt files. |
| 10 | +const commonKeyChain = "<Public key from key card>"; |
| 11 | +const walletPassphrase = "<Wallet passphrase>"; |
| 12 | + |
| 13 | + |
| 14 | +async function testRecoveryMpcV2() { |
| 15 | + const userKey = fs.readFileSync('userKey.txt', 'utf8').replace(/(\r\n|\n|\r)/gm, ""); |
| 16 | + const backupKey = fs.readFileSync('backupKey.txt', 'utf8').replace(/(\r\n|\n|\r)/gm, ""); |
| 17 | + // Converting the user and backup keys on the keycard to key buffers that can be used in signing. |
| 18 | + const mpcv2KeyChain = await ECDSAUtils.getMpcV2RecoveryKeyShares(userKey, backupKey, walletPassphrase); |
| 19 | + assert(mpcv2KeyChain.commonKeyChain === commonKeyChain, "Common key chain on keys do not match the common key chain from keycard."); |
| 20 | + // Computing SHA256 hash of the message. |
| 21 | + const messageHash = crypto.createHash('sha256').update(Buffer.from(sampleMessage, 'utf8')).digest(); |
| 22 | + // Signing the message hash using the MPCv2 recovery key shares. |
| 23 | + const signature = await ECDSAUtils.signRecoveryMpcV2(messageHash, mpcv2KeyChain.userKeyShare, mpcv2KeyChain.backupKeyShare, commonKeyChain); |
| 24 | + const hdTree: HDTree = new Secp256k1Bip32HdTree(); |
| 25 | + // Deriving the public key at path m/0 from the common key chain. |
| 26 | + const derivedPub = hdTree.publicDerive( |
| 27 | + { |
| 28 | + pk: bigIntFromBufferBE(Buffer.from(commonKeyChain.slice(0, 66), 'hex')), |
| 29 | + chaincode: bigIntFromBufferBE(Buffer.from(commonKeyChain.slice(66), 'hex')), |
| 30 | + }, |
| 31 | + 'm/0' |
| 32 | + ); |
| 33 | + // Verifying that the signature is valid. |
| 34 | + const isSignatureValid = secp256k1.ecdsaVerify(Buffer.concat([Buffer.from(signature.r, 'hex'), Buffer.from(signature.s, 'hex')]), messageHash, bigIntToBufferBE(derivedPub.pk)); |
| 35 | + assert(isSignatureValid, "Signature is not valid."); |
| 36 | +} |
| 37 | + |
| 38 | +testRecoveryMpcV2().catch((e) => console.error(e)); |
0 commit comments