0

I have created a wallet on the bitgo platform and in response I get the private and public keys.

I wanted to use them for signing some data in node.js using the private key and verify it using the public key that we got from above.

I see that we can use crypto.createSign method for creating the signature and crypto.createVerify to verify the signature using the respective keys. I was able to perform signing and verifying using -

Test keys that I created using Bitgo -

Bitgo Keys:

Private key: 
xprv9s21ZrQH143K2SiPk3UYw24a2d5ZVey4g9mKB58at9vuXbsPmGxzQWzFJQRcaTHhbyNzyt33uRaXmuXopv1Faep4rrL1qHdmWGrwfj2sUHr

Public key: 
xpub661MyMwAqRbcEvnrr51ZJA1Jaev3u7gv3NguyTYCSVTtQQCYJpHExKJj9fiPM9EELJcGaxV8vFiwJTJuM4F5HoSJXVM4nrVFcWDki7gzmcr

I want to use the bitgo private and public keys to do the same.

My knowledge is very limited in cryptography but I am guessing that I have to convert bitgo keys in some format that I can use for signing and verification.

Can someone please help me?

Thanks!

Sydney_dev
  • 1,448
  • 2
  • 17
  • 24

1 Answers1

0

Yes, nodejs crypto takes several PEM and DER formats defined by OpenSSL, or JWK which do not include the Bitcoin HD (BIP32) formats (nor the classic Bitcoin formats like WIF). You need to first extract the actual raw-key parts (private multiplier and public point) from the HD format, similar to How to verify a signature made by trezor wallet for Python, and then build the SEC1 (or PKCS8, but SEC1 is easier) and SPKI (X.509/PKIX) formats needed for nodejs/OpenSSL, the former being almost the same as How to convert an ECDSA key to PEM format . (In general JWK is easier to build, but the Bitcoin formats here don't contain the information needed to do so.)

Adjusted and combined code (separate if you want to do signing and verifying separately, which usually people do):

const crypto = require('crypto');
const b58 = require('bs58check');
const prv = 'xprv9s21ZrQH143K2SiPk3UYw24a2d5ZVey4g9mKB58at9vuXbsPmGxzQWzFJQRcaTHhbyNzyt33uRaXmuXopv1Faep4rrL1qHdmWGrwfj2sUHr';
const pub = 'xpub661MyMwAqRbcEvnrr51ZJA1Jaev3u7gv3NguyTYCSVTtQQCYJpHExKJj9fiPM9EELJcGaxV8vFiwJTJuM4F5HoSJXVM4nrVFcWDki7gzmcr';

let prvraw = b58.decode(prv).subarray(46);
let pubraw = b58.decode(pub).subarray(45);

// hardcode secp256k1 and compressed point, which Bitcoin and BIP32 require
let prvsec1 = Buffer.from("302e0201010420"+prvraw.toString('hex')+"a00706052b8104000a",'hex');
let pubspki = Buffer.from("3036301006072a8648ce3d020106052b8104000a032200"+pubraw.toString('hex'),'hex');

// optional prebuild, or can inline in .sign and .verify
let prvkey = crypto.createPrivateKey({key:prvsec1,format:'der',type:'sec1'});
let pubkey = crypto.createPublicKey({key:pubspki,format:'der',type:'spki'});

let data = "some test data";
let sign = crypto.createSign('sha256'); sign.update(data);
let signature = sign.sign(prvkey,'hex'); console.log(signature);
let vrfy = crypto.createVerify('sha256'); vrfy.update(data);
console.log (vrfy.verify(pubkey,signature,'hex'));
// add dsaEncoding:'ieee-p1363' in .sign and .verify if you want that
dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70
  • Thanks. This answers my question. And a lot of useful links are there. Sorry, I could not upvote it because of the lack of reputation. – Anuj Kumar Apr 16 '23 at 19:30