Skip to content

Commit 8ccb522

Browse files
committed
Fix point at infinity verification in signature and public key
1 parent 7ede23d commit 8ccb522

File tree

7 files changed

+51
-14
lines changed

7 files changed

+51
-14
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Given a version number MAJOR.MINOR.PATCH, increment:
1313

1414

1515
## [Unreleased]
16+
### Fixed
17+
- point at infinity verification in signature and public key
1618

1719
## [1.1.3] - 2021-11-04
1820
### Fixed

ellipticcurve/curve.js

+15-6
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,23 @@ class CurveFp {
1919
this.name = name;
2020
this.nistName = nistName;
2121
this._oid = oid;
22+
};
2223

23-
this.contains = function (p) {
24-
return modulo(((p.y.pow(2)).minus((p.x.pow(3)).add(this.A.multiply(p.x)).add(this.B))), this.P).equals(0);
25-
};
24+
contains(p) {
25+
if (p.x < 0 || p.x > this.P.minus(1)) {
26+
return false;
27+
}
28+
if (p.y < 0 || p.y > this.P.minus(1)) {
29+
return false;
30+
}
31+
if (!modulo(((p.y.pow(2)).minus((p.x.pow(3)).add(this.A.multiply(p.x)).add(this.B))), this.P).equals(0)) {
32+
return false;
33+
}
34+
return true;
35+
};
2636

27-
this.length = function () {
28-
return Math.floor((1 + this.N.toString(16).length) / 2);
29-
};
37+
length() {
38+
return Math.floor((1 + this.N.toString(16).length) / 2);
3039
};
3140

3241
get oid() {

ellipticcurve/ecdsa.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ exports.verify = function (message, signature, publicKey, hashfunc=sha256) {
4343
let inv = EcdsaMath.inv(sigS, curve.N);
4444
let u1 = EcdsaMath.multiply(curve.G, modulo((numberMessage.multiply(inv)), curve.N), curve.N, curve.A, curve.P);
4545
let u2 = EcdsaMath.multiply(publicKey.point, modulo((sigR.multiply(inv)), curve.N), curve.N, curve.A, curve.P);
46-
let add = EcdsaMath.add(u1, u2, curve.A, curve.P);
47-
return sigR.eq(add.x);
46+
let v = EcdsaMath.add(u1, u2, curve.A, curve.P);
47+
if (v.isAtInfinity()) {
48+
return false;
49+
}
50+
return v.x.mod(curve.N).eq(sigR);
4851
};

ellipticcurve/math.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ var jacobianDouble = function (p, A, P) {
100100
// :param A: Coefficient of the first-order term of the equation Y^2 = X^3 + A*X + B (mod p)
101101
// :return: Point that represents the sum of First and Second Point
102102

103-
if (!p.y.value) {
103+
if (p.y == 0) {
104104
return new Point(BigInt(0), BigInt(0), BigInt(0));
105105
};
106106
let ysq = modulo((p.y.pow(2)), P);
@@ -123,10 +123,10 @@ var jacobianAdd = function (p, q, A, P) {
123123
// :param A: Coefficient of the first-order term of the equation Y^2 = X^3 + A*X + B (mod p)
124124
// :return: Point that represents the sum of First and Second Point
125125

126-
if (!p.y.value) {
126+
if (p.y == 0) {
127127
return q;
128128
};
129-
if (!q.y.value) {
129+
if (q.y == 0) {
130130
return p;
131131
};
132132

ellipticcurve/point.js

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ class Point {
77
this.y = y;
88
this.z = z;
99
}
10+
11+
isAtInfinity() {
12+
return this.y == 0;
13+
}
1014
}
1115

1216

ellipticcurve/publicKey.js

+13-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const BinaryAscii = require("./utils/binary");
22
const EcdsaCurve = require("./curve");
33
const Point = require("./point").Point;
44
const der = require("./utils/der");
5+
const Math = require("./math");
56

67

78
class PublicKey {
@@ -86,11 +87,20 @@ class PublicKey {
8687

8788
let p = new Point(BinaryAscii.numberFromString(xs), BinaryAscii.numberFromString(ys));
8889

89-
if (validatePoint & !curve.contains(p)) {
90+
let publicKey = new PublicKey(p, curve);
91+
if (!validatePoint) {
92+
return publicKey;
93+
}
94+
if (p.isAtInfinity()) {
95+
throw new Error("Public Key point is at infinity");
96+
}
97+
if (!curve.contains(p)) {
9098
throw new Error("point (" + p.x + "," + p.y + ") is not valid for curve " + curve.name);
9199
}
92-
93-
return new PublicKey(p, curve);
100+
if (!Math.multiply(p, curve.N, curve.N, curve.A, curve.P).isAtInfinity()) {
101+
throw new Error("Point (" + p.x + "," + p.y + " * " + curve.name + ".N is not at infinity");
102+
}
103+
return publicKey
94104
};
95105
};
96106

test/test.js

+9
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ describe("ECDSA test", function() {
3030
assert.equal(Ecdsa.verify(message2, signature, publicKey), false);
3131
});
3232
});
33+
describe("#testZeroSignature()", function() {
34+
it("should deny authenticity", function() {
35+
let privateKey = new PrivateKey();
36+
let publicKey = privateKey.publicKey();
37+
let message = "This is the right message";
38+
39+
assert.equal(Ecdsa.verify(message, new Signature(0, 0), publicKey), false);
40+
});
41+
});
3342
});
3443
describe("openSSL test", function() {
3544
describe("#testAssign()", function() {

0 commit comments

Comments
 (0)