Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
noble-curves — Implementazione JS minimale e verificata di crittografia a curva ellittica. | Kitploit
Strumenti/GitHubGitHub/paulmillr/noble-curves
Strumenti di Crittografia/DecrittografiaAnalisi HashCrittografiaUtilità e FrameworkApprendimento e Formazione
GitHubpaulmillr/noble-curves

noble-curves

Implementazione JS minimale e verificata di crittografia a curva ellittica.

Vedi Repository
958101157 giorni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
Sito web

noble-curves

Implementazione JS minimale e verificata di crittografia a curve ellittiche.

  • 🔒 Verificata da società di sicurezza indipendenti
  • 🪶 Minimale: 15KB (gzip) secp256k1, il codice inutilizzato è escluso dalle tue build
  • 🏎 Veloce: ottimizzata manualmente per le particolarità dei motori JS
  • 🔍 Affidabile: test cross-library / wycheproof garantiscono la correttezza
  • ➰ Curve di Weierstrass, Edwards; firme ECDSA, EdDSA, Schnorr, BLS
  • ✍️ ECDH, hash-to-curve, OPRF, FROST, hash Poseidon, FFT
  • 🔖 Non ripudio (SUF-CMA, SBS) e compatibilità con il consenso (ZIP215) in ed25519, ed448
  • 🥈 Wrapper con API identica su WebCrypto nativo

Le curve hanno progetti gemelli da 5kb secp256k1 & ed25519. Hanno una superficie di attacco più piccola, ma meno funzionalità.

Questa libreria appartiene alla crittografia noble

noble cryptography — set di librerie e strumenti crittografici ad alta sicurezza e facilmente verificabili.

  • Dipendenze zero o minime
  • Codice TypeScript / JS altamente leggibile
  • Release firmate con PGP e build NPM trasparenti
  • Tutte le librerie: ciphers, curves, hashes, post-quantum, 5kb secp256k1 / ed25519
  • Versione WASM: awasm-noble
  • Dai un'occhiata alla homepage per risorse di lettura, documentazione e app costruite con noble

Utilizzo

npm install @noble/curves

deno add jsr:@noble/curves

Supportiamo tutte le principali piattaforme e runtime. Per React Native, potresti aver bisogno di un polyfill per getRandomValues. È disponibile anche un file standalone noble-curves.js.```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:~
- [Firme ECDSA, EdDSA, Schnorr](#ecdsa-eddsa-schnorr-signatures)
- [ECDH: segreti condivisi Diffie-Hellman](#ecdh-diffie-hellman-shared-secrets)
- [webcrypto: wrapper semplificato](#webcrypto-friendly-wrapper)
- [Firme BLS, bls12-381, bn254 aka alt\_bn128](#bls-signatures-bls12-381-bn254-aka-alt_bn128)
- [hash-to-curve: hashing verso punti della curva](#hash-to-curve-hashing-to-curve-points)
- [OPRF](#oprfs) | [Firme soglia FROST](#frost-threshold-signatures)
- [poseidon: hash Poseidon](#poseidon-poseidon-hash) | [fft: Trasformata di Fourier veloce](#fft-fast-fourier-transform) | [utils](#utils-byte-shuffling-conversion)
- Interni: [Aritmetica dei punti](#elliptic-curve-point-math) | [modulare](#modular-modular-arithmetics--finite-fields) | [curve personalizzate](#weierstrass-custom-weierstrass-curve--ecdsa)
- [Specifiche](#specs)
- [Sicurezza](#security) | [Velocità](#speed) | [Aggiornamento](#upgrading) | [Contribuire e testare](#contributing--testing) | [Licenza](#license)

### Firme 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);

I messaggi vengono sempre sottoposti prima a hash: vedi firma pre-hashed. ECDSA utilizza k deterministico, EdDSA segue RFC 8032, Schnorr (solo secp256k1) segue BIP 340: vedi Specifiche.

Lo schema di firma MuSig2 e la mappatura BIP324 ElligatorSwift per secp256k1 sono disponibili in un pacchetto separato.

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:~
Consulta [RFC 9496](https://www.rfc-editor.org/rfc/rfc9496) per maggiori informazioni su ristretto255 e decaf448.
Consulta la documentazione separata per [Point](#elliptic-curve-point-math), [hasher](#hash-to-curve-hashing-to-curve-points) e [oprf](#oprfs).

#### Firma pre-hashed```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 });

