Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
noble-curves — Implémentation JS auditée et minimale de cryptographie sur courbes elliptiques. | Kitploit
Outils/GitHubGitHub/paulmillr/noble-curves
Outils de Chiffrement/DéchiffrementAnalyse de HachageCryptographieUtilitaires et FrameworksApprentissage et Éducation
GitHubpaulmillr/noble-curves

noble-curves

Implémentation JS auditée et minimale de cryptographie sur courbes elliptiques.

Voir le dépôt
95810115il y a 7 joursVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager
Site web

noble-curves

Implémentation JS auditée et minimale de cryptographie sur courbes elliptiques.

  • 🔒 Auditée par des sociétés de sécurité indépendantes
  • 🪶 Minimale : 15 Ko (gzippé) pour secp256k1, le code inutilisé est exclu de vos builds
  • 🏎 Rapide : optimisée à la main pour les particularités des moteurs JS
  • 🔍 Fiable : tests inter-bibliothèques / wycheproof garantissant la correction
  • ➰ Courbes de Weierstrass, Edwards ; signatures ECDSA, EdDSA, Schnorr, BLS
  • ✍️ ECDH, hash-to-curve, OPRF, FROST, hash Poseidon, FFT
  • 🔖 Non-répudiation (SUF-CMA, SBS) et compatibilité consensus (ZIP215) dans ed25519, ed448
  • 🥈 Wrapper avec API identique au-dessus de WebCrypto natif

Les courbes ont des projets frères de 5 Ko secp256k1 & ed25519. Ils ont une surface d'attaque plus réduite, mais moins de fonctionnalités.

Cette bibliothèque appartient à la cryptographie noble

noble cryptography — ensemble de bibliothèques et d'outils cryptographiques à haute sécurité, facilement auditables et contenus.

  • Dépendances nulles ou minimales
  • Code TypeScript / JS hautement lisible
  • Versions signées PGP et builds NPM transparents
  • Toutes les bibliothèques : ciphers, curves, hashes, post-quantum, 5 Ko secp256k1 / ed25519
  • Version WASM : awasm-noble
  • Consultez la page d'accueil pour des ressources de lecture, de la documentation et des applications construites avec noble

Utilisation

npm install @noble/curves

deno add jsr:@noble/curves

Nous prenons en charge toutes les principales plateformes et environnements d'exécution. Pour React Native, vous pourriez avoir besoin d'un polyfill pour getRandomValues. Un fichier autonome noble-curves.js est également disponible.```js // import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size import { secp256k1 } from '@noble/curves/secp256k1.js'; const { secretKey, publicKey } = secp256k1.keygen(); const msg = new TextEncoder().encode('hello noble'); const sig = secp256k1.sign(msg, secretKey); const isValid = secp256k1.verify(sig, msg, publicKey);

root@kitploit:~
- [Signatures ECDSA, EdDSA, Schnorr](#ecdsa-eddsa-schnorr-signatures)
- [ECDH : secrets partagés Diffie-Hellman](#ecdh-diffie-hellman-shared-secrets)
- [webcrypto : wrapper convivial](#webcrypto-friendly-wrapper)
- [Signatures BLS, bls12-381, bn254 alias alt\_bn128](#bls-signatures-bls12-381-bn254-aka-alt_bn128)
- [hash-to-curve : hachage vers des points de courbe](#hash-to-curve-hashing-to-curve-points)
- [OPRFs](#oprfs) | [Signatures de seuil FROST](#frost-threshold-signatures)
- [poseidon : hash Poseidon](#poseidon-poseidon-hash) | [fft : Transformée de Fourier rapide](#fft-fast-fourier-transform) | [utils](#utils-byte-shuffling-conversion)
- Internes : [Mathématiques de points](#elliptic-curve-point-math) | [modulaire](#modular-modular-arithmetics--finite-fields) | [courbes personnalisées](#weierstrass-custom-weierstrass-curve--ecdsa)
- [Spécifications](#specs)
- [Sécurité](#security) | [Vitesse](#speed) | [Mise à niveau](#upgrading) | [Contribution et tests](#contributing--testing) | [Licence](#license)

### Signatures ECDSA, EdDSA, Schnorr

#### secp256k1, p256, p384, p521, ed25519, ed448, brainpool```js
import { secp256k1, schnorr } from '@noble/curves/secp256k1.js';
import { p256, p384, p521 } from '@noble/curves/nist.js';
import { ed25519 } from '@noble/curves/ed25519.js';
import { ed448 } from '@noble/curves/ed448.js';
import { brainpoolP256r1, brainpoolP384r1, brainpoolP512r1 } from '@noble/curves/misc.js';
for (const curve of [
  secp256k1, schnorr,
  p256, p384, p521,
  ed25519, ed448,
  brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
]) {
  const { secretKey, publicKey } = curve.keygen();
  const msg = new TextEncoder().encode('hello noble');
  const sig = curve.sign(msg, secretKey);
  const isValid = curve.verify(sig, msg, publicKey);
  console.log(curve, secretKey, publicKey, sig, isValid);
}

// Specific private key
import { hexToBytes } from '@noble/curves/utils.js';
const secret2 = hexToBytes('46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236');
const pub2 = secp256k1.getPublicKey(secret2);

Les messages sont toujours hachés d'abord : voir signature pré-hachée. ECDSA utilise un k déterministe, EdDSA suit la RFC 8032, Schnorr (secp256k1 uniquement) suit le BIP 340 : voir Spécifications.

