UNPKG

1.88 kBJavaScriptView Raw
1var assert = require('assert')
2var BigInteger = require('bigi')
3
4var Point = require('./point')
5
6function Curve (p, a, b, Gx, Gy, n, h) {
7 this.p = p
8 this.a = a
9 this.b = b
10 this.G = Point.fromAffine(this, Gx, Gy)
11 this.n = n
12 this.h = h
13
14 this.infinity = new Point(this, null, null, BigInteger.ZERO)
15
16 // result caching
17 this.pOverFour = p.add(BigInteger.ONE).shiftRight(2)
18}
19
20Curve.prototype.pointFromX = function (isOdd, x) {
21 var alpha = x.pow(3).add(this.a.multiply(x)).add(this.b).mod(this.p)
22 var beta = alpha.modPow(this.pOverFour, this.p) // XXX: not compatible with all curves
23
24 var y = beta
25 if (beta.isEven() ^ !isOdd) {
26 y = this.p.subtract(y) // -y % p
27 }
28
29 return Point.fromAffine(this, x, y)
30}
31
32Curve.prototype.isInfinity = function (Q) {
33 if (Q === this.infinity) return true
34
35 return Q.z.signum() === 0 && Q.y.signum() !== 0
36}
37
38Curve.prototype.isOnCurve = function (Q) {
39 if (this.isInfinity(Q)) return true
40
41 var x = Q.affineX
42 var y = Q.affineY
43 var a = this.a
44 var b = this.b
45 var p = this.p
46
47 // Check that xQ and yQ are integers in the interval [0, p - 1]
48 if (x.signum() < 0 || x.compareTo(p) >= 0) return false
49 if (y.signum() < 0 || y.compareTo(p) >= 0) return false
50
51 // and check that y^2 = x^3 + ax + b (mod p)
52 var lhs = y.square().mod(p)
53 var rhs = x.pow(3).add(a.multiply(x)).add(b).mod(p)
54 return lhs.equals(rhs)
55}
56
57/**
58 * Validate an elliptic curve point.
59 *
60 * See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive
61 */
62Curve.prototype.validate = function (Q) {
63 // Check Q != O
64 assert(!this.isInfinity(Q), 'Point is at infinity')
65 assert(this.isOnCurve(Q), 'Point is not on the curve')
66
67 // Check nQ = O (where Q is a scalar multiple of G)
68 var nQ = Q.multiply(this.n)
69 assert(this.isInfinity(nQ), 'Point is not a scalar multiple of G')
70
71 return true
72}
73
74module.exports = Curve