Skip to content

Commit

Permalink
curve: adds pointFromX and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dcousens committed Jun 21, 2014
1 parent c24e519 commit 91296c1
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 24 deletions.
15 changes: 15 additions & 0 deletions lib/curve.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@ function Curve(p, a, b, Gx, Gy, n, h) {
this.h = h

this.infinity = new Point(this, null, null, BigInteger.ZERO)

// result caching
this.pOverFour = p.add(BigInteger.ONE).shiftRight(2)
}

Curve.prototype.pointFromX = function(isOdd, x) {
var alpha = x.pow(3).add(this.a.multiply(x)).add(this.b).mod(this.p)
var beta = alpha.modPow(this.pOverFour, this.p)

var y = beta
if (beta.isEven() ^ !isOdd) {
y = this.p.subtract(y) // -y % p
}

return Point.fromAffine(this, x, y)
}

Curve.prototype.isInfinity = function(Q) {
Expand Down
33 changes: 9 additions & 24 deletions lib/point.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,44 +217,29 @@ Point.prototype.getEncoded = function(compressed) {
}

Point.decodeFrom = function(curve, buffer) {
var type = buffer.readUInt8(0);
var type = buffer.readUInt8(0)
var compressed = (type !== 4)
var x = BigInteger.fromBuffer(buffer.slice(1, 33))
var y

var x = BigInteger.fromBuffer(buffer.slice(1, 33))
var byteLength = Math.floor((curve.p.bitLength() + 7) / 8)

var Q
if (compressed) {
assert.equal(buffer.length, byteLength + 1, 'Invalid sequence length')
assert(type === 0x02 || type === 0x03, 'Invalid sequence tag')

var isYEven = (type === 0x02)
var a = curve.a
var b = curve.b
var p = curve.p

// 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)
}

// Convert x to point
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.
y = (beta.isEven() ^ isYEven) ? p.subtract(beta) : beta
var isOdd = (type === 0x03)
Q = curve.pointFromX(isOdd, x)

} else {
assert.equal(buffer.length, 1 + byteLength + byteLength, 'Invalid sequence length')

y = BigInteger.fromBuffer(buffer.slice(1 + byteLength))
var y = BigInteger.fromBuffer(buffer.slice(1 + byteLength))
Q = Point.fromAffine(curve, x, y)
}

var pt = Point.fromAffine(curve, x, y)
pt.compressed = compressed
return pt
Q.compressed = compressed
return Q
}

Point.prototype.toString = function () {
Expand Down
17 changes: 17 additions & 0 deletions test/curve.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ var Curve = ecurve.Curve
var Point = ecurve.Point

var fixtures = require('./fixtures/curve')
var pointFixtures = require('./fixtures/point')

describe('Ecurve', function() {
it('should create curve objects', function() {
Expand Down Expand Up @@ -218,4 +219,20 @@ describe('Ecurve', function() {
// }, /Point is not a scalar multiple of G/)
// })
})

describe('pointFromX', function() {
pointFixtures.valid.forEach(function(f) {
var curve = getCurveByName(f.curve)

var x = new BigInteger(f.x)
var odd = !(new BigInteger(f.y).isEven())

it('recovers Y coordinate ' + f.y + ' for curve ' + f.curve + ' correctly', function() {
var actual = curve.pointFromX(odd, x)

assert.equal(actual.affineX.toString(), f.x)
assert.equal(actual.affineY.toString(), f.y)
})
})
})
})

0 comments on commit 91296c1

Please sign in to comment.