var assert = require('assert')
var BigInteger = require('bigi')
var Point = require('./point')
function Curve (p, a, b, Gx, Gy, n, h) {
this.p = p
this.a = a
this.b = b
this.G = Point.fromAffine(this, Gx, Gy)
this.n = n
this.h = h
this.infinity = new Point(this, null, null, BigInteger.ZERO)
// result caching
this.pOverFour = p.add(BigInteger.ONE).shiftRight(2)
// determine size of p in bytes
this.pLength = Math.floor((this.p.bitLength() + 7) / 8)
}
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) // XXX: not compatible with all curves
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) {
if (Q === this.infinity) return true
return Q.z.signum() === 0 && Q.y.signum() !== 0
}
Curve.prototype.isOnCurve = function (Q) {
if (this.isInfinity(Q)) return true
var x = Q.affineX
var y = Q.affineY
var a = this.a
var b = this.b
var p = this.p
// Check that xQ and yQ are integers in the interval [0, p - 1]
if (x.signum() < 0 || x.compareTo(p) >= 0) return false
if (y.signum() < 0 || y.compareTo(p) >= 0) return false
// and check that y^2 = x^3 + ax + b (mod p)
var lhs = y.square().mod(p)
var rhs = x.pow(3).add(a.multiply(x)).add(b).mod(p)
return lhs.equals(rhs)
}
/**
* Validate an elliptic curve point.
*
* See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive
*/
Curve.prototype.validate = function (Q) {
// Check Q != O
assert(!this.isInfinity(Q), 'Point is at infinity')
assert(this.isOnCurve(Q), 'Point is not on the curve')
// Check nQ = O (where Q is a scalar multiple of G)
var nQ = Q.multiply(this.n)
assert(this.isInfinity(nQ), 'Point is not a scalar multiple of G')
return true
}
module.exports = Curve