Le schéma de signature MuSig2 et le mapping ElligatorSwift BIP324 pour secp256k1 sont disponibles dans un package séparé.

ristretto255, decaf448```ts

import { ristretto255, ristretto255_hasher, ristretto255_oprf } from '@noble/curves/ed25519.js'; import { decaf448, decaf448_hasher, decaf448_oprf } from '@noble/curves/ed448.js';

console.log(ristretto255.Point, decaf448.Point);

root@kitploit:~
Consultez la [RFC 9496](https://www.rfc-editor.org/rfc/rfc9496) pour plus d'informations sur ristretto255 et decaf448.
Consultez la documentation séparée pour [Point](#elliptic-curve-point-math), [hasher](#hash-to-curve-hashing-to-curve-points) et [oprf](#oprfs).

#### Signature pré-hachée```js
import { secp256k1 } from '@noble/curves/secp256k1.js';
import { keccak_256 } from '@noble/hashes/sha3.js';
const { secretKey } = secp256k1.keygen();
const msg = new TextEncoder().encode('hello noble');
// prehash: true (default) - hash using secp256k1.hash (sha256)
const sig = secp256k1.sign(msg, secretKey);
// prehash: false - hash using custom hash
const sigKeccak = secp256k1.sign(keccak_256(msg), secretKey, { prehash: false });

Par défaut (prehash: true), sign() et verify() appliquent d'abord le hachage intégré de la courbe au message : sha256 pour secp256k1, sha512 pour p521. prehash: false permet d'utiliser un hachage personnalisé (par exemple secp256k1 + keccak_256). Dans noble-curves v1, prehash: false était la valeur par défaut.

Récupération des clés publiques à partir des signatures```js

import { secp256k1 } from '@noble/curves/secp256k1.js'; const { secretKey, publicKey } = secp256k1.keygen(); const msg = new TextEncoder().encode('hello noble'); const sigRec = secp256k1.sign(msg, secretKey, { format: 'recovered' }); const publicKey_ = secp256k1.recoverPublicKey(sigRec, msg); // == publicKey

// recovered sig is compact sig with an extra byte const sigNoRec = secp256k1.sign(msg, secretKey, { format: 'compact' }); // sigNoRec == sigRec.slice(1)

// Signature instance const sigInstance = secp256k1.Signature.fromBytes(sigRec, 'recovered');

root@kitploit:~
La récupération de clé publique n'est prise en charge qu'avec ECDSA. Il s'agit d'une simple opération mathématique :
aucune garantie n'existe que la signature a réellement été effectuée. Un triplet (r, s, h) falsifié donne une clé publique aléatoire, mais il n'est pas réalisable de trouver m qui conduirait à ce h falsifié spécifique.

#### ECDSA couvert avec bruit```js
import { secp256k1 } from '@noble/curves/secp256k1.js';
const { secretKey } = secp256k1.keygen();
const msg = new TextEncoder().encode('hello noble');
// extraEntropy: false - default, hedging disabled
const sigNoisy = secp256k1.sign(msg, secretKey);
// extraEntropy: true - fetch 32 random bytes from CSPRNG
const sigNoisyA = secp256k1.sign(msg, secretKey, { extraEntropy: true });
// extraEntropy: bytes - specific extra entropy
const ent = Uint8Array.from([0xca, 0xfe, 0x01, 0x23]);
const sigNoisy2 = secp256k1.sign(msg, secretKey, { extraEntropy: ent });

Par défaut, les signatures ECDSA sont déterministes (RFC 6979). Les signatures purement déterministes sont vulnérables aux attaques par faute, c'est pourquoi les schémas plus récents, tels que BIP340 schnorr, intègrent de l'aléatoire dans la génération de signature - aussi appelé hedging. extraEntropy active le mode hedged. Pour plus d'informations, consultez Deterministic signatures are not your friends.

Consensus-friendliness vs e-voting```js

import { ed25519 } from '@noble/curves/ed25519.js'; const { secretKey, publicKey } = ed25519.keygen(); const msg = new TextEncoder().encode('hello noble'); const sig = ed25519.sign(msg, secretKey); // zip215: true const isValid = ed25519.verify(sig, msg, publicKey); // SBS / e-voting / RFC8032 / FIPS 186-5 const isValidRfc = ed25519.verify(sig, msg, publicKey, { zip215: false });

root@kitploit:~
* `zip215: true` (par défaut) utilise les règles de vérification plus permissives et [compatibles avec le consensus](https://hdevalence.ca/blog/2020-10-04-its-25519am) définies dans [ZIP215](https://zips.z.cash/zip-0215).
* `zip215: false` applique une vérification stricte RFC 8032 / FIPS 186-5 et ajoute la
  non-répudiation basée sur SBS, ce qui est utile pour la signature de contrats, le vote électronique et les blockchains.

Les deux modes disposent de SUF-CMA (forte infalsifiabilité sous attaques à messages choisis) ;
la plupart des autres bibliothèques n'ont ni SUF-CMA ni SBS.
Voir [Taming the many EdDSAs](https://eprint.iacr.org/2020/1244) pour plus d'informations.

### ECDH : secrets partagés Diffie-Hellman```js
import { x25519 } from '@noble/curves/ed25519.js';
const alice = x25519.keygen();
const bob = x25519.keygen();
const sharedKey = x25519.getSharedSecret(alice.secretKey, bob.publicKey);
// Same API: secp256k1, p256, p384, p521, x448