Per impostazione predefinita (prehash: true), sign() e verify() applicano prima l'hash integrato della curva al messaggio: sha256 per secp256k1, sha512 per p521. prehash: false consente di utilizzare un hash personalizzato (ad es. secp256k1 + keccak_256). In noble-curves v1, prehash: false era l'impostazione predefinita.

Recupero delle chiavi pubbliche dalle firme```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:~
Il recupero della chiave pubblica è supportato solo con ECDSA. È una semplice operazione matematica:
non ci sono garanzie che la firma sia stata effettivamente eseguita. Una tupla (r, s, h) falsificata viene recuperata in
una chiave pubblica casuale, ma non è fattibile trovare m che porterebbe a questo specifico h falsificato.

#### ECDSA con copertura tramite rumore```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 });

Per impostazione predefinita, le firme ECDSA sono deterministiche (RFC 6979). Le firme puramente deterministiche sono vulnerabili agli attacchi di tipo fault, quindi schemi più recenti, come BIP340 schnorr, incorporano casualità nella generazione della firma - ovvero hedging. extraEntropy abilita la modalità hedged. Per maggiori informazioni, consulta 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` (predefinito) utilizza le regole di verifica più permissive, [compatibili con il consenso](https://hdevalence.ca/blog/2020-10-04-its-25519am), definite in [ZIP215](https://zips.z.cash/zip-0215).
* `zip215: false` applica la verifica rigorosa RFC 8032 / FIPS 186-5 e aggiunge il
  non-ripudio basato su SBS, utile per la firma di contratti, il voto elettronico e le blockchain.

Entrambe le modalità dispongono di SUF-CMA (strong unforgeability under chosen message attacks);
la maggior parte delle altre librerie non dispone né di SUF-CMA né di SBS.
Per maggiori informazioni, consultare [Taming the many EdDSAs](https://eprint.iacr.org/2020/1244).

### ECDH: segreti condivisi 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);

Forniamo ECDH su tutte le curve Weierstrass, e su 2 curve Montgomery X25519 (Curve25519) e X448 (Curve448), conformi a RFC 7748.

Nelle curve Weierstrass, i segreti condivisi:

  • Includono i byte di parità di y: usa key.slice(1) per rimuoverli
  • Non sono sottoposti a hash: usa hashing o KDF sopra, come sha256(shared) o hkdf(shared)

webcrypto: wrapper amichevole```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 sottile wrapper su WebCrypto integrato, che rispecchia l'API noble. I metodi sono sempre asincroni;
il supporto a runtime varia - verifica con `await curve.isSupported()`.
Dai un'occhiata a [micro-key-producer](https://github.com/paulmillr/micro-key-producer) per
utility di conversione chiavi in puro JS.

### Firme BLS, bls12-381, bn254 aka 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

Per un esempio di utilizzo, consulta l'implementazione dei precompilati BLS EVM.

L'API BN254 rispecchia bls12-381. La curva era precedentemente chiamata alt_bn128. L'implementazione è compatibile con EIP-196 e EIP-197: consulta l'implementazione dei precompilati bn254 EVM. I punti bn254 non implementano toBytes, poiché non esiste uno standard di serializzazione: le implementazioni divergono su endianness, flag e ordine della parte immaginaria di G2. Inizializza i punti da bigint.

hash-to-curve: hashing verso punti della curva```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:~
Il modulo consente di eseguire l'hashing di stringhe arbitrarie su punti di curve ellittiche. Implementa [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
I namespace `_hasher` sono separati dalle curve per il tree-shaking:
gli utenti che non necessitano di hash-to-curve non lo avranno nelle loro build.

### OPRF```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';

Forniamo OPRF (oblivious pseudorandom functions), conformi a RFC 9497.

OPRF consente di creare in modo interattivo un Output = PRF(Input, serverSecretKey):

  • Il server non può calcolare Output da solo: non conosce Input
  • Il client non può calcolare Output da solo: non conosce server secretKey
  • Un attaccante che intercetta la comunicazione non può ripristinare Input/Output/serverSecretKey e non può collegare Input a un qualche valore.

