- Harden FROST distributed key generation against round-one transcript substitution.
- This is not a vulnerability; it's protection against those who don't follow the FROST spec. Spec wants user to preserve rounds.
- FROST: Enforced RFC 9591 point validation for BLS and BN
- POPRF: replace inversion with const-time version
- Weierstrass: harden public-key boundaries & infinity handling
- ECDH and ECDSA now reject the identity even for point types whose generic codec permits it
- Curves that disallow infinity cannot encode it, while opted-in curves use the canonical SEC 1
0x00encoding.
- DER: Bounded ECDSA signature and INTEGER sizes before bigint conversion, preventing malformed inputs from causing disproportionate parsing and allocation work
- Snapshot all security-sensitive state (passed arguments) to ensure it can't be mutated
Special thanks to Red Team (Rob Hamilton, CalleBTC, Omer Talip) and 1Password's Off-by-1 Labs.
- Hardened constant-time execution from best-effort to actual guarantees, with no measurable timing behavior across 200,000 samples. Scalar multiplication now uses secret-scalar blinding via CSPRNG, unprecomputed points use a constant-time fixed-window multiply instead of variable-time fallbacks, and modular arithmetic helpers were hardened. New constant-time benchmarks track timing behavior.
- General hardening across all modules.
- Applied fixes from the Trail of Bits review: recovered ECDSA signatures are now bound to their recovery ID, non-canonical BLS signature encodings are rejected, Edwards-to-Montgomery conversion helpers were corrected, and FROST DKG round-two retry handling was hardened.
It was possible to execute a remote timing attack on X25519 across many samples and learn up to 4.036 bits of a long-term private key. The other 247 bits were not affected.
The impact is primarily fingerprinting—a key can be recognized across deployments—not key recovery or a break of X25519. The maintainer was also unable to escalate the attack to co-residency (SMT).
Reported and found by:
- George Stergiopoulos, Department of Informatics, Athens University of Economics and Business, Greece (
geostergiop@aueb.gr). - Constantinos Patsakis, Department of Informatics, University of Piraeus, 80 Karaoli & Dimitriou Street, 18534 Piraeus, Greece (
kpatsak@unipi.gr).
- Improved ECDSA and EdDSA verification by up to 32%, Weierstrass ECDH by up to 19%, and X25519
getPublicKeyby 2.7×. - Improved BLS signature performance by 2×.
- Reduced initialization time for the first
getPublicKeyorsigncall by approximately 2× for Ed25519, P-256, P-384, and P-521. - Also improved verification of recovered signatures, pairing tower, FFT, and Pippenger performance, as well as joint-MSM paths in FROST and OPRF.
getPublicKeyandsignbecame slower because the window size was decreased from 8 to 6 and constant-time execution was hardened. Long-running applications that prefer 2.2.0-level speed can restore it withsecp256k1.Point.BASE.precompute(8), and likewise for other curves.
- Improved tree-shaking for smaller bundles.
- Improved error messages and type checks.
- Upgraded noble-hashes to 2.3.0 for improved performance.
- Reduced on-disk size from 1,831 KB to 1,548 KB by disabling source maps, which have become less relevant.
- March 2026 self-audit (all files): no major issues found.
- Audited for specification compliance and security.
- Updated Ed25519 ZIP 215 verification to match the specification more strictly where its vectors were insufficient.
- Disabled ZIP 215 mode by default for Ed448 in favor of stricter verification.
- Changed Schnorr randomness handling to reduce modulo N instead of throwing.
- Hardened square-root calculations.
- Corrected the Baby Jubjub curve and its parameters.
- Improved DER parsing.
- Improved BLS point decoding.
- Fixed the Fp6 and Fp12 order for BLS and BN curves.
- Made empty hash-to-curve DST and count values throw.
- Applied
Object.freezeto most primitives. - Other minor hardening.
- Fixed all byte-array types to work properly in both TypeScript 5.6 and TypeScript 5.9+.
- TypeScript 5.6 has
Uint8Array, while TypeScript 5.9+ made it generic:Uint8Array<ArrayBuffer>. - This created incompatibilities between TypeScript versions.
- Previously, usage was difficult and constantly emitted errors similar to
TS2345. - See TypeScript issue #62240 for more context.
- TypeScript 5.6 has
- Implemented FROST threshold signatures from RFC 9591.
- Fixed compilation issues on TypeScript 6.
- Improved tree-shaking and reduced bundle sizes.
- Added extensive documentation throughout the codebase.
Version 2.1 was skipped to align with other noble packages.
- Disabled extensionless imports. If you used
/ed25519, switch to/ed25519.js. See 2.0.0 for more details. - Specified exported submodules in
package.jsonto ensure TypeScript autocompletion. - Upgraded hashes to 2.0.1, including the scrypt and
package.jsonchanges. - Exported
map_to_curve_elligator2_curve25519for Ed25519 in #211. - Added
try/catcharoundpairingBatchinbls12_381.verify()by @MegaManSec in #212. - Exposed extra information through FFT's
rootsOfUnity.
- @MegaManSec made their first contribution in #212.
This GitHub release does not include the standalone noble-curves.js; use 2.0.0 until the project upgrades to newly added GitHub Immutable Releases.
Version 2 substantially simplifies internals, improves security, reduces bundle size, and lays a path for the future. To simplify upgrading, first upgrade to curves 1.9.x, which surfaces deprecations in VS Code-like editors.
- The package is now ESM-only. ESM can be loaded from CommonJS on Node.js 20.19+.
- Node.js 20.19 is now the minimum required version.
- Package imports now work correctly in bundlerless environments, such as browsers.
- Reduced NPM package size from 354 KB to 300 KB.
- Reduced unpacked NPM size from 2.1 MB to 1.2 MB.
- Reduced bundle sizes compared to v1.x: 4 KB smaller for Schnorr, 5.3 KB smaller for Ristretto255, and 9.4 KB smaller for X448.
- The
.jsextension must be used for all modules.- Old:
@noble/curves/ed25519 - New:
@noble/curves/ed25519.js - This simplifies native browser usage without transpilers.
- Old:
- Added a friendly noble-like wrapper around built-in WebCrypto.
- Implemented RFC 9497 OPRFs (oblivious pseudorandom functions).
- P-256, P-384, P-521, Ristretto255, and Decaf448 are supported.
- Added
isValidSecretKeyandisValidPublicKeyto Weierstrass and Edwards curves. - Added the BrainpoolP256r1, BrainpoolP384r1, and BrainpoolP512r1 curves to
misc.
- Most methods now expect
Uint8Array; hexadecimal string inputs are prohibited.- This simplifies reasoning, improves security, and reduces malleability.
Point.fromHexnow expects only hexadecimal strings; usePoint.fromBytesforUint8Array.
- Breaking ECDSA changes for secp256k1, P-256, P-384, and other curves:
signandverifynow expect unhashed messages instead of message hashes. Use{ prehash: false }to restore the old behavior.signandverifynow use low-S signatures by default. This does not affect secp256k1, which has used low-S from the beginning. Tests against specific signature vectors may fail after upgrading unless{ lowS: false }is used to restore the old behavior.signandverifynow useUint8Arraysignatures in compact format by default.- DER format must now be explicitly selected with
{ format: 'der' }inverify, reducing malleability. verifynow prohibitsSignatureinstances; callsignature.toBytes()first.
- Breaking BLS signature changes for BLS12-381 and BN254:
- Moved
getPublicKey,sign,verify,signShortSignature, and related methods intobls.longSignaturesfor G1 public keys and G2 signatures, andbls.shortSignaturesfor G1 signatures and G2 public keys. verifyBatchnow expects an array of{ message, publicKey }inputs.
- Moved
- Curve changes:
- Substantially simplified curve creation and split point creation from signature generator creation.
- The new methods are
weierstrass() + ecdsa()andedwards() + eddsa(). - Weierstrass and Edwards constructors expect simplified curve parameters;
Fpbecamep. - ECDSA and EdDSA constructors expect a
Pointclass and hash. - Removed the unnecessary
Fnargument frompippenger.
- Modular arithmetic changes:
Field#fromBytes()now validates elements to be in the range from zero through order minus one.
- Upgraded the TypeScript compilation environment to TypeScript 5.9 and ES2022.
- Made error messages substantially more descriptive.
- Module changes:
- Moved the
p256,p384, andp521modules intonist. - Moved the
jubjubmodule intomisc.
- Moved the
- Point changes:
- Renamed
ExtendedPointandProjectivePointtoPoint. - Renamed projective and extended point coordinates from
px/ex,py/ey,pz/ez, andettoX,Y,Z, andT. - Moved
Point.normalizeZandPoint.msmto separate methods in theabstract/curve.jssubmodule. - Removed
Point.fromPrivateKey(); usePoint.BASE.multiply()andPoint.Fn.fromBytes(secretKey). - Renamed
toRawBytesandfromRawBytestotoBytesandfromBytes. - Renamed
RistrettoPointtoristretto255.PointandDecafPointtodecaf448.Point.
- Renamed
- ECDSA signature changes:
- Renamed
toCompactRawBytesandtoDERRawBytestotoBytes('compact')andtoBytes('der'). - Renamed
toCompactHexandtoDERHextotoHex('compact')andtoHex('der'). - Renamed
fromCompactandfromDERtofromBytes(format)andfromHex(format).
- Renamed
- Utility changes:
- Renamed
randomPrivateKeytorandomSecretKey. - Replaced
utils.precomputeandPoint#_setWindowSizewithPoint#precompute. - Renamed
edwardsToMontgomerytoutils.toMontgomery. - Renamed
edwardsToMontgomeryPrivtoutils.toMontgomerySecret.
- Renamed
- Renamed all curve-specific hash-to-curve methods to
*curve*_hasher; for example,secp256k1.hashToCurvebecamesecp256k1_hasher.hashToCurve(). - Renamed and improved many types.
- Removed
Point#multiplyAndAddUnsafeandPoint#hasEvenY. - Removed the
CURVEproperty with miscellaneous internals.Point.CURVE()replaces it but provides only curve parameters. - Removed the
pastaandbn254_weierstrasscurves; this does not affect the pairing-based BN254 curve. - Removed
Field.MASK. - Removed
utils.normPrivateKeyToScalar.
- Renamed the newly introduced, experimental Edwards method
toMontgomeryPrivtotoMontgomerySecret. - Restored
SignatureConstructorfor Weierstrass curves. - Added more deprecations and preparations for version 2.
- Exposed
nBitLengthandnByteLengthfor Edwards curves. - Renamed
secretandpublictosecretKeyandpublicKeyin the experimentalCurveLengthsinterface. - Began point precomputation earlier, within
weierstrass(), while retaining lazy calculation until the first call. - Added the new internal version-2
towerimplementation to BLS. - Ensured Ed448 and Decaf448 use separate
Fnfields with differentBITSlengths.
- Fixed Rollup warnings from #205.
- Restored aliases for
secp256r1,secp384r1, andsecp521r1from #203. - Restored
CURVE.nByteLengthfrom #202. - Added more preparations and deprecations for the future version-2 release.
- Fixed #201, an invalid renaming of
ProjConstructor. - Added more deprecations for the upcoming version-2 release.
This release contains bug fixes and improvements that pave the way for version 2. Existing code continues to work unchanged, while old APIs are visually flagged as deprecated through JSDoc in TypeScript-aware environments.
- Renamed
*privateKeyto*secretKeythroughout for consistency with post-quantum and non-noble libraries. - Added
keygen, which creates both secret and public keys. - Made the Weierstrass endomorphism generic for all Koblitz curves.
- Added
fromBytesandtoBytesto Weierstrass signatures and deprecatedfromDER,fromCompact,toDERRawBytes, andtoCompactRawBytes. - Moved Edwards
edwardsToMontgomeryintoutils.toMontgomery. - Added a new Decaf and Ristretto interface that is more consistent with other points.
- Added
ED448_TORSION_GROUPfor Ed448. - Added
curve.infoto all curves for better interoperability. - Changed the public wNAF API.
- Added
sqrt9mod16to modular arithmetic. - Moved all hash-to-curve hashers into
_hasherproperties, such assecp256k1_hasher. - Added ACVP test vectors.
- Primarily renamed wNAF internals.
- Added field-bound validation for scalar fields (
Fn) and curve fields (Fp).
This release contains bug fixes and improvements that pave the way for version 2.
- Substantially refactored Edwards and Weierstrass curves with a simpler ECDSA and EdDSA API in #192.
- The old code continues to work until version 2.
- The new API is experimental until the next patch release.
- Renamed
toRawBytestotoBytes. - Renamed
ExtendedPointandProjectivePointtoPoint. - Added static
FpandFnfield properties toPoint.
- Added support for ECDSA on curves with a cofactor greater than one.
- Added support for points with an x-coordinate of zero in Weierstrass curves.
- Substantially refactored BLS, improved types, and added the new
bls.longSignaturesandbls.shortSignaturesAPIs.- The old code continues to work until version 2.
- The new API is experimental until the next patch release.
- Reused noble-hashes utilities.
- Used
randomBytesand HMAC from noble-hashes by default.
- Refactored range-check logic for Edwards and Weierstrass curves.
- Improved Weierstrass
sign()logic for nonce generation. - Hardened
multiplyUnsafeand stopped usingmultiplyAndAddUnsafefor Weierstrass curves.
- @randombit added a test that BLS12-381 augmented signatures can be verified in #191.
- Added an experimental FFT/NTT implementation in
abstract/fft. - Verified Edwards curve parameters against the curve equation during initialization.
- Verified Weierstrass curve parameters against the discriminant during initialization.
- Improved
getSharedSecretargument validation for rare Weierstrass curves. - Fixed invalid signature-recovery decoding lengths for rare Weierstrass curves.
- Improved modular square-root calculation.
- Allowed X25519 and X448 to accept more valid private- and public-key inputs.
- Improved secp256k1 tree-shaking.
This release contains bug fixes and improvements that pave the way for version 2.
- Modules are now available with a
.jsextension.- Old:
@noble/curves/ed25519 - New:
@noble/curves/ed25519.js - The old path remains available.
- This simplifies native browser usage without transpilers.
- Old:
- Added sponge and Grain LFSR support to Poseidon.
- Merged P-256, P-384, and P-521 into the new
nistmodule. - Prohibited y-coordinates of zero during Weierstrass initialization.
- Used
inv0throughout hash-to-curve to ensure zero elements are returned in exceptional cases. - Improved modular square-root logic, including Tonelli-Shanks and Legendre calculations.
- Fixed
FpInvertBatchcreating sparse arrays instead of arrays containingundefined. - Deprecated Pasta curves.
- Updated noble-hashes to 1.8.0.
- Important: adjusted wNAF scalar multiplication logic.
- The adjustment is small and deduplicates code, but wNAF is sensitive code that handles private keys.
- Review the change in #184.
- Made Edwards curves such as Ed25519 and Ed448 always use the complete addition formula.
- Prohibited Edwards points with
z = 0; zero points havez = 1. - Used a slower but more precise
CURVE.adefinition for Ed25519. - Froze Weierstrass signatures on creation.
- Fixed Weierstrass curves in the Pale Moon browser (#176).
- Improved the hash-to-curve error for zero in
mapToCurve. - Fixed the incorrect
Fp12fields type intower. - Added the
miscmodule containing Jubjub and Baby Jubjub. - Updated utils to use built-in
Uint8ArraytoHexandfromHexwhen available, providing a 13× speed-up on 256-byte arrays and a 20× speed-up on 32 KB arrays.
- Updated noble-hashes to 1.7.2.
- Reduced the standalone build by 500 bytes.
- Standalone build files are now attested in CI. See the README for the verification guide.
- TypeScript source can now be used without compilation in Node.js 24 due to
erasableSyntaxOnly.
- @tuantran-genetica made their first contribution in #181.
- @kigawas made their first contribution in #183.
Thanks to @ChALkeR for spotting the Edwards bug.
- Enabled TypeScript's
verbatimModuleSyntaxto support future Node.js type stripping. - Updated noble-hashes to 1.7.1.
- Improved documentation.
- The package is now available on JSR.
- Enabled TypeScript's
isolatedDeclarationsoption, which substantially simplifies automatic documentation generation and more.- See the JSR page for an example.
- Added extensive comments throughout the codebase to improve autocompletion, LLM code generation, and general code understanding.
- Fixed
isLElogic and reversedmapHashToFieldin modular arithmetic. - Upgraded noble-hashes to 1.7.0.
- Added
wnafCachedUnsafe()andprecomputeMSMUnsafe()to curves.- The new methods speed up MSM when inputs are public.
- Edwards and Weierstrass
multiplyUnsafenow use the new wNAF methods.
- Made modular square-root calculation fail on a non-prime P instead of looping.
- Delayed
sqrtPcalculation until its first use instead of precomputing it at initialization.
- Delayed
- Added support for a strict
formatoption in Weierstrassverify, selecting betweencompactandder. - Exported additional BLS types to simplify custom curves.
- Improved
isBytesperformance. - Improved compatibility with parsers and minifiers.
- Upgraded noble-hashes to 1.6.0.
- @andreibancioiu made their first contribution in #156.
- @ChALkeR made their first contribution in #166.
- Added multi-scalar multiplication using the Pippenger algorithm to Weierstrass and Edwards curves.
- Improved DER encoding edge cases, fixing P-521 signatures.
- Added more hash-to-curve type checks.
- Exported
abstract/towerfor pairing-friendly curves. - Added support for Node.js 14.
- Upgraded noble-hashes to 1.5.0.
- Implemented BN254 (also known as alt_bn128) pairings compatible with EVM and ZEC.
- Point serialization is not implemented because there is no standard representation, but it can be implemented in user space. See the README.
- Refactored and simplified range checks for private keys and signatures.
- Added memoization to
toAffineandassertValidityto speed up BLS. - Made all points immutable and frozen for improved security.
- Reverted the TypeScript build target from ES2022 to ES2020 due to compatibility issues.
- Added
mapToCurveto BLS12-381 and fixed TypeScript types. - Improved tree-shaking for Ed25519 and utils.
- Emitted separate ESM type declarations from the TypeScript build for improved compatibility.
- Changed the TypeScript build target from ES2020 to ES2022.
- @carleeto made their first contribution in #133.
- Fixed verification of BLS short signatures when using hexadecimal strings.
- Fixed types in hash-to-field and Weierstrass entropy.
- Updated noble-hashes to 1.4.0, adding support for big-endian platforms.
- Refactored small utilities to reduce code duplication.
- Improved
tsconfig.
- @ardislu made their first contribution in #110.
- @dhrubabasu made their first contribution in #117.
- @xrchz made their first contribution in #129.
- BLS changes:
- Added support for short signatures, which use G1 for signatures and G2 for public keys rather than the reverse.
- Contributed by @randombit in #74.
- Refactored mask-bit settings and improved encoding resilience.
- Implemented the
Groupinterface for Ed25519 and Ed448DecafPointandRistrettoPointby @sublimator in #85. - Fixed X448 private keys to be 56 bytes rather than 57 bytes.
- Fixed the missing
CURVEobject in WeierstrassweierstrassPointsby @secure12 in #92. - Utility changes:
- Sped up
hexToBytesby 6× and improved error formatting, by @arobsn in #83. - Improved
isBytesreliability in environments such as JSDOM. - Improved
concatBytessafety by checking types early. - Made
equalBytesconstant-time.
- Sped up
- Upgraded noble-hashes to 1.3.3.
- Upgraded the TypeScript build version to 5.3.2.
- @randombit made their first contribution in #74.
- @arobsn made their first contribution in #83.
- @secure12 made their first contribution in #92.
- @yhc125 made their first contribution in #93.
- Added Decaf448 support to Ed448.
- Improved the security of random Weierstrass private keys by reducing bias from
2^-64to2^-curve_security_level. - Allowed Weierstrass
extraEntropyto accept any number of bytes. - Improved Poseidon security by making
sboxPowermandatory, allowing only 3, 5, or 7, and prohibiting oddroundsFullvalues. - Allowed string and
Uint8ArrayDSTs in hash-to-curve. - Improved tree-shaking by adding
sideEffects: falsetopackage.jsonand pure annotations to Ed25519. - Updated noble-hashes to 1.3.2.
- @stknob made their first contribution in #59.
- @mahnunchik made their first contribution in #56.
- @steveluscher made their first contribution in #62.
- Ed25519 and Ed448
verifynow provide non-repudiation (strongly binding signatures) whenzip215: falseis used.- Non-repudiation is useful for e-voting and other systems.
- See The Provable Security of Ed25519: Theory and Practice.
- See Taming the many EdDSAs and its NIST presentation.
- Reduced common-case bundle sizes by 20% with pure annotations, helping bundlers eliminate dead code during tree-shaking.
- secp256k1: 75.4 KB to 62.3 KB.
- Ed25519: 67.5 KB to 51.1 KB.
- Ed448: 55.1 KB to 44.0 KB.
- P-256: 67.8 KB to 59.8 KB.
- P-384: 75.4 KB to 67.4 KB.
- P-521: 75.8 KB to 67.8 KB.
- Changed the Weierstrass
signreturn type fromSignatureTypetoRecoveredSignatureType. - Renamed Edwards
edwardsToMontgomerytoedwardsToMontgomeryPuband addededwardsToMontgomeryPriv. - Made BLS12-381 friendlier to non-compliant compilers by avoiding BigInt literals.
- Improved compatibility with non-compliant compilers by avoiding the exponentiation operator with BigInts.
- Fixed the Ed25519
ristrettoHashsize typo inhashToCurveby @sublimator in #42. - Harmonized utils with noble-hashes.
- Fixed
utf8ToBytesin Firefox extension contexts.
- @mirceanis made their first contribution in #32.
- @legobeat made their first contribution in #38.
- @sublimator made their first contribution in #42.
- Thanks to @Wind4Greg for their involvement in strongly binding signatures.
First stable release. The API should now remain stable.
contextis now an option insignandverify.zip215is a newverifyoption that conforms to RFC 8032 whenfalseand matches ZIP 215 whentrue.- Added
edwardsToMontgomery.
-
CURVEis no longer exposed because it was an internal property. UseG1.CURVEandG2.CURVE. -
Fields moved into the
fields: { Fp, Fp2, Fp6, Fp12, Fr }property. -
See the README for new usage.
-
Improved DER decoding and validated curve creation for Weierstrass curves.
-
Updated Wycheproof vectors.
-
Restricted hash-to-curve
expandtoxmdandxof.
- Initial release