Merge pull request #150 from dcousens/bigitests

Adds BI.toPaddedBuffer and toBuffer
This commit is contained in:
Wei Lu 2014-04-25 00:19:33 +08:00
commit 373b05de2c
8 changed files with 129 additions and 26 deletions

View file

@ -55,12 +55,11 @@ function decode(string) {
i++ i++
} }
// FIXME: If BigInteger supported buffers, this could be a copy var buffer = num.toBuffer()
var buffer = new Buffer(num.toByteArrayUnsigned()) var leadz = new Buffer(i)
var padding = new Buffer(i) leadz.fill(0)
padding.fill(0)
return Buffer.concat([padding, buffer]) return Buffer.concat([leadz, buffer])
} }
module.exports = { module.exports = {

View file

@ -1,7 +1,17 @@
var assert = require('assert') var assert = require('assert')
var BigInteger = require('bigi') var BigInteger = require('bigi')
// Import operations
BigInteger.fromHex = function(hex) {
var buffer = new Buffer(hex, 'hex')
assert.equal(buffer.length, Buffer.byteLength(hex) / 2)
return BigInteger.fromBuffer(buffer)
}
BigInteger.fromBuffer = function(buffer) { BigInteger.fromBuffer = function(buffer) {
assert(Array.isArray(buffer) || Buffer.isBuffer(buffer)) // FIXME: Transitionary
// FIXME: Transitionary // FIXME: Transitionary
if (Buffer.isBuffer(buffer)) { if (Buffer.isBuffer(buffer)) {
buffer = Array.prototype.slice.call(buffer) buffer = Array.prototype.slice.call(buffer)
@ -10,4 +20,19 @@ BigInteger.fromBuffer = function(buffer) {
return BigInteger.fromByteArrayUnsigned(buffer) return BigInteger.fromByteArrayUnsigned(buffer)
} }
// Export operations
BigInteger.prototype.toBuffer = function(s) {
if (s != undefined) assert(Number.isFinite(s))
var buffer = new Buffer(this.toByteArrayUnsigned())
var padded = new Buffer(s - buffer.length)
padded.fill(0)
return Buffer.concat([padded, buffer], s)
}
BigInteger.prototype.toHex = function(s) {
return this.toBuffer(s).toString('hex')
}
module.exports = BigInteger module.exports = BigInteger

View file

@ -65,13 +65,7 @@ ECKey.prototype.sign = function(hash) {
// Export functions // Export functions
ECKey.prototype.toBuffer = function() { ECKey.prototype.toBuffer = function() {
var buffer = new Buffer(this.D.toByteArrayUnsigned()) return this.D.toBuffer(32)
// pad out to atleast 32 bytes
var padded = new Buffer(32 - buffer.length)
padded.fill(0)
return Buffer.concat([padded, buffer])
} }
ECKey.prototype.toHex = function() { ECKey.prototype.toHex = function() {
return this.toBuffer().toString('hex') return this.toBuffer().toString('hex')

View file

@ -25,25 +25,18 @@ function magicHash(message) {
// TODO: parameterize compression instead of using ECKey.compressed // TODO: parameterize compression instead of using ECKey.compressed
function sign(key, message) { function sign(key, message) {
var hash = magicHash(message) var hash = magicHash(message)
var sig = key.sign(hash) var sig = ecdsa.parseSig(key.sign(hash))
var obj = ecdsa.parseSig(sig) var i = ecdsa.calcPubKeyRecoveryParam(key.pub.Q, sig.r, sig.s, hash)
var i = ecdsa.calcPubKeyRecoveryParam(key.pub.Q, obj.r, obj.s, hash)
i += 27 i += 27
if (key.pub.compressed) { if (key.pub.compressed) {
i += 4 i += 4
} }
var rBa = obj.r.toByteArrayUnsigned() var rB = sig.r.toBuffer(32)
var sBa = obj.s.toByteArrayUnsigned() var sB = sig.s.toBuffer(32)
// Pad to 32 bytes per value return Buffer.concat([new Buffer([i]), rB, sB], 65)
while (rBa.length < 32) rBa.unshift(0);
while (sBa.length < 32) sBa.unshift(0);
sig = [i].concat(rBa, sBa)
return sig
} }
// FIXME: stricter API? // FIXME: stricter API?

46
test/bigi.js Normal file
View file

@ -0,0 +1,46 @@
var assert = require('assert')
var BigInteger = require('../').BigInteger
var fixtures = require('./fixtures/bigi')
describe('BigInteger', function() {
describe('fromBuffer/fromHex', function() {
it('should match the test vectors', function() {
fixtures.valid.forEach(function(f) {
assert.equal(BigInteger.fromHex(f.hex).toString(), f.dec)
assert.equal(BigInteger.fromHex(f.hexPadded).toString(), f.dec)
})
})
fixtures.invalid.forEach(function(f) {
it('throws on ' + f.description, function() {
assert.throws(function() {
BigInteger.fromHex(f.string)
})
})
})
})
describe('toBuffer/toHex', function() {
it('should match the test vectors', function() {
fixtures.valid.forEach(function(f) {
var bi = new BigInteger(f.dec)
assert.equal(bi.toHex(), f.hex)
assert.equal(bi.toHex(32), f.hexPadded)
})
})
it('throws on non-finite padding value', function() {
var bi = new BigInteger('1')
assert.throws(function() { bi.toHex({}) })
assert.throws(function() { bi.toHex([]) })
assert.throws(function() { bi.toHex('') })
assert.throws(function() { bi.toHex(0 / 0) })
assert.throws(function() { bi.toHex(1 / 0) })
})
})
})
module.exports = BigInteger

View file

@ -39,7 +39,7 @@ describe('ecdsa', function() {
var sig_a = s1.sign([0]) var sig_a = s1.sign([0])
assert.ok(sig_a, 'Sign null') assert.ok(sig_a, 'Sign null')
assert.ok(s1.pub.verify(BigInteger.ZERO, sig_a)) assert.ok(s1.pub.verify([0], sig_a))
var message = new Buffer(1024) // More or less random :P var message = new Buffer(1024) // More or less random :P
var hash = crypto.sha256(message) var hash = crypto.sha256(message)

46
test/fixtures/bigi.js vendored Normal file
View file

@ -0,0 +1,46 @@
module.exports = {
"valid": [
{
"dec": "1",
"hex": "01",
"hexPadded": "0000000000000000000000000000000000000000000000000000000000000001"
},
{
"dec": "158798437896437949616241483468158498679",
"hex": "77777777777777777777777777777777",
"hexPadded": "0000000000000000000000000000000077777777777777777777777777777777"
},
{
"dec": "115792089237316195423570985008687907852837564279074904382605163141518161494336",
"hex": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
"hexPadded": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140"
},
{
"dec": "48968302285117906840285529799176770990048954789747953886390402978935544927851",
"hex": "6c4313b03f2e7324d75e642f0ab81b734b724e13fec930f309e222470236d66b",
"hexPadded": "6c4313b03f2e7324d75e642f0ab81b734b724e13fec930f309e222470236d66b"
}
],
"invalid": [
{
"description": "non-hex string",
"string": "invalid"
},
{
"description": "non-hex alphabet",
"string": "c2F0b3NoaQo="
},
{
"description": "internal whitespace",
"string": "11111 11111"
},
{
"description": "leading whitespace",
"string": " 1111111111"
},
{
"description": "trailing whitespace",
"string": "1111111111 "
}
]
}