// converting ed25519 keys to x25519
import { ed25519 } from '@noble/curves/ed25519.js';
const alice2 = ed25519.keygen();
const bob2 = ed25519.keygen();
const aliceSecX = ed25519.utils.toMontgomerySecret(alice2.secretKey);
const bobPubX = ed25519.utils.toMontgomery(bob2.publicKey);
const sharedKey2 = x25519.getSharedSecret(aliceSecX, bobPubX);

Nous fournissons ECDH sur toutes les courbes de Weierstrass, et sur 2 courbes de Montgomery X25519 (Curve25519) & X448 (Curve448), conformément à la RFC 7748.

Dans les courbes de Weierstrass, les secrets partagés :

  • Incluent les octets de parité y : utilisez key.slice(1) pour les retirer
  • Ne sont pas hachés : utilisez un hachage ou un KDF par-dessus, comme sha256(shared) ou hkdf(shared)

webcrypto : wrapper convivial```js

import { ed25519, x25519 } from '@noble/curves/webcrypto.js';

// signatures: p256, p384, p521, ed25519, ed448 const keys = await ed25519.keygen(); const msg = new TextEncoder().encode('hello noble'); const sig = await ed25519.sign(msg, keys.secretKey); const isValid = await ed25519.verify(sig, msg, keys.publicKey);

// ECDH: p256, p384, p521, x25519, x448 const alice = await x25519.keygen(); const bob = await x25519.keygen(); const shared = await x25519.getSharedSecret(alice.secretKey, bob.publicKey);

// key conversion between noble (raw) and webcrypto (pkcs8 / spki) formats import { p256 as p256n } from '@noble/curves/nist.js'; import { p256 } from '@noble/curves/webcrypto.js'; const nobleKeys = p256n.keygen(); const secretKeyPkcs8 = await p256.utils.convertSecretKey(nobleKeys.secretKey, 'raw', 'pkcs8'); const publicKeySpki = await p256.utils.convertPublicKey(nobleKeys.publicKey, 'raw', 'spki');

root@kitploit:~
Un mince wrapper au-dessus de WebCrypto intégré, reflétant l'API noble. Les méthodes sont toujours asynchrones ;
la prise en charge à l'exécution varie - vérifiez avec `await curve.isSupported()`.
Consultez [micro-key-producer](https://github.com/paulmillr/micro-key-producer) pour
des utilitaires de conversion de clés en pur JS.

### Signatures BLS, bls12-381, bn254 alias alt_bn128```ts
import { bls12_381 } from '@noble/curves/bls12-381.js';

