Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,42 +36,42 @@
"url": "https://github.com/bitcoinjs/bitcoinjs-lib.git"
},
"devDependencies": {
"mocha": "1.18.2",
"istanbul": "0.1.30",
"uglify-js": "2.4.13",
"sinon": "1.9.0",
"browserify": "~4.1.5",
"coveralls": "~2.10.0",
"mocha-lcov-reporter": "0.0.1",
"helloblock-js": "^0.2.1",
"browserify": "~4.1.5",
"jshint": "2.5.1"
"istanbul": "0.1.30",
"jshint": "2.5.1",
"mocha": "1.18.2",
"mocha-lcov-reporter": "0.0.1",
"sinon": "1.9.0",
"uglify-js": "2.4.13"
},
"testling": {
"browsers": [
"android-browser/4.2..latest",
"chrome/20..latest",
"firefox/21..latest",
"safari/latest",
"opera/15..latest",
"iphone/6..latest",
"ipad/6..latest",
"android-browser/4.2..latest"
"iphone/6..latest",
"opera/15..latest",
"safari/latest"
],
"harness": "mocha-bdd",
"files": "test/*.js"
},
"scripts": {
"unit": "./node_modules/.bin/istanbul test ./node_modules/.bin/_mocha -- --reporter list `find test -maxdepth 1 -not -type d`",
"test": "npm run-script unit",
"integration": "./node_modules/.bin/_mocha --reporter list test/integration/*.js",
"jshint": "./node_modules/.bin/jshint --config jshint.json src/*.js ; true",
"compile": "./node_modules/.bin/browserify ./src/index.js -s Bitcoin | ./node_modules/.bin/uglifyjs > bitcoinjs-min.js",
"coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- --reporter list test/*.js",
"coveralls": "npm run-script coverage && node ./node_modules/.bin/coveralls < coverage/lcov.info",
"compile": "./node_modules/.bin/browserify ./src/index.js -s Bitcoin | ./node_modules/.bin/uglifyjs > bitcoinjs-min.js"
"integration": "./node_modules/.bin/_mocha --reporter list test/integration/*.js",
"jshint": "./node_modules/.bin/jshint --config jshint.json src/*.js ; true",
"test": "npm run-script unit",
"unit": "./node_modules/.bin/istanbul test ./node_modules/.bin/_mocha -- --reporter list `find test -maxdepth 1 -not -type d`"
},
"dependencies": {
"bigi": "1.1.0",
"crypto-js": "3.1.2-3",
"ecurve": "0.9.0",
"ecurve": "0.10.0",
"secure-random": "0.2.1"
}
}
52 changes: 27 additions & 25 deletions src/ecdsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var BigInteger = require('bigi')
var ECSignature = require('./ecsignature')
var Point = require('ecurve').Point

// https://tools.ietf.org/html/rfc6979#section-3.2
function deterministicGenerateK(curve, hash, d) {
assert(Buffer.isBuffer(hash), 'Hash must be a Buffer, not ' + hash)
assert.equal(hash.length, 32, 'Hash must be 256 bit')
Expand All @@ -13,22 +14,40 @@ function deterministicGenerateK(curve, hash, d) {
var x = d.toBuffer(32)
var k = new Buffer(32)
var v = new Buffer(32)
k.fill(0)

// Step B
v.fill(1)

// Step C
k.fill(0)

// Step D
k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([0]), x, hash]), k)

// Step E
v = crypto.HmacSHA256(v, k)

// Step F
k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([1]), x, hash]), k)

// Step G
v = crypto.HmacSHA256(v, k)

// Step H1/H2a, ignored as tlen === qlen (256 bit)
// Step H2b
v = crypto.HmacSHA256(v, k)

var n = curve.n
var kB = BigInteger.fromBuffer(v).mod(n)
assert(kB.compareTo(BigInteger.ONE) > 0, 'Invalid k value')
assert(kB.compareTo(n) < 0, 'Invalid k value')
var T = BigInteger.fromBuffer(v)

return kB
// Step H3, repeat until T is within the interval [1, n - 1]
while ((T.signum() <= 0) || (T.compareTo(curve.n) >= 0)) {
k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([0])]), k)
v = crypto.HmacSHA256(v, k)

T = BigInteger.fromBuffer(v)
}

return T
}

function sign(curve, hash, d) {
Expand Down Expand Up @@ -97,37 +116,20 @@ function recoverPubKey(curve, e, signature, i) {
var s = signature.s

// A set LSB signifies that the y-coordinate is odd
// By reduction, the y-coordinate is even if it is clear
var isYEven = !(i & 1)
var isYOdd = i & 1

// The more significant bit specifies whether we should use the
// first or second candidate key.
var isSecondKey = i >> 1

var n = curve.n
var G = curve.G
var p = curve.p
var a = curve.a
var b = curve.b

// We precalculate (p + 1) / 4 where p is the field order
if (!curve.P_OVER_FOUR) {
curve.P_OVER_FOUR = p.add(BigInteger.ONE).shiftRight(2)
}

// 1.1 Let x = r + jn
var x = isSecondKey ? r.add(n) : r

// 1.2, 1.3 Convert x to a point R using routine specified in Section 2.3.4
var alpha = x.pow(3).add(a.multiply(x)).add(b).mod(p)
var beta = alpha.modPow(curve.P_OVER_FOUR, p)

// If beta is even, but y isn't, or vice versa, then convert it,
// otherwise we're done and y == beta.
var y = (beta.isEven() ^ isYEven) ? p.subtract(beta) : beta
var R = curve.pointFromX(isYOdd, x)

// 1.4 Check that nR is at infinity
var R = Point.fromAffine(curve, x, y)
var nR = R.multiply(n)
assert(curve.isInfinity(nR), 'nR is not a valid curve point')

Expand Down
18 changes: 17 additions & 1 deletion test/ecdsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var crypto = require('../src/crypto')
var ecdsa = require('../src/ecdsa')
var message = require('../src/message')
var networks = require('../src/networks')
var sinon = require('sinon')

var BigInteger = require('bigi')
var ECSignature = require('../src/ecsignature')
Expand All @@ -15,14 +16,29 @@ var fixtures = require('./fixtures/ecdsa.json')
describe('ecdsa', function() {
describe('deterministicGenerateK', function() {
fixtures.valid.forEach(function(f) {
it('determines k for \"' + f.message + '\"', function() {
it('for \"' + f.message + '\"', function() {
var d = BigInteger.fromHex(f.d)
var h1 = crypto.sha256(f.message)

var k = ecdsa.deterministicGenerateK(curve, h1, d)
assert.equal(k.toHex(), f.k)
})
})

it('loops until an appropriate k value is found', sinon.test(function() {
this.mock(BigInteger).expects('fromBuffer')
.exactly(3)
.onCall(0).returns(new BigInteger('0'))
.onCall(1).returns(curve.n)
.onCall(2).returns(new BigInteger('42'))

var d = new BigInteger('1')
var h1 = new Buffer(32)

var k = ecdsa.deterministicGenerateK(curve, h1, d)

assert.equal(k.toString(), '42')
}))
})

describe('recoverPubKey', function() {
Expand Down
2 changes: 1 addition & 1 deletion test/eckey.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('ECKey', function() {
var d = new BigInteger(f.d)
var privKey = new ECKey(d)

assert.equal(privKey.pub.Q.toString(), f.Q.toString())
assert.equal(privKey.pub.Q.toString(), f.Q)
})
})

Expand Down