port message to common.js style and add tests

This commit is contained in:
Roman Shtylman 2013-03-02 12:28:13 -05:00
parent 981203e982
commit 41f0027883
4 changed files with 59 additions and 24 deletions

View file

@ -70,7 +70,7 @@ var ECDSA = {
r = sig.r;
s = sig.s;
} else {
throw "Invalid value for signature";
throw new Error("Invalid value for signature");
}
var Q;
@ -79,7 +79,7 @@ var ECDSA = {
} else if (util.isArray(pubkey)) {
Q = ECPointFp.decodeFrom(ecparams.getCurve(), pubkey);
} else {
throw "Invalid format for pubkey value, must be byte array or ECPointFp";
throw new Error("Invalid format for pubkey value, must be byte array or ECPointFp");
}
var e = BigInteger.fromByteArrayUnsigned(hash);
@ -176,14 +176,14 @@ var ECDSA = {
parseSigCompact: function (sig) {
if (sig.length !== 65) {
throw "Signature has the wrong length";
throw new Error("Signature has the wrong length");
}
// Signature is prefixed with a type byte storing three bits of
// information.
var i = sig[0] - 27;
if (i < 0 || i > 7) {
throw "Invalid signature type";
throw new Error("Invalid signature type");
}
var n = ecparams.getN();
@ -253,10 +253,13 @@ var ECDSA = {
Q.validate();
if (!ECDSA.verifyRaw(e, r, s, Q)) {
throw "Pubkey recovery unsuccessful";
throw new Error("Pubkey recovery unsuccessful");
}
var pubKey = new Bitcoin.ECKey();
// TODO (shtylman) this is stupid because this file and eckey
// have circular dependencies
var ECKey = require('./eckey');
var pubKey = ECKey();
pubKey.pub = Q;
return pubKey;
},
@ -275,14 +278,13 @@ var ECDSA = {
calcPubkeyRecoveryParam: function (address, r, s, hash)
{
for (var i = 0; i < 4; i++) {
try {
var pubkey = Bitcoin.ECDSA.recoverPubKey(r, s, hash, i);
if (pubkey.getBitcoinAddress().toString() == address) {
return i;
}
} catch (e) {}
var pubkey = ECDSA.recoverPubKey(r, s, hash, i);
if (pubkey.getBitcoinAddress().toString() == address) {
return i;
}
}
throw "Unable to find valid recovery factor";
throw new Error("Unable to find valid recovery factor");
}
};

View file

@ -25,6 +25,7 @@ var endian = function (n) {
module.exports = {
Address: require('./address'),
Key: require('./eckey'),
Message: require('./message'),
BigInteger: require('./jsbn/jsbn'),
Script: require('./script'),
Opcode: require('./opcode'),

View file

@ -1,6 +1,10 @@
/**
* Implements Bitcoin's feature for signing arbitrary messages.
*/
/// Implements Bitcoin's feature for signing arbitrary messages.
var Crypto = require('./crypto-js/crypto');
var ecdsa = require('./ecdsa');
var conv = require('./convert');
var util = require('./util');
var Message = {};
Message.magicPrefix = "Bitcoin Signed Message:\n";
@ -10,9 +14,9 @@ Message.makeMagicMessage = function (message) {
var messageBytes = Crypto.charenc.UTF8.stringToBytes(message);
var buffer = [];
buffer = buffer.concat(Bitcoin.Util.numToVarInt(magicBytes.length));
buffer = buffer.concat(util.numToVarInt(magicBytes.length));
buffer = buffer.concat(magicBytes);
buffer = buffer.concat(Bitcoin.Util.numToVarInt(messageBytes.length));
buffer = buffer.concat(util.numToVarInt(messageBytes.length));
buffer = buffer.concat(messageBytes);
return buffer;
@ -28,10 +32,10 @@ Message.signMessage = function (key, message, compressed) {
var sig = key.sign(hash);
var obj = Bitcoin.ECDSA.parseSig(sig);
var obj = ecdsa.parseSig(sig);
var address = key.getBitcoinAddress().toString();
var i = Bitcoin.ECDSA.calcPubkeyRecoveryParam(address, obj.r, obj.s, hash);
var i = ecdsa.calcPubkeyRecoveryParam(address, obj.r, obj.s, hash);
i += 27;
if (compressed) i += 4;
@ -45,17 +49,17 @@ Message.signMessage = function (key, message, compressed) {
sig = [i].concat(rBa).concat(sBa);
return Crypto.util.bytesToBase64(sig);
return conv.bytesToBase64(sig);
};
Message.verifyMessage = function (address, sig, message) {
sig = Crypto.util.base64ToBytes(sig);
sig = Bitcoin.ECDSA.parseSigCompact(sig);
sig = conv.base64ToBytes(sig);
sig = ecdsa.parseSigCompact(sig);
var hash = Message.getHash(message);
var isCompressed = !!(sig.i & 4);
var pubKey = Bitcoin.ECDSA.recoverPubKey(sig.r, sig.s, hash, sig.i);
var pubKey = ecdsa.recoverPubKey(sig.r, sig.s, hash, sig.i);
pubKey.setCompressed(isCompressed);

28
test/message.js Normal file
View file

@ -0,0 +1,28 @@
var assert = require('assert');
var Message = require('../').Message;
var Key = require('../').Key;
var hexToBytes = require('../').convert.hexToBytes;
var priv = '18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725';
var addr = '16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM';
var msg = 'foobar';
test('create', function() {
var key = Key(hexToBytes(priv));
assert.equal(key.getBitcoinAddress().toString(), addr);
var sig = Message.signMessage(key, msg);
assert.ok(Message.verifyMessage(addr, sig, msg));
// wrong message
assert.ok(!Message.verifyMessage(addr, sig, 'not foobar'));
// wrong address
assert.ok(!Message.verifyMessage('1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a', sig, msg));
});
test('incorrect signature', function() {
// wrong signature
var priv = '5HwoXVkHoRM8sL2KmNRS217n1g8mPPBomrY7yehCuXC1115WWsh';
var key = Key(hexToBytes(priv));
var sig = Message.signMessage(key, msg);
assert.ok(!Message.verifyMessage(addr, sig, msg));
});