// G1 pubkeys, G2 sigs
const blsl = bls12_381.longSignatures;
const { secretKey, publicKey } = blsl.keygen();
const msg = new TextEncoder().encode('hello noble');
const msgp = blsl.hash(msg); // hash to point, default DST
const msgpd = blsl.hash(msg, 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_'); // custom DST (Ethereum)
const signature = blsl.sign(msgp, secretKey);
const isValid = blsl.verify(signature, msgp, publicKey);

// G1 sigs, G2 pubkeys: identical API
const blss = bls12_381.shortSignatures;

// Aggregation
const aggregatedKey = blsl.aggregatePublicKeys([
  blsl.getPublicKey(bls12_381.utils.randomSecretKey()),
  blsl.getPublicKey(bls12_381.utils.randomSecretKey()),
]);
// const aggregatedSig = blsl.aggregateSignatures(sigs)

// Pairings: bls12_381.pairing(PointG1, PointG2)
// Fields: bls12_381.fields.Fp, Fp2, Fp12, Fr

Pour un exemple d'utilisation, consultez l'implémentation des précompilations BLS EVM.

L'API BN254 reflète celle de bls12-381. La courbe était auparavant appelée alt_bn128. L'implémentation est compatible avec EIP-196 et EIP-197 : consultez l'implémentation des précompilations bn254 EVM. Les points bn254 n'implémentent pas toBytes, car il n'existe pas de standard de sérialisation : les implémentations divergent sur l'endianness, les flags et l'ordre de la partie imaginaire de G2. Initialisez les points à partir de bigints à la place.

hash-to-curve : hachage vers des points de courbe```ts

import { secp256k1_hasher } from '@noble/curves/secp256k1.js';

const msg = Uint8Array.from([0xca, 0xfe, 0x01, 0x23]); const point = secp256k1_hasher.hashToCurve(msg); const pointDst = secp256k1_hasher.hashToCurve(msg, { DST: 'hello noble' }); const pointNu = secp256k1_hasher.encodeToCurve(msg); const scalar = secp256k1_hasher.hashToScalar(msg);

// Same API: p256_hasher, p384_hasher, p521_hasher (nist.js), // ed25519_hasher, ristretto255_hasher (ed25519.js), ed448_hasher, decaf448_hasher (ed448.js), // bls12_381.G1, bls12_381.G2. // ristretto255 & decaf448 also provide deriveToCurve.

// abstract methods import { expand_message_xmd, expand_message_xof, hash_to_field } from '@noble/curves/abstract/hash-to-curve.js';

root@kitploit:~
Le module permet de hacher des chaînes arbitraires en points de courbe elliptique. Implémente la [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
Les espaces de noms `_hasher` sont séparés des courbes pour le tree-shaking :
les utilisateurs qui n'ont pas besoin du hash-to-curve ne l'auront pas dans leurs builds.

### OPRFs```js
import { p256_oprf, p384_oprf, p521_oprf } from '@noble/curves/nist.js';
import { ristretto255_oprf } from '@noble/curves/ed25519.js';
import { decaf448_oprf } from '@noble/curves/ed448.js';

Nous fournissons des OPRF (fonctions pseudorandom oblivious), conformes à la RFC 9497.

OPRF permet de créer de manière interactive un Output = PRF(Input, serverSecretKey) :

  • Le serveur ne peut pas calculer Output par lui-même : il ne connaît pas Input
  • Le client ne peut pas calculer Output par lui-même : il ne connaît pas serverSecretKey
  • Un attaquant interceptant la communication ne peut pas restaurer Input/Output/serverSecretKey et ne peut pas lier Input à une quelconque valeur.

Signatures à seuil FROST

FROST implémente la signature Schnorr à seuil RFC 9591. Du point de vue de l'application, cela est similaire au multisig : n'importe quel min de max participants peut produire conjointement une signature Schnorr sous une clé publique partagée. Les suites cryptographiques prises en charge sont p256_FROST, ed25519_FROST, ed448_FROST, ristretto255_FROST, secp256k1_FROST, et schnorr_FROST (secp256k1 compatible Taproot). La signature comporte deux tours : les signataires sélectionnés s'engagent d'abord, puis produisent les parts de signature.```js import { p256_FROST } from '@noble/curves/nist.js';

const signers = { min: 2, max: 3 }; const alice = p256_FROST.Identifier.derive('[email protected]'); const bob = p256_FROST.Identifier.derive('[email protected]'); const carol = p256_FROST.Identifier.derive('[email protected]'); // trusted dealer const deal = p256_FROST.trustedDealer(signers, [alice, bob, carol]); for (const id of [alice, bob, carol]) p256_FROST.validateSecret(deal.secretShares[id], deal.public);

const msg = new TextEncoder().encode('hello threshold'); // round 1: selected signers commit const aliceRound1 = p256_FROST.commit(deal.secretShares[alice]); const bobRound1 = p256_FROST.commit(deal.secretShares[bob]); const commitmentList = [aliceRound1.commitments, bobRound1.commitments]; // round 2: signers produce signature shares const sigShares = { [alice]: https://raw.githubusercontent.com/paulmillr/noble-curves/main/p256_FROST.signShare( deal.secretShares[alice], deal.public, aliceRound1.nonces, commitmentList, msg ), [bob]: https://raw.githubusercontent.com/paulmillr/noble-curves/main/p256_FROST.signShare( deal.secretShares[bob], deal.public, bobRound1.nonces, commitmentList, msg ), }; const sig = p256_FROST.aggregate(deal.public, commitmentList, msg, sigShares); const isValid = p256_FROST.verify(sig, msg, deal.public.commitments[0]);

root@kitploit:~
La génération de clés peut être effectuée avec un trusted dealer (ci-dessus) ou avec DKG (distributed key generation).
DKG comporte trois tours : les participants s'engagent sur la génération de clés, échangent des parts privées,
puis dérivent les clés finales des participants - voir l'utilisation de `DKG.round1` / `round2` / `round3` dans
[les tests](https://github.com/paulmillr/noble-curves/blob/main/test/rfc9591-frost.test.ts).
La bibliothèque implémente les étapes cryptographiques, pas le protocole applicatif environnant :
les appelants doivent toujours gérer la communication authentifiée, la coordination, les tentatives, la gestion de session et la politique.

### poseidon: Poseidon hash

Implémente le hash ZK-friendly [Poseidon](https://www.poseidon-hash.info) :
permutation et sponge.

Il existe de nombreuses variantes de poseidon avec des constantes différentes.
Nous ne les fournissons pas : vous devez les construire manuellement.
Consultez le paquet [scure-starknet](https://github.com/paulmillr/scure-starknet) pour un exemple approprié.```ts
import { bn254 } from '@noble/curves/bn254.js';
import { grainGenConstants, poseidon, poseidonSponge } from '@noble/curves/abstract/poseidon.js';

const rate = 2;
const capacity = 1;
const Fp = bn254.fields.Fr;
const { mds, roundConstants } = grainGenConstants({
  Fp,
  t: rate + capacity,
  roundsFull: 8,
  roundsPartial: 31,
});
const opts = {
  Fp,
  rate,
  capacity,
  sboxPower: 17,
  mds,
  roundConstants,
  roundsFull: 8,
  roundsPartial: 31,
};
const permutation = poseidon({ ...opts, t: rate + capacity });
const sponge = poseidonSponge(opts); // use carefully, not specced

fft : Transformée de Fourier rapide```ts

import * as fft from '@noble/curves/abstract/fft.js'; import { bls12_381 } from '@noble/curves/bls12-381.js'; const Fr = bls12_381.fields.Fr; const roots = fft.rootsOfUnity(Fr, 7n); const fftFr = fft.FFT(roots, Fr);

root@kitploit:~
NTT / FFT (Transformée de Fourier rapide) sur des corps finis.

### utils : réorganisation d'octets, conversion```ts
import { bytesToHex, concatBytes, equalBytes, hexToBytes } from '@noble/curves/utils.js';

bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23]));
hexToBytes('cafe0123');
concatBytes(Uint8Array.from([0xca, 0xfe]), Uint8Array.from([0x01, 0x23]));
equalBytes(Uint8Array.of(0xca), Uint8Array.of(0xca));

