diff --git a/README.md b/README.md index 0fcdaa8..273af6a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Audited & minimal JS implementation of elliptic curve cryptography. - 🔒 [**Audited**](#security) by an independent security firm - 🔻 Tree-shaking-friendly: use only what's necessary, other code won't be included - 🏎 Ultra-fast, hand-optimized for caveats of JS engines -- 🔍 Unique tests ensure correctness: property-based, cross-library and Wycheproof vectors, fuzzing +- 🔍 Unique tests ensure correctness: property-based, cross-library and Wycheproof vectors, fuzzing - ➰ Short Weierstrass, Edwards, Montgomery curves - ✍️ ECDSA, EdDSA, Schnorr, BLS signature schemes, ECDH key agreement - #️⃣ Hash-to-curve @@ -121,7 +121,10 @@ x25519 ECDH and [ristretto255](https://datatracker.ietf.org/doc/html/draft-irtf- Default `verify` behavior follows [ZIP215](https://zips.z.cash/zip-0215) and [can be used in consensus-critical applications](https://hdevalence.ca/blog/2020-10-04-its-25519am). -`zip215: false` option switches verification criteria to RFC8032 / FIPS 186-5. +`zip215: false` option switches verification criteria to stricter +RFC8032 / FIPS 186-5 which is also +SUF-CMA (strong unforgeability under chosen message attacks) and +SBS (Strongly Binding signature) as per [eprint 2020/1244](https://eprint.iacr.org/2020/1244). ```ts import { ed25519 } from '@noble/curves/ed25519'; @@ -554,7 +557,7 @@ aggregateSignatures: { millerLoop: (ell: [Fp2, Fp2, Fp2][], g1: [Fp, Fp]) => Fp12; pairing: (P: ProjPointType, Q: ProjPointType, withFinalExponent?: boolean) => Fp12; G1: CurvePointsRes & ReturnType>; -G2: CurvePointsRes & ReturnType>; +G2: CurvePointsRes & ReturnType>; Signature: SignatureCoder; params: { x: bigint; @@ -567,7 +570,7 @@ fields: { Fp2: IField; Fp6: IField; Fp12: IField; - Fr: IField; + Fr: IField; }; utils: { randomPrivateKey: () => Uint8Array; diff --git a/src/abstract/edwards.ts b/src/abstract/edwards.ts index 5834400..9124f66 100644 --- a/src/abstract/edwards.ts +++ b/src/abstract/edwards.ts @@ -474,6 +474,7 @@ export function twistedEdwards(curveDef: CurveType): CurveFn { } catch (error) { return false; } + if (!zip215 && A.isSmallOrder()) return false; const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg); const RkA = R.add(A.multiplyUnsafe(k)); diff --git a/test/ed25519.test.js b/test/ed25519.test.js index d4a07ce..f034ff8 100644 --- a/test/ed25519.test.js +++ b/test/ed25519.test.js @@ -410,12 +410,9 @@ describe('ed25519', () => { } }); - should('not verify when x=0 and x_0 = 1 (RFC8032)', () => { - const list = [edgeCases[8], edgeCases[10], edgeCases[11]]; - for (let v of list) { - const result = ed.verify(v.signature, v.message, v.pub_key, { zip215: true }); - strictEqual(result, true, `zip215: true must validate: ${v.signature}`); - } + should('have strict SUF-CMA and SBS properties', () => { + // https://eprint.iacr.org/2020/1244 + const list = [0, 1, 6, 7, 8, 9, 10, 11].map((i) => edgeCases[i]); for (let v of list) { const result = ed.verify(v.signature, v.message, v.pub_key, { zip215: false }); strictEqual(result, false, `zip215: false must not validate: ${v.signature}`);