CVE-2022-41340 (JSON, published 2022-09-24T19:15Z)
Description: value: The secp256k1-js package before 1.1.0 for Node.js implements ECDSA without required r and s validation, leading to signature forgery.
Severity: nan (CVSS v3 base score: 7.5)
Weakness: CWE-347 \u2014 Improper Verification of Cryptographic Signature
The product does not verify, or incorrectly verifies, the cryptographic signature for data.
Repository: https://github.com/lionello/secp256k1-js
Files changed:
package-lock.json
package.json
src/secp256k1.js
test/test.js
Commit message: Fix #11: add parameter validation


Vulnerable code:
  "version": "1.0.0",
  "version": "1.0.0",
            const success = Secp256k1Node.verify(B(z), Buffer.concat([B(sig.r), B(sig.s)]), Buffer.concat([Buffer('\04'), B(pubX), B(pubY)]))
            const success = Secp256k1Node.verify(B(z), Buffer.concat([B(sig.r), B(sig.s)]), Buffer.concat([Buffer('\04'), B(pubX), B(pubY)]))
    it('can verify self', () =>  {
    it('can recover self', () =>  {

Fixed code:
  "version": "1.0.1",
  "version": "1.0.1",
    function assert(cond, msg) {
        if (!cond) {
            throw Error("assertion failed: " + msg)
        }
    }

        assert(d != 0, "d must not be 0")
        assert(z != 0, "z must not be 0")
        assert(recId >= 0 && recId <= 3, "recId must be 0..3")
        assert(sigr != 0, "sigr must not be 0")
        assert(sigs != 0, "sigs must not be 0")
        if (sigs == 0 || sigr == 0) {
            return false
        }
            const success = Secp256k1Node.verify(B(z), Buffer.concat([B(sig.r), B(sig.s)]), Buffer.concat([Buffer.from('\04'), B(pubX), B(pubY)]))
            const success = Secp256k1Node.verify(B(z), Buffer.concat([B(sig.r), B(sig.s)]), Buffer.concat([Buffer.from('\04'), B(pubX), B(pubY)]))
    it('can verify ours', () =>  {
    it('can verify known sig', () =>  {
        Assert.ok(Secp256k1.ecverify(pubX, pubY, Secp256k1.uint256(r,16), Secp256k1.uint256(s,16), z))
    })

    it('cannot sign 000...', () =>  {
        const z = Secp256k1.uint256("0000000000000000000000000000000000000000000000000000000000000000", 16)
        Assert.throws(() => Secp256k1.ecsign(d, z), "assertion failed: z must not be 0")
    })

    it('verify fails if r=0', () => {
        Assert.isFalse(Secp256k1.ecverify(pubX, pubY, Secp256k1.uint256(0), Secp256k1.uint256(s,16), z))
    })

    it('verify fails if s=0', () => {
        Assert.isFalse(Secp256k1.ecverify(pubX, pubY, Secp256k1.uint256(r,16), Secp256k1.uint256(0), z))
    })

    it('can recover ours', () =>  {

    it('can recover known sig', () =>  {
        const Q = Secp256k1.ecrecover(v, Secp256k1.uint256(r,16), Secp256k1.uint256(s,16), z)
        Assert.deepStrictEqual(Q, {x: pubX.toString(16), y: pubY.toString(16)})
    })

    it('recover fails if r=0', () => {
        Assert.throws(() => Secp256k1.ecrecover(v, Secp256k1.uint256(0), Secp256k1.uint256(s,16), z), "assertion failed: sigr must not be 0")
    })

    it('recover fails if s=0', () => {
        Assert.throws(() => Secp256k1.ecrecover(v, Secp256k1.uint256(r,16), Secp256k1.uint256(0), z), "assertion failed: sigs must not be 0")
    })

    it('recover fails if recId<0', () => {
        Assert.throws(() => Secp256k1.ecrecover(-1, Secp256k1.uint256(r,16), Secp256k1.uint256(s,16), z), "assertion failed: recId must be 0..3")
    })

    it('recover fails if recId>3', () => {
        Assert.throws(() => Secp256k1.ecrecover(4, Secp256k1.uint256(r,16), Secp256k1.uint256(s,16), z), "assertion failed: recId must be 0..3")
    })