Détails internes

Arithmétique des points sur courbe elliptique```js

import { secp256k1 } from '@noble/curves/secp256k1.js'; const { Point } = secp256k1; const { BASE, ZERO, Fp, Fn } = Point; const p = BASE.multiply(2n);

// Math const p1 = p.add(p); const p2 = p.double(); const p3 = p.subtract(p); const p4 = p.negate(); const p5 = p.multiply(451n);

// MSM (multi-scalar multiplication) import { pippenger } from '@noble/curves/abstract/curve.js'; const pa = [BASE, BASE.multiply(2n), BASE.multiply(4n), BASE.multiply(8n)]; const p6 = pippenger(Point, pa, [3n, 5n, 7n, 11n]); // == BASE.multiply(129n)

// Cofactor const pcl = p.clearCofactor(); const isTorsionFree = p.isTorsionFree();

// Conversions const bytes = p.toBytes(); const p_ = Point.fromBytes(bytes); const { x, y } = p.toAffine(); const p__ = Point.fromAffine({ x, y });

root@kitploit:~
Chaque courbe expose sa classe Point : secp256k1, schnorr, p256, p384, p521, ed25519, ed448,
ristretto255, decaf448, bls12_381.G1 / G2, bn254.G1, jubjub, babyjubjub.
Les points Weierstrass utilisent des coordonnées projectives (homogènes) `new Point(X, Y, Z)`,
les points edwards utilisent des coordonnées étendues `new Point(X, Y, Z, T)` ; les deux avec x=X/Z, y=Y/Z.

#### modular : arithmétique modulaire et corps finis```js
import { mod, invert, Field } from '@noble/curves/abstract/modular.js';

// Finite Field utils
const fp = Field(2n ** 255n - 19n); // Finite field over 2^255-19
fp.mul(591n, 932n); // multiplication
fp.pow(481n, 11024858120n); // exponentiation
fp.div(5n, 17n); // division: 5/17 mod 2^255-19 == 5 * invert(17)
fp.inv(5n); // modular inverse
fp.sqrt(4n); // square root

// Non-Field generic utils are also available
mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse

Toute l'arithmétique est effectuée avec des bigints JS sur des corps finis, qui sont définis à partir du sous-module modular.

Les opérations sur les corps ne sont pas à temps constant : voir sécurité. Ce fait est généralement sans importance, mais la méthode importante à garder à l'esprit est pow, qui peut divulguer des bits de l'exposant lorsqu'elle est utilisée naïvement.

weierstrass : courbe de Weierstrass personnalisée & ECDSA```js

import { weierstrass, ecdsa } from '@noble/curves/abstract/weierstrass.js'; import { sha256 } from '@noble/hashes/sha2.js'; // NIST secp192r1 aka p192. https://www.secg.org/sec2-v2.pdf const p192_CURVE = { p: 0xfffffffffffffffffffffffffffffffeffffffffffffffffn, n: 0xffffffffffffffffffffffff99def836146bc9b1b4d22831n, h: 1n, a: 0xfffffffffffffffffffffffffffffffefffffffffffffffcn, b: 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1n, Gx: 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012n, Gy: 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811n, }; const p192_Point = weierstrass(p192_CURVE); const p192 = ecdsa(p192_Point, sha256);

const keys = p192.keygen(); const msg = new TextEncoder().encode('custom curve'); const sig = p192.sign(msg, keys.secretKey); const isValid = p192.verify(sig, msg, keys.publicKey);

root@kitploit:~
La formule de la courbe de Weierstrass courte est `y² = x³ + ax + b`. `weierstrass`
attend les arguments `a`, `b`, la caractéristique du corps `p`, l'ordre de la courbe `n`,
le cofacteur `h` et les coordonnées `Gx`, `Gy` du point générateur, et renvoie une classe Point.
`ecdsa` combine une classe Point avec une fonction de hachage en un schéma de signature.

#### edwards : Courbe d'Edwards personnalisée```js
import { edwards } from '@noble/curves/abstract/edwards.js';
const ed25519_CURVE = {
  p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
  n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,
  h: 8n,
  a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,
  d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,
  Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,
  Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n,
};
const ed25519_Point = edwards(ed25519_CURVE);

La formule de la courbe de Twisted Edwards est ax² + y² = 1 + dx²y². Vous devez spécifier a, d, la caractéristique du corps p, l'ordre de la courbe n (parfois nommé L), le cofacteur h et les coordonnées Gx, Gy du point générateur.

Spécifications

  • ECDSA : k déterministe selon RFC 6979, signatures couvertes selon le brouillon cfrg-det-sigs-with-noise
  • EdDSA : RFC 8032, FIPS 186-5 ; vérification compatible avec le consensus : ZIP215
  • Signatures Schnorr : BIP 340
  • X25519, X448 ECDH : RFC 7748
  • ristretto255, decaf448 : RFC 9496
  • hash-to-curve : RFC 9380
  • OPRFs : RFC 9497
  • FROST : RFC 9591
  • bn254 : EIP-196, EIP-197
  • Poseidon : site

Sécurité