Firme soglia FROST

FROST implementa la firma Schnorr soglia di RFC 9591. È simile al multisig dal punto di vista dell'applicazione: qualsiasi min di max partecipanti può produrre congiuntamente una firma Schnorr sotto una chiave pubblica condivisa. Le ciphersuite supportate sono p256_FROST, ed25519_FROST, ed448_FROST, ristretto255_FROST, secp256k1_FROST, e schnorr_FROST (secp256k1 compatibile con Taproot). La firma ha due round: i firmatari selezionati si impegnano prima, poi producono le quote di firma.```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 generazione delle chiavi può essere effettuata con un trusted dealer (sopra) o con DKG (distributed key generation).
DKG prevede tre round: i partecipanti si impegnano nella generazione delle chiavi, scambiano le quote private,
poi derivano le chiavi finali dei partecipanti - vedi l'utilizzo di `DKG.round1` / `round2` / `round3` in
[the tests](https://github.com/paulmillr/noble-curves/blob/main/test/rfc9591-frost.test.ts).
La libreria implementa i passaggi crittografici, non il protocollo applicativo circostante:
chi la utilizza deve comunque gestire comunicazione autenticata, coordinamento, retry, gestione delle sessioni e policy.

### poseidon: Poseidon hash

Implementa l'hash ZK-friendly [Poseidon](https://www.poseidon-hash.info):
permutazione e sponge.

Esistono molte varianti di poseidon con costanti diverse.
Non le forniamo: dovresti costruirle manualmente.
Dai un'occhiata al pacchetto [scure-starknet](https://github.com/paulmillr/scure-starknet) per un esempio adeguato.```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: Trasformata di Fourier veloce```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 (Fast Fourier Transform) su campi finiti.

### utils: byte shuffling, conversione```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));

Internals

Aritmetica dei punti su curve ellittiche```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:~
Ogni curva espone la sua classe Point: secp256k1, schnorr, p256, p384, p521, ed25519, ed448,
ristretto255, decaf448, bls12_381.G1 / G2, bn254.G1, jubjub, babyjubjub.
I punti Weierstrass usano coordinate proiettive (omogenee) `new Point(X, Y, Z)`,
i punti edwards usano coordinate estese `new Point(X, Y, Z, T)`; entrambi con x=X/Z, y=Y/Z.

#### modular: Aritmetica modulare e campi finiti```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

Tutte le operazioni aritmetiche sono eseguite con bigint JS su campi finiti, definiti dal sottomodulo modular.

Le operazioni sui campi non sono a tempo costante: vedere security. Il fatto è per lo più irrilevante, ma il metodo importante da tenere a mente è pow, che può rivelare i bit dell'esponente, se usato ingenuamente.

weierstrass: curva Weierstrass personalizzata & 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 formula della curva di Weierstrass in forma breve è `y² = x³ + ax + b`. `weierstrass`
si aspetta gli argomenti `a`, `b`, la caratteristica del campo `p`, l'ordine della curva `n`,
il cofattore `h` e le coordinate `Gx`, `Gy` del punto generatore, e restituisce una classe Point.
`ecdsa` combina una classe Point con una funzione di hash in uno schema di firma.

#### edwards: Curva di Edwards personalizzata```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 formula della curva di Twisted Edwards è ax² + y² = 1 + dx²y². È necessario specificare a, d, la caratteristica del campo p, l'ordine della curva n (talvolta chiamato L), il cofattore h e le coordinate Gx, Gy del punto generatore.

Specifiche

  • ECDSA: k deterministico da RFC 6979, firme hedged dalla bozza cfrg-det-sigs-with-noise
  • EdDSA: RFC 8032, FIPS 186-5; verifica consensus-friendly: ZIP215
  • Firme Schnorr: BIP 340
  • X25519, X448 ECDH: RFC 7748
  • ristretto255, decaf448: RFC 9496
  • hash-to-curve: RFC 9380
  • OPRF: RFC 9497
  • FROST: RFC 9591
  • bn254: EIP-196, EIP-197
  • Poseidon: sito

Sicurezza

La libreria è stata sottoposta a audit:

  • alla versione 2.3.0, in Aug 2026, da Trail of Bits, in collaborazione con OpenAI
    • È stato eseguito durante l'iniziativa "Patch the Planet"
    • Ambito: tutto
  • alla versione 1.6.0, in Sep 2024, in modo indipendente, da Cure53
    • PDF: sito web, nel repository
    • Ambito: ed25519, ed448, i loro componenti aggiuntivi, bls12-381, bn254, hash-to-curve, primitive di basso livello bls, tower, edwards, montgomery.
    • L'audit è stato finanziato da OpenSats
  • alla versione 1.2.0, in Sep 2023, in modo indipendente, da Kudelski Security
    • PDF: nel repository
    • Ambito: scure-starknet e i suoi moduli astratti correlati di noble-curves: curve, modular, poseidon, weierstrass
    • L'audit è stato finanziato da Starkware
  • alla versione 0.7.3, in Feb 2023, in modo indipendente, da Trail of Bits
    • PDF: sito web, nel repository

Abbiamo avviato regolari self-audit assistiti dall'IA in Apr 2026.

È testata contro vettori property-based, cross-library e Wycheproof, ed è sottoposta a fuzzing nella CI di github.

Se noti qualcosa di insolito: indaga e segnala.

Constant-timeness

Puntiamo al tempo costante algoritmico. Il compilatore JIT e il Garbage Collector rendono estremamente difficile ottenere la resistenza ai timing attack con "tempo costante" in un linguaggio di scripting. Il che significa che qualsiasi altra libreria JS non può avere constant-timeness. Persino Rust, un linguaggio tipizzato staticamente senza GC, rende più difficile ottenere il tempo costante in alcuni casi. Se il tuo obiettivo è la sicurezza assoluta, non usare alcuna libreria JS — incluse le binding a librerie native. Usa librerie e linguaggi di basso livello.

Entro questi limiti, la moltiplicazione per scalare segreto fornisce proprietà specifiche e misurabili:

  • Sequenza di operazioni fissa: multiply() usa tabelle a finestra fissa con segno e scansioni di tabella data-oblivious — il numero e l'ordine delle operazioni sui punti sono indipendenti dal valore dello scalare.
  • Blinding dello scalare: gli scalari segreti sono inoltre mascherati come s + r·n con un r casuale a 128 bit prima della moltiplicazione. Questo si applica a tutte le moltiplicazioni su curve con cofattore 1 (p256, p384, p521, secp256k1), e alle moltiplicazioni per il punto base ovunque.
  • Validazione statistica: un harness dudect-style con test t di Welch (benchmark/ct.ts) confronta i tempi tra classi di scalari avversariali (sparsi vs densi, bit bassi vs alti, vicini all'ordine, pattern di bit). La moltiplicazione per il punto base non mostra tempi distinguibili su nessuna curva, e la moltiplicazione per punto casuale non ne mostra sulle curve Weierstrass (max |t| ≤ 2.8 a 1000 campioni; soglia 4.5).

Limitazione nota: sulle curve Edwards con cofattore (ed25519, ed448), moltiplicare un punto non-base per uno scalare segreto non è sottoposto a blinding. Lo stesso harness rileva questo in modo affidabile. La firma EdDSA non è interessata (moltiplica solo il punto base sottoposto a blinding), e X25519/X448 usano una separata implementazione a scala di Montgomery (anch'essa non interessata). È rilevante per i protocolli che moltiplicano punti Edwards/Ristretto arbitrari per scalari segreti di lunga durata; in quei casi preferisci scalari a larghezza piena per costruzione. Nota che la rilevabilità in un harness isolato non implica sfruttabilità pratica: abbiamo tentato l'estrazione dello scalare in un contesto realistico cross-tenant / in-browser e non siamo riusciti a recuperare gli scalari Edwards nemmeno con 100.000 campioni di timing.

Memory dumping

Usa linguaggi di basso livello invece di JS / WASM se il tuo obiettivo è la sicurezza assoluta.

La libreria usa principalmente Uint8Array e bigint.

  • Gli Uint8Array hanno .fill(0) che indica di riempire il contenuto con zeri ma non ci sono garanzie in JS
  • I bigint sono immutabili e non hanno un metodo per azzerare il loro contenuto: un utente deve attendere il successivo ciclo di garbage collection
  • Le stringhe esadecimali sono anch'esse immutabili: non c'è modo di azzerarle
  • await fn() scriverà tutte le variabili interne in memoria. Con le funzioni async non ci sono garanzie su quando il blocco di codice verrebbe eseguito. Il che significa che un attaccante può avere molto tempo per leggere i dati dalla memoria.

Questo significa che alcuni segreti potrebbero rimanere in memoria più a lungo del previsto. Tuttavia, se un attaccante può leggere la memoria dell'applicazione, è comunque spacciato: non c'è modo di garantire nulla sull'azzeramento di dati sensibili senza una complessa suite di test che effettui il dump della memoria del processo e verifichi che non sia rimasto alcun dato sensibile. Per JS questo significa testare tutti i browser (inclusi quelli mobile). E, naturalmente, sarà inutile senza usare la stessa suite di test nell'applicazione reale che consuma la libreria.

Sicurezza della supply chain

  • I Commit sono firmati con chiavi PGP per prevenire falsificazioni. Assicurati di verificare le firme dei commit
  • Le Release sono effettuate in modo trasparente tramite CI GitHub senza token e Trusted Publishing. Assicurati di verificare i log di provenienza per l'autenticità.
  • Il rilascio raro è praticato per minimizzare la necessità di ri-audit da parte degli utenti finali.
  • Le Dipendenze sono minimizzate e rigorosamente bloccate per ridurre il rischio della supply-chain.
    • Usiamo il minor numero possibile di dipendenze.
    • Gli intervalli di versione sono bloccati, e le modifiche sono verificate con npm-diff.
  • Le Dipendenze di sviluppo sono escluse dalle installazioni degli utenti finali; sono usate solo per lo sviluppo e le fasi di build.

Per questo pacchetto, c'è 1 dipendenza; e alcune dipendenze di sviluppo:

  • noble-hashes fornisce funzionalità di hashing crittografico
  • jsbt è usato per benchmarking / testing / tooling di build ed è sviluppato dallo stesso autore
  • prettier, fast-check e typescript sono usati per la qualità del codice / la generazione di test / la compilazione ts

Casualità

Ci affidiamo alla funzione integrata crypto.getRandomValues, che è considerata un PRNG crittograficamente sicuro.

I browser hanno avuto debolezze in passato - e potrebbero averne di nuovo - ma implementare un CSPRNG in userspace è persino peggio, poiché non esiste una fonte affidabile in userspace di entropia di alta qualità.

Computer quantistici

Un computer quantistico crittograficamente rilevante, se costruito, permetterà di violare la crittografia a curve ellittiche (sia ECDSA / EdDSA che ECDH) usando l'algoritmo di Shor.

Considera di passare ad algoritmi più recenti / ibridi, come SPHINCS+. Sono disponibili in noble-post-quantum.

NIST vieta la crittografia classica (RSA, DSA, ECDSA, ECDH) dopo il 2035. L'ASD australiano la vieta dopo il 2030.

Velocità```sh

npm run benchmark

root@kitploit:~
noble-curves impiega più di 10 ms per generare oltre 20 MB di precalcoli del punto base.
Questa operazione viene eseguita **una sola volta** per curva.

La generazione viene posticipata fino a quando non viene chiamato un metodo qualsiasi (pubkey, sign, verify).
L'utente può forzare la generazione dei precalcoli chiamando manualmente `Point.BASE.precompute(windowSize, false)`.
Dai un'occhiata al codice sorgente.

Risultati del benchmark su 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

Aggiornamento

Versioni di node.js supportate:

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

da v1 a v2

v2 semplifica enormemente gli interni, migliora la sicurezza, riduce la dimensione del bundle e apre la strada per il futuro. Abbiamo cercato di mantenere v2 il più possibile retrocompatibile.

Percorso di aggiornamento: aggiorna prima a curves v1.9.x. Correggi gli avvisi di deprecazione, poi passa a v2.

Moduli:

  • Il pacchetto ora è solo ESM. ESM può finalmente essere caricato da common.js su node v20.19+
  • L'estensione .js ora è obbligatoria: @noble/curves/ed25519 => @noble/curves/ed25519.js. Questo abilita l'uso nativo nel browser, senza transpiler
  • p256, p384, p521 sono stati spostati in nist; jubjub è stato spostato in misc
  • Le curve pasta e bn254_weierstrass (NON bn254 basata su pairing) sono state rimosse

Nuove funzionalità:

  • webcrypto: wrapper amichevole in stile noble sopra WebCrypto integrato
  • oprf: OPRF RFC 9497 (funzioni pseudorandom oblivious) per p256, p384, p521, ristretto255 e decaf448
  • weierstrass, edwards: nuovi metodi isValidSecretKey, isValidPublicKey
  • misc: curve Brainpool brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
  • Messaggi di errore enormemente migliorati e più descrittivi

Modifiche incompatibili:

  • La maggior parte dei metodi ora accetta solo Uint8Array; gli input stringa esadecimale sono proibiti. Questo semplifica il ragionamento, migliora la sicurezza e riduce la malleabilità. Point.fromHex ora è solo per stringhe: usa Point.fromBytes per Uint8Array
  • ECDSA (secp256k1, p256, p384...) sign & verify:
    • Messaggi pre-hash: i metodi ora si aspettano il messaggio non hash invece di messageHash. Vecchio comportamento: {prehash: false}
    • firme lowS per impostazione predefinita. secp256k1 non è interessata: ha usato lowS fin dall'inizio. Vecchio comportamento: {lowS: false}
    • firme Uint8Array (formato: 'compact') per impostazione predefinita
    • verify: il formato der deve essere specificato esplicitamente in {format: 'der'}. Questo riduce la malleabilità
    • verify: le istanze Signature sono proibite: chiama prima signature.toBytes()
  • Firme BLS (bls12-381, bn254):
    • getPublicKey, sign, verify, signShortSignature ecc. sono stati spostati in due nuovi namespace: longSignatures (pubkey G1, firme G2) e shortSignatures (firme G1, pubkey G2)
    • verifyBatch ora si aspetta un array di input {message: ..., publicKey: ...}[]

Rinomine (curves v1.9 evidenzia i vecchi nomi come deprecati):

  • Punti
    • ExtendedPoint, ProjectivePoint => Point
    • Coordinate dei punti px/ex, py/ey, pz/ez, et => X, Y, Z, T
    • toRawBytes, fromRawBytes => toBytes, fromBytes
    • Point.normalizeZ, Point.msm => metodi separati nel sottomodulo abstract/curve.js
    • Point.fromPrivateKey(key) => Point.BASE.multiply(Point.Fn.fromBytes(key))
    • Proprietà CURVE con ogni tipo di roba casuale => Point.CURVE(), che fornisce solo i parametri della curva
    • RistrettoPoint => ristretto255.Point, DecafPoint => decaf448.Point
  • Firme 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
  • Metodi hash-to-curve specifici per curva => *curve*_hasher. Esempio: secp256k1.hashToCurve => secp256k1_hasher.hashToCurve()
  • Enormi rinominazioni e miglioramenti dei tipi

Funzionalità rimosse: Point#multiplyAndAddUnsafe, Point#hasEvenY, Field.MASK

Contribuire e testare

npm install && npm run build && npm test compilerà il codice ed eseguirà i test.

Ci sono suite aggiuntive: test lenti con scalari grandi / curve grandi npm run test:slow, e l'harness per la constant-timeness npm run benchmark:ct.

Vedi paulmillr.com/noble per risorse utili, articoli, documentazione e demo relative alla libreria.

Licenza

The MIT License (MIT)

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

Vedi il file LICENSE.

Scarica lo strumento
  • Ambito: moduli astratti curve, hash-to-curve, modular, poseidon, utils, weierstrass e moduli di primo livello _shortw_utils e secp256k1
  • L'audit è stato finanziato da Ryan Shea
  • Curve personalizzate:
    • La creazione di curve è stata enormemente semplificata e suddivisa in creazione di punti e creazione di generatori di firme: weierstrass() + ecdsa() / edwards() + eddsa(). weierstrass / edwards si aspettano parametri di curva semplificati (Fp è diventato p); ecdsa / eddsa si aspettano la classe Point e l'hash
    • pippenger: rimosso l'argomento Fn non necessario
    • Field#fromBytes() ora valida che gli elementi siano nell'intervallo 0..order-1