Skip to content

Commit 302800f

Browse files
committed
Fix #11: add parameter validation
1 parent 27bc5c1 commit 302800f

File tree

4 files changed

+58
-6
lines changed

4 files changed

+58
-6
lines changed

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@enumatech/secp256k1-js",
3-
"version": "1.0.0",
3+
"version": "1.0.1",
44
"description": "Pure JS implementation of secp256k1 signing, verification, recovery ECDSA.",
55
"engines": {
66
"node": ">=14.0.0"

src/secp256k1.js

+14
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,15 @@
7070
return JtoA(PUBinJ)
7171
}
7272

73+
function assert(cond, msg) {
74+
if (!cond) {
75+
throw Error("assertion failed: " + msg)
76+
}
77+
}
78+
7379
function ecsign(d, z) {
80+
assert(d != 0, "d must not be 0")
81+
assert(z != 0, "z must not be 0")
7482
while (true) {
7583
const k = rnd(P)
7684
const R = mulG(k)
@@ -182,6 +190,9 @@
182190
}
183191

184192
function ecrecover(recId, sigr, sigs, message) {
193+
assert(recId >= 0 && recId <= 3, "recId must be 0..3")
194+
assert(sigr != 0, "sigr must not be 0")
195+
assert(sigs != 0, "sigs must not be 0")
185196
// 1.0 For j from 0 to h (h == recId here and the loop is outside this function)
186197
// 1.1 Let x = r + jn
187198
const x = addmod(uint256(sigr), P.muln(recId >> 1), P)
@@ -227,6 +238,9 @@
227238
}
228239

229240
function ecverify (Qx, Qy, sigr, sigs, z) {
241+
if (sigs == 0 || sigr == 0) {
242+
return false
243+
}
230244
const w = invmod(sigs, N)
231245
const u1 = mulmod(z, w, N)
232246
const u2 = mulmod(sigr, w, N)

test/test.js

+42-4
Original file line numberDiff line numberDiff line change
@@ -51,32 +51,41 @@ describe('secp256k1', () => {
5151
Assert.ok(/^[0-9a-f]{64}$/.test(sig.s), 'sig.s is not a hex string')
5252
Assert.ok(sig.v===0 || sig.v===1, 'sig.v is not a 0 or 1')
5353
if (Secp256k1Node) {
54-
const success = Secp256k1Node.verify(B(z), Buffer.concat([B(sig.r), B(sig.s)]), Buffer.concat([Buffer('\04'), B(pubX), B(pubY)]))
54+
const success = Secp256k1Node.verify(B(z), Buffer.concat([B(sig.r), B(sig.s)]), Buffer.concat([Buffer.from('\04'), B(pubX), B(pubY)]))
5555
Assert.ok(success, JSON.stringify(sig))
5656
}
5757
})
5858

5959
it('has recovery bit', () => {
6060
const sig = Secp256k1.ecsign(d, z)
6161
if (Secp256k1Node) {
62-
const success = Secp256k1Node.verify(B(z), Buffer.concat([B(sig.r), B(sig.s)]), Buffer.concat([Buffer('\04'), B(pubX), B(pubY)]))
62+
const success = Secp256k1Node.verify(B(z), Buffer.concat([B(sig.r), B(sig.s)]), Buffer.concat([Buffer.from('\04'), B(pubX), B(pubY)]))
6363
Assert.ok(success, JSON.stringify(sig))
6464
const Q = Secp256k1Node.recover(B(z), Buffer.concat([B(sig.r), B(sig.s)]), sig.v, false)
6565
Assert.deepStrictEqual({x: Q.toString('hex').substr(2,64), y: Q.toString('hex').slice(-64)}, {x: pubX.toString(16), y: pubY.toString(16)})
6666
}
6767
})
6868

69-
it('can verify self', () => {
69+
it('can verify ours', () => {
7070
const sig = Secp256k1.ecsign(d, z)
7171
Assert.ok(Secp256k1.ecverify(pubX, pubY, Secp256k1.uint256(sig.r,16), Secp256k1.uint256(sig.s,16), z))
7272
})
7373

74+
it('can verify known sig', () => {
75+
Assert.ok(Secp256k1.ecverify(pubX, pubY, Secp256k1.uint256(r,16), Secp256k1.uint256(s,16), z))
76+
})
77+
7478
it('can verify fff...', () => {
7579
const z = Secp256k1.uint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)
7680
const sig = Secp256k1.ecsign(d, z)
7781
Assert.ok(Secp256k1.ecverify(pubX, pubY, Secp256k1.uint256(sig.r,16), Secp256k1.uint256(sig.s,16), z))
7882
})
7983

84+
it('cannot sign 000...', () => {
85+
const z = Secp256k1.uint256("0000000000000000000000000000000000000000000000000000000000000000", 16)
86+
Assert.throws(() => Secp256k1.ecsign(d, z), "assertion failed: z must not be 0")
87+
})
88+
8089
it('can verify other sig', () => {
8190
if (Secp256k1Node) {
8291
const sig = Secp256k1Node.sign(B(z), B(d))
@@ -86,6 +95,14 @@ describe('secp256k1', () => {
8695
Assert.ok(Secp256k1.ecverify(pubX, pubY, Secp256k1.uint256(r,16), Secp256k1.uint256(s,16), z))
8796
})
8897

98+
it('verify fails if r=0', () => {
99+
Assert.isFalse(Secp256k1.ecverify(pubX, pubY, Secp256k1.uint256(0), Secp256k1.uint256(s,16), z))
100+
})
101+
102+
it('verify fails if s=0', () => {
103+
Assert.isFalse(Secp256k1.ecverify(pubX, pubY, Secp256k1.uint256(r,16), Secp256k1.uint256(0), z))
104+
})
105+
89106
it('can recover other sig', () => {
90107
if (Secp256k1Node) {
91108
const sig = Secp256k1Node.sign(B(z), B(d))
@@ -97,9 +114,30 @@ describe('secp256k1', () => {
97114
Assert.deepStrictEqual(Q, {x: pubX.toString(16), y: pubY.toString(16)})
98115
})
99116

100-
it('can recover self', () => {
117+
it('can recover ours', () => {
101118
const sig = Secp256k1.ecsign(d, z)
102119
const Q = Secp256k1.ecrecover(sig.v, Secp256k1.uint256(sig.r,16), Secp256k1.uint256(sig.s,16), z)
103120
Assert.deepStrictEqual(Q, {x: pubX.toString(16), y: pubY.toString(16)})
104121
})
122+
123+
it('can recover known sig', () => {
124+
const Q = Secp256k1.ecrecover(v, Secp256k1.uint256(r,16), Secp256k1.uint256(s,16), z)
125+
Assert.deepStrictEqual(Q, {x: pubX.toString(16), y: pubY.toString(16)})
126+
})
127+
128+
it('recover fails if r=0', () => {
129+
Assert.throws(() => Secp256k1.ecrecover(v, Secp256k1.uint256(0), Secp256k1.uint256(s,16), z), "assertion failed: sigr must not be 0")
130+
})
131+
132+
it('recover fails if s=0', () => {
133+
Assert.throws(() => Secp256k1.ecrecover(v, Secp256k1.uint256(r,16), Secp256k1.uint256(0), z), "assertion failed: sigs must not be 0")
134+
})
135+
136+
it('recover fails if recId<0', () => {
137+
Assert.throws(() => Secp256k1.ecrecover(-1, Secp256k1.uint256(r,16), Secp256k1.uint256(s,16), z), "assertion failed: recId must be 0..3")
138+
})
139+
140+
it('recover fails if recId>3', () => {
141+
Assert.throws(() => Secp256k1.ecrecover(4, Secp256k1.uint256(r,16), Secp256k1.uint256(s,16), z), "assertion failed: recId must be 0..3")
142+
})
105143
})

0 commit comments

Comments
 (0)