La bibliothèque a été auditée :

  • à la version 2.3.0, en août 2026, par Trail of Bits, en collaboration avec OpenAI
    • Cela a été réalisé dans le cadre de l'initiative « Patch the Planet »
    • Périmètre : tout
  • à la version 1.6.0, en septembre 2024, indépendamment, par Cure53
    • PDFs : site web, dans le dépôt
    • Périmètre : ed25519, ed448, leurs modules complémentaires, bls12-381, bn254, hash-to-curve, primitives de bas niveau bls, tower, edwards, montgomery.
    • L'audit a été financé par OpenSats
  • à la version 1.2.0, en septembre 2023, indépendamment, par Kudelski Security
    • PDFs : dans le dépôt
    • Périmètre : scure-starknet et ses modules abstraits associés de noble-curves : curve, modular, poseidon, weierstrass
    • L'audit a été financé par Starkware
  • à la version 0.7.3, en février 2023, indépendamment, par Trail of Bits
    • PDFs : site web, dans le dépôt

Nous avons commencé des auto-audits réguliers assistés par IA en avril 2026.

Elle est testée contre des vecteurs basés sur les propriétés, inter-bibliothèques et Wycheproof, et est soumise au fuzzing dans la CI GitHub.

Si vous voyez quelque chose d'inhabituel : enquêtez et signalez-le.

Constance temporelle

Nous visons un temps algorithmique constant. Le compilateur JIT et le ramasse-miettes rendent la résistance aux attaques temporelles extrêmement difficile à atteindre dans un langage de script. Ce qui signifie que toute autre bibliothèque JS ne peut pas avoir de constance temporelle. Même Rust, un langage à typage statique sans GC, rend plus difficile l'obtention d'un temps constant dans certains cas. Si votre objectif est une sécurité absolue, n'utilisez aucune bibliothèque JS — y compris les bindings vers des bibliothèques natives. Utilisez des bibliothèques et des langages de bas niveau.

Dans ces limites, la multiplication par un scalaire secret fournit des propriétés spécifiques et mesurables :

  • Séquence d'opérations fixe : multiply() utilise des tables à fenêtre fixe signée avec des parcours de table indépendants des données — le nombre et l'ordre des opérations sur les points sont indépendants de la valeur du scalaire.
  • Aveuglement du scalaire : les scalaires secrets sont en outre masqués par s + r·n avec un r aléatoire de 128 bits avant la multiplication. Cela s'applique à toutes les multiplications sur les courbes de cofacteur 1 (p256, p384, p521, secp256k1), et aux multiplications par le point de base partout.
  • Validation statistique : un harnais de test t de Welch de style dudect (benchmark/ct.ts) compare les temps d'exécution entre des classes de scalaires adverses (creux vs denses, bits faibles vs élevés, proches de l'ordre, motifs binaires). La multiplication par le point de base ne montre aucun temps distinguable sur aucune courbe, et la multiplication par un point aléatoire n'en montre aucun sur les courbes de Weierstrass (max |t| ≤ 2,8 à 1000 échantillons ; seuil 4,5).

Limitation connue : sur les courbes d'Edwards à cofacteur (ed25519, ed448), la multiplication d'un point non-base par un scalaire secret n'est pas aveuglée. Le même harnais détecte cela de manière fiable. La signature EdDSA n'est pas affectée (elle ne multiplie que le point de base aveuglé), et X25519/X448 utilisent une implémentation séparée d'échelle de Montgomery (également non affectée). Cela importe pour les protocoles qui multiplient des points Edwards/Ristretto arbitraires par des scalaires secrets de longue durée ; préférez-y des scalaires de pleine largeur par construction. Notez que la détectabilité dans un harnais isolé n'implique pas une exploitabilité pratique : nous avons tenté une extraction de scalaire dans un cadre réaliste multi-locataires / en navigateur et n'avons pas pu récupérer les scalaires Edwards même avec 100 000 échantillons temporels.

Vidage mémoire

Utilisez des langages de bas niveau plutôt que JS / WASM si votre objectif est une sécurité absolue.

La bibliothèque utilise principalement des Uint8Arrays et des bigints.

  • Les Uint8Arrays ont .fill(0) qui demande de remplir le contenu avec des zéros mais il n'y a aucune garantie en JS
  • Les bigints sont immuables et n'ont pas de méthode pour effacer leur contenu : un utilisateur doit attendre le prochain cycle de ramasse-miettes
  • Les chaînes hexadécimales sont également immuables : il n'y a aucun moyen de les effacer
  • await fn() écrira toutes les variables internes en mémoire. Avec les fonctions asynchrones, il n'y a aucune garantie quant au moment où le bloc de code serait exécuté. Ce qui signifie qu'un attaquant peut avoir amplement le temps de lire les données en mémoire.

Cela signifie que certains secrets pourraient rester en mémoire plus longtemps que prévu. Cependant, si un attaquant peut lire la mémoire de l'application, tout est perdu de toute façon : il n'y a aucun moyen de garantir quoi que ce soit concernant l'effacement des données sensibles sans une suite de tests complexe qui videra la mémoire du processus et vérifiera qu'il ne reste aucune donnée sensible. Pour JS, cela signifie tester tous les navigateurs (y compris mobiles). Et, bien sûr, cela sera inutile sans utiliser la même suite de tests dans l'application réelle qui consomme la bibliothèque.

