paulmillr / noble-curves

Audited & minimal JS implementation of elliptic curve cryptography.
https://paulmillr.com/noble
MIT License
621 stars 56 forks source link

Incompatibility with old bls12-381 library: not in prime-order subgroup #130

Closed CluEleSsUK closed 3 months ago

CluEleSsUK commented 3 months ago

When migrating to @noble/curves from @noble/bls12-381, some of our old network's signatures are not being verified. I've tried a few other BLS libs in go and they're verifying fine.

When verifying, the following error occurs:

Error: bad point: not in prime-order subgroup
    at Point.assertValidity (node_modules/@noble/curves/src/abstract/weierstrass.ts:355:40)
    at Object.fromHex (node_modules/@noble/curves/src/bls12-381.ts:1390:15)
    at normP2 (node_modules/@noble/curves/src/abstract/bls.ts:290:68)
    at Object.verify (node_modules/@noble/curves/src/abstract/bls.ts:351:15)

On some other signatures, I've periodically seen:

Error: No root
    at Object.sqrt (node_modules/@noble/curves/src/bls12-381.ts:171:25)
    at Object.fromHex (node_modules/@noble/curves/src/bls12-381.ts:1379:21)
    at normP2 (node_modules/@noble/curves/src/abstract/bls.ts:290:68)
    at Object.verify (node_modules/@noble/curves/src/abstract/bls.ts:351:15)

A minimal reproduction I've made is the following:

import {bls12_381} from "@noble/curves/bls12-381"
import * as bls from "@noble/bls12-381"
import {sha256} from "@noble/hashes/sha256"
import {expect} from "chai"

describe("wtf", () => {
    it("wtf", async () => {
        const beacon = {
            round: 19398585,
            randomness: '9ff50f8dd76a4c6a7e11f075b457bb95deb680c9a51eda6e81e471b4ede7869b',
            signature: 'af8695d75961338f379158022f24526203289a37ce94f29067f10b9f18db74f88ad189d0576d54f4b9b07f03195a0900191029ff7ff9a7db955ee381813a1f2875edc4a90151ffaf2e40f4106b9167b0a02e9507881e6b0028f09df236f838d2'
        }

        const publicKey = "8200fc249deb0148eb918d6e213980c5d01acd7fc251900d9260136da3b54836ce125172399ddc69c4e3e11429b62c11"
        const msg = hashedRoundNumber(beacon.round)
        expect(await bls.verify(beacon.signature, msg, publicKey)).to.be.true
        expect(bls12_381.verify(beacon.signature, msg, publicKey)).to.be.true
    })
})

function hashedRoundNumber(round: number) {
    const roundNumberBuffer = Buffer.alloc(8);
    roundNumberBuffer.writeBigUInt64BE(BigInt(round));
    return sha256(roundNumberBuffer)
}

The first verification (on the old library) succeeds, but the second fails with the prime order subgroup error

paulmillr commented 3 months ago

32bda7926dea02a6479ea4b7dfa98da23831dd0b could fix this. Can you try using the github version? Clone it to your machine, do npm install && npm run build && npm pack, then copy archive somewhere and install the packed archive: npm install curves.tgz

CluEleSsUK commented 3 months ago

yep that works a charm, thanks for the help! If you could do a release I'd be super grateful

paulmillr commented 3 months ago

1.4.0