Sécurité de la chaîne d'approvisionnement

  • Les commits sont signés avec des clés PGP pour prévenir la falsification. Assurez-vous de vérifier les signatures des commits
  • Les versions sont publiées de manière transparente via la CI GitHub sans token et Trusted Publishing. Assurez-vous de vérifier les journaux de provenance pour l'authenticité.
  • La publication rare est pratiquée pour minimiser le besoin de ré-audits par les utilisateurs finaux.
  • Les dépendances sont minimisées et strictement épinglées pour réduire le risque de chaîne d'approvisionnement.
    • Nous utilisons aussi peu de dépendances que possible.
    • Les plages de versions sont verrouillées, et les changements sont vérifiés avec npm-diff.
  • Les dépendances de développement sont exclues des installations des utilisateurs finaux ; elles ne sont utilisées que pour le développement et les étapes de build.

Pour ce paquet, il y a 1 dépendance ; et quelques dépendances de développement :

  • noble-hashes fournit des fonctionnalités de hachage cryptographique
  • jsbt est utilisé pour le benchmarking / les tests / l'outillage de build et est développé par le même auteur
  • prettier, fast-check et typescript sont utilisés pour la qualité du code / la génération de tests / la compilation ts

Aléatoire

Nous nous appuyons sur la fonction intégrée crypto.getRandomValues, qui est considérée comme un PRNG cryptographiquement sûr.

Les navigateurs ont eu des faiblesses par le passé — et pourraient en avoir à nouveau — mais implémenter un CSPRNG en espace utilisateur est encore pire, car il n'existe pas de source fiable d'entropie de haute qualité en espace utilisateur.

Ordinateurs quantiques

Un ordinateur quantique cryptographiquement pertinent, s'il est construit, permettra de casser la cryptographie sur courbes elliptiques (à la fois ECDSA / EdDSA et ECDH) en utilisant l'algorithme de Shor.

Envisagez de passer à des algorithmes plus récents / hybrides, tels que SPHINCS+. Ils sont disponibles dans noble-post-quantum.

Le NIST interdit la cryptographie classique (RSA, DSA, ECDSA, ECDH) après 2035. L'ASD australien l'interdit après 2030.

Vitesse```sh

npm run benchmark

root@kitploit:~
noble-curves passe plus de 10 ms à générer plus de 20 Mo de précalculs de points de base.
Cela est effectué **une seule fois** par courbe.

La génération est différée jusqu'à ce qu'une méthode (pubkey, sign, verify) soit appelée.
L'utilisateur peut forcer la génération des précalculs en appelant manuellement `Point.BASE.precompute(windowSize, false)`.
Consultez le code source.

Résultats de benchmark sur Apple M4 :```
# algorithm=getPublicKey
ed25519                    7,299 ops/sec · 137 μs/op
secp256k1                  4,872 ops/sec · 205 μs/op · -1.5x
p256                       4,724 ops/sec · 212 μs/op · -1.5x
bls12_381 (long, G2 sig)   3,466 ops/sec · 288 μs/op · -2.1x
ed448                      3,224 ops/sec · 310 μs/op · -2.3x
p384                       2,185 ops/sec · 458 μs/op · -3.3x
p521                       1,221 ops/sec · 819 μs/op · -6x
bls12_381 (short, G1 sig)  1,070 ops/sec · 934 μs/op · -6.8x

# algorithm=sign
secp256k1                  4,217 ops/sec · 237 μs/op
p256                       4,116 ops/sec · 243 μs/op · ≈
ed25519                    3,536 ops/sec · 283 μs/op · -1.2x
p384                       1,992 ops/sec · 502 μs/op · -2.1x
ed448                      1,577 ops/sec · 634 μs/op · -2.7x
p521                       1,131 ops/sec · 884 μs/op · -3.7x
bls12_381 (short, G1 sig)  417 ops/sec · 2.39 ms/op · -10x
bls12_381 (long, G2 sig)   112 ops/sec · 8.88 ms/op · -37x

# algorithm=verify
ed25519                    1,504 ops/sec · 665 μs/op
secp256k1                  1,352 ops/sec · 739 μs/op · -1.1x
p256                       917 ops/sec · 1.09 ms/op · -1.6x
ed448                      546 ops/sec · 1.83 ms/op · -2.8x
p384                       381 ops/sec · 2.62 ms/op · -3.9x
p521                       187 ops/sec · 5.34 ms/op · -8x
bls12_381 (short, G1 sig)  100 ops/sec · 9.98 ms/op · -15x
bls12_381 (long, G2 sig)   77 ops/sec · 12.9 ms/op · -19x

# algorithm=getSharedSecret
ed25519                    1,695 ops/sec · 590 μs/op
secp256k1                  763 ops/sec · 1.31 ms/op · -2.2x
p256                       737 ops/sec · 1.36 ms/op · -2.3x
ed448                      599 ops/sec · 1.67 ms/op · -2.8x
p384                       326 ops/sec · 3.06 ms/op · -5.2x
p521                       176 ops/sec · 5.68 ms/op · -9.6x

Mise à niveau

Versions de node.js prises en charge :

  • v2 (2025-08) : v20.19+ (ESM uniquement)
  • v1 (2023-04) : v14.21+ (ESM & CJS)

v1 vers v2

v2 simplifie massivement les internes, améliore la sécurité, réduit la taille du bundle et prépare l'avenir. Nous avons essayé de conserver v2 aussi rétrocompatible que possible.

Chemin de mise à niveau : mettez d'abord à niveau vers curves v1.9.x. Corrigez les avertissements de dépréciation, puis passez à v2.

Modules :

  • Le paquet est désormais ESM uniquement. ESM peut enfin être chargé depuis common.js sur node v20.19+
  • L'extension .js est désormais requise : @noble/curves/ed25519 => @noble/curves/ed25519.js. Cela permet une utilisation native dans le navigateur, sans transpileurs
  • p256, p384, p521 ont été déplacés dans nist ; jubjub a été déplacé dans misc
  • Les courbes pasta et bn254_weierstrass (bn254 NON basé sur le pairing) ont été supprimées

Nouvelles fonctionnalités :

  • webcrypto : wrapper convivial de type noble au-dessus de WebCrypto intégré
  • oprf : OPRF RFC 9497 (fonctions pseudorandom oblivious) pour p256, p384, p521, ristretto255 et decaf448
  • weierstrass, edwards : nouvelles méthodes isValidSecretKey, isValidPublicKey
  • misc : courbes Brainpool brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
  • Messages d'erreur massivement améliorés et plus descriptifs

Changements incompatibles :

  • La plupart des méthodes n'acceptent désormais que Uint8Array ; les entrées hexadécimales sous forme de chaîne sont interdites. Cela simplifie le raisonnement, améliore la sécurité et réduit la malléabilité. Point.fromHex est désormais réservé aux chaînes : utilisez Point.fromBytes pour Uint8Array
  • ECDSA (secp256k1, p256, p384...) sign & verify :
    • Messages préhachés : les méthodes attendent désormais le message non haché au lieu de messageHash. Ancien comportement : {prehash: false}
    • Signatures lowS par défaut. secp256k1 n'est pas affecté : il utilise lowS depuis le début. Ancien comportement : {lowS: false}
    • Signatures Uint8Array (format : 'compact') par défaut
    • verify : le format der doit être explicitement spécifié dans {format: 'der'}. Cela réduit la malléabilité
    • verify : les instances Signature sont interdites : appelez d'abord signature.toBytes()
  • Signatures BLS (bls12-381, bn254) :
    • getPublicKey, sign, verify, signShortSignature etc ont été déplacés dans deux nouveaux namespaces : longSignatures (clés publiques G1, signatures G2) et shortSignatures (signatures G1, clés publiques G2)
    • verifyBatch attend désormais un tableau d'entrées {message: ..., publicKey: ...}[]

Renommages (curves v1.9 met en évidence les anciens noms comme dépréciés) :

  • Points
    • ExtendedPoint, ProjectivePoint => Point
    • Coordonnées de Point px/ex, py/ey, pz/ez, et => X, Y, Z, T
    • toRawBytes, fromRawBytes => toBytes, fromBytes
    • Point.normalizeZ, Point.msm => méthodes séparées dans le sous-module abstract/curve.js
    • Point.fromPrivateKey(key) => Point.BASE.multiply(Point.Fn.fromBytes(key))
    • Propriété CURVE avec toutes sortes de choses aléatoires => Point.CURVE(), qui ne fournit que les paramètres de courbe
    • RistrettoPoint => ristretto255.Point, DecafPoint => decaf448.Point
  • Signatures ECDSA
    • toCompactRawBytes, toDERRawBytes => toBytes('compact'), toBytes('der')
    • toCompactHex, toDERHex => toHex('compact'), toHex('der')
    • fromCompact, fromDER => fromBytes(bytes, format), fromHex(hex, format)
  • utils
    • randomPrivateKey => randomSecretKey
    • normPrivateKeyToScalar => Point.Fn.fromBytes
    • utils.precompute, Point#_setWindowSize => Point#precompute
    • edwardsToMontgomery, edwardsToMontgomeryPriv => utils.toMontgomery, utils.toMontgomerySecret
  • Méthodes hash-to-curve spécifiques à une courbe => *curve*_hasher. Exemple : secp256k1.hashToCurve => secp256k1_hasher.hashToCurve()
  • Renommages et améliorations massifs des types

Fonctionnalités supprimées : Point#multiplyAndAddUnsafe, Point#hasEvenY, Field.MASK

Contribution & tests

npm install && npm run build && npm test compilera le code et exécutera les tests.

Il existe des suites supplémentaires : tests lents à grand scalaire / grande courbe npm run test:slow, et le harnais de constance temporelle npm run benchmark:ct.

Voir paulmillr.com/noble pour des ressources utiles, des articles, de la documentation et des démos liés à la bibliothèque.

Licence

The MIT License (MIT)

Copyright (c) 2022 Paul Miller (https://paulmillr.com)

Voir le fichier LICENSE.

Télécharger l’outil
  • Périmètre : modules abstraits curve, hash-to-curve, modular, poseidon, utils, weierstrass et modules de haut niveau _shortw_utils et secp256k1
  • L'audit a été financé par Ryan Shea
  • Courbes personnalisées :
    • La création de courbes a été massivement simplifiée et scindée en création de points & création de générateur de signatures : weierstrass() + ecdsa() / edwards() + eddsa(). weierstrass / edwards attendent des paramètres de courbe simplifiés (Fp est devenu p) ; ecdsa / eddsa attendent la classe Point et le hash
    • pippenger : suppression de l'argument Fn inutile
    • Field#fromBytes() valide désormais que les éléments sont dans la plage 0..order-1