Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
Ferramentas/GitHubGitHub/paulmillr/noble-curves
Ferramentas de Criptografia/DescriptografiaAnálise de HashCriptografiaUtilitários e FrameworksAprendizado e Educação
GitHubpaulmillr/noble-curves

noble-curves

Implementação JS auditada e minimalista de criptografia de curva elíptica.

Ver Repositório
9581018há 7 diasRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
Site

noble-curves

Implementação JS auditada e minimalista de criptografia de curva elíptica.

  • 🔒 Auditada por empresas de segurança independentes
  • 🪶 Minimalista: 15KB (gzipped) secp256k1, código não utilizado é excluído das suas builds
  • 🏎 Rápida: otimizada manualmente para as particularidades dos motores JS
  • 🔍 Confiável: testes cross-library / wycheproof garantem a correção
  • ➰ Curvas Weierstrass, Edwards; assinaturas ECDSA, EdDSA, Schnorr, BLS
  • ✍️ ECDH, hash-to-curve, OPRF, FROST, hash Poseidon, FFT
  • 🔖 Não-repúdio (SUF-CMA, SBS) e compatibilidade com consenso (ZIP215) em ed25519, ed448
  • 🥈 Wrapper com API idêntica sobre WebCrypto nativo

As curvas têm projetos irmãos de 5kb secp256k1 & ed25519. Eles têm uma superfície de ataque menor, mas menos funcionalidades.

Esta biblioteca pertence à criptografia noble

noble cryptography — conjunto de bibliotecas e ferramentas criptográficas contidas, de alta segurança e facilmente auditáveis.

  • Dependências zero ou mínimas
  • Código TypeScript / JS altamente legível
  • Lançamentos assinados com PGP e builds NPM transparentes
  • Todas as bibliotecas: ciphers, curves, hashes, post-quantum, 5kb secp256k1 / ed25519
  • Versão WASM: awasm-noble
  • Confira a homepage para recursos de leitura, documentação e aplicações construídas com noble

Uso

npm install @noble/curves

deno add jsr:@noble/curves

Suportamos todas as principais plataformas e runtimes. Para React Native, você pode precisar de um polyfill para getRandomValues. Um arquivo autônomo noble-curves.js também está disponível.```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:~
- [Assinaturas ECDSA, EdDSA, Schnorr](#ecdsa-eddsa-schnorr-signatures)
- [ECDH: segredos compartilhados Diffie-Hellman](#ecdh-diffie-hellman-shared-secrets)
- [webcrypto: wrapper amigável](#webcrypto-friendly-wrapper)
- [Assinaturas BLS, bls12-381, bn254 aka alt\_bn128](#bls-signatures-bls12-381-bn254-aka-alt_bn128)
- [hash-to-curve: hashing para pontos de curva](#hash-to-curve-hashing-to-curve-points)
- [OPRFs](#oprfs) | [Assinaturas de limiar FROST](#frost-threshold-signatures)
- [poseidon: hash Poseidon](#poseidon-poseidon-hash) | [fft: Transformada Rápida de Fourier](#fft-fast-fourier-transform) | [utils](#utils-byte-shuffling-conversion)
- Internos: [Aritmética de pontos](#elliptic-curve-point-math) | [modular](#modular-modular-arithmetics--finite-fields) | [curvas personalizadas](#weierstrass-custom-weierstrass-curve--ecdsa)
- [Especificações](#specs)
- [Segurança](#security) | [Velocidade](#speed) | [Atualização](#upgrading) | [Contribuição e testes](#contributing--testing) | [Licença](#license)

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

As mensagens são sempre primeiro submetidas a hash: consulte assinatura pré-hasheada. O ECDSA usa k determinístico, o EdDSA segue o RFC 8032, o Schnorr (apenas secp256k1) segue o BIP 340: consulte Especificações.

O esquema de assinatura MuSig2 e o mapeamento BIP324 ElligatorSwift para secp256k1 estão disponíveis num pacote separado.

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:~
Confira o [RFC 9496](https://www.rfc-editor.org/rfc/rfc9496) para mais informações sobre ristretto255 e decaf448.
Confira a documentação separada para [Point](#elliptic-curve-point-math), [hasher](#hash-to-curve-hashing-to-curve-points) e [oprf](#oprfs).

#### Assinatura pré-hasheada```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 });

Por padrão (prehash: true), sign() e verify() aplicam primeiro o hash integrado da curva à mensagem: sha256 para secp256k1, sha512 para p521. prehash: false permite usar um hash personalizado (por exemplo, secp256k1 + keccak_256). No noble-curves v1, prehash: false era o padrão.

Recuperando chaves públicas a partir de assinaturas```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:~
A recuperação de chave pública só é suportada com ECDSA. É uma operação matemática simples:
não há garantias de que a assinatura foi realmente feita. Um (r, s, h) forjado é recuperado em
uma chave pública aleatória, mas não é viável encontrar m que levaria a este h forjado específico.

#### ECDSA com hedge e ruído```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 });

Por padrão, as assinaturas ECDSA são determinísticas (RFC 6979). Assinaturas puramente determinísticas são vulneráveis a ataques de falha, então esquemas mais recentes, como o schnorr BIP340, incorporam aleatoriedade na geração de assinaturas - também conhecido como hedging. extraEntropy habilita o modo hedged. Para mais informações, confira Deterministic signatures are not your friends.

Compatibilidade com consenso 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` (padrão) usa as regras de verificação mais permissivas e [compatíveis com consenso](https://hdevalence.ca/blog/2020-10-04-its-25519am) definidas na [ZIP215](https://zips.z.cash/zip-0215).
* `zip215: false` impõe verificação estrita RFC 8032 / FIPS 186-5 e adiciona
  não-repúdio baseado em SBS, o que é útil para assinatura de contratos, voto eletrónico e blockchains.

Ambos os modos têm SUF-CMA (strong unforgeability under chosen message attacks);
a maioria das outras bibliotecas não tem nem SUF-CMA nem SBS.
Consulte [Taming the many EdDSAs](https://eprint.iacr.org/2020/1244) para mais informações.

### ECDH: segredos partilhados 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);

Fornecemos ECDH sobre todas as curvas Weierstrass, e sobre 2 curvas Montgomery X25519 (Curve25519) & X448 (Curve448), em conformidade com a RFC 7748.

Em curvas Weierstrass, os segredos compartilhados:

  • Incluem bytes de paridade y: use key.slice(1) para removê-los
  • Não são hasheados: use hashing ou KDF por cima, como sha256(shared) ou hkdf(shared)

webcrypto: wrapper amigável```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:~
Um wrapper fino sobre o WebCrypto integrado, espelhando a API noble. Os métodos são sempre assíncronos;
o suporte em tempo de execução varia - verifique com `await curve.isSupported()`.
Confira [micro-key-producer](https://github.com/paulmillr/micro-key-producer) para
utilitários de conversão de chaves em JS puro.

### Assinaturas 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

Para exemplo de uso, confira a implementação dos precompilados BLS EVM.

A API BN254 espelha a bls12-381. A curva era anteriormente chamada alt_bn128. A implementação é compatível com EIP-196 e EIP-197: confira a implementação dos precompilados bn254 EVM. Os pontos bn254 não implementam toBytes, porque não há um padrão de serialização: as implementações divergem quanto ao endianness, flags e ordem da parte imaginária de G2. Inicialize pontos a partir de bigints.

hash-to-curve: hashing para pontos de 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:~
O módulo permite fazer hash de strings arbitrárias para pontos de curva elíptica. Implementa a [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380).
Os namespaces `_hasher` são separados das curvas para tree-shaking:
utilizadores que não precisam de hash-to-curve não o terão nas suas 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';

Fornecemos OPRFs (funções pseudorrandômicas oblivious), em conformidade com a RFC 9497.

OPRF permite criar interativamente um Output = PRF(Input, serverSecretKey):

  • O servidor não consegue calcular o Output sozinho: ele não conhece o Input
  • O cliente não consegue calcular o Output sozinho: ele não conhece a serverSecretKey
  • Um atacante que intercepte a comunicação não consegue restaurar Input/Output/serverSecretKey e não consegue associar o Input a algum valor.

Assinaturas de limiar FROST

FROST implementa a assinatura Schnorr de limiar RFC 9591. É semelhante ao multisig do ponto de vista da aplicação: qualquer min de max participantes podem produzir conjuntamente uma assinatura Schnorr sob uma chave pública partilhada. Os ciphersuites suportados são p256_FROST, ed25519_FROST, ed448_FROST, ristretto255_FROST, secp256k1_FROST, e schnorr_FROST (secp256k1 compatível com Taproot). A assinatura tem duas rondas: os signatários selecionados comprometem-se primeiro, depois produzem as partilhas da assinatura.```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:~
A geração de chaves pode ser feita com um trusted dealer (acima) ou com DKG (geração de chaves distribuída).
O DKG tem três rodadas: os participantes se comprometem com a geração de chaves, trocam shares privados,
e então derivam as chaves finais dos participantes - veja o uso de `DKG.round1` / `round2` / `round3` em
[the tests](https://github.com/paulmillr/noble-curves/blob/main/test/rfc9591-frost.test.ts).
A biblioteca implementa os passos criptográficos, não o protocolo de aplicação ao redor:
os chamadores ainda precisam de comunicação autenticada, coordenação, retries, gerenciamento de sessão e política.

### poseidon: Poseidon hash

Implementa o hash ZK-friendly [Poseidon](https://www.poseidon-hash.info):
permutação e sponge.

Existem muitas variantes de poseidon com constantes diferentes.
Nós não as fornecemos: você deve construí-las manualmente.
Confira o pacote [scure-starknet](https://github.com/paulmillr/scure-starknet) para um exemplo adequado.```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: Transformada Rápida de Fourier```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 (Transformada Rápida de Fourier) sobre corpos finitos.

### utils: embaralhamento de bytes, conversão```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));

Internos

Matemática de pontos em curvas elípticas```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:~
Cada curva expõe sua classe Point: secp256k1, schnorr, p256, p384, p521, ed25519, ed448,
ristretto255, decaf448, bls12_381.G1 / G2, bn254.G1, jubjub, babyjubjub.
Pontos Weierstrass usam coordenadas projetivas (homogêneas) `new Point(X, Y, Z)`,
pontos edwards usam coordenadas estendidas `new Point(X, Y, Z, T)`; ambos com x=X/Z, y=Y/Z.

#### modular: Aritmética modular e corpos finitos```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

Toda a aritmética é feita com bigints de JS sobre corpos finitos, que é definido a partir do submódulo modular.

As operações de corpo não são de tempo constante: consulte security. O facto é maioritariamente irrelevante, mas o método importante a ter em mente é pow, que pode revelar bits do expoente, quando usado de forma ingénua.

weierstrass: curva Weierstrass personalizada & 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:~
A fórmula da curva de Weierstrass curta é `y² = x³ + ax + b`. `weierstrass`
espera os argumentos `a`, `b`, característica do corpo `p`, ordem da curva `n`,
cofator `h` e coordenadas `Gx`, `Gy` do ponto gerador, e retorna uma classe Point.
`ecdsa` combina uma classe Point com uma função de hash em um esquema de assinatura.

#### edwards: Curva de Edwards personalizada```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);

A fórmula da curva de Twisted Edwards é ax² + y² = 1 + dx²y². Você deve especificar a, d, a característica do corpo p, a ordem da curva n (às vezes chamada de L), o cofator h e as coordenadas Gx, Gy do ponto gerador.

Especificações

  • ECDSA: k determinístico do RFC 6979, assinaturas hedged do rascunho cfrg-det-sigs-with-noise
  • EdDSA: RFC 8032, FIPS 186-5; verificação amigável ao consenso: ZIP215
  • Assinaturas 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

Segurança

A biblioteca foi auditada:

  • na versão 2.3.0, em Ago 2026, pela Trail of Bits, em colaboração com a OpenAI
    • Foi realizada durante a iniciativa "Patch the Planet"
    • Escopo: tudo
  • na versão 1.6.0, em Set 2024, de forma independente, pela Cure53
    • PDFs: website, no repositório
    • Escopo: ed25519, ed448, seus complementos, bls12-381, bn254, hash-to-curve, primitivas de baixo nível bls, tower, edwards, montgomery.
    • A auditoria foi financiada pela OpenSats
  • na versão 1.2.0, em Set 2023, de forma independente, pela Kudelski Security
    • PDFs: no repositório
    • Escopo: scure-starknet e seus módulos abstratos relacionados do noble-curves: curve, modular, poseidon, weierstrass
    • A auditoria foi financiada pela Starkware
  • na versão 0.7.3, em Fev 2023, de forma independente, pela Trail of Bits
    • PDFs: website, no repositório

Iniciamos autoauditorias regulares assistidas por IA em Abr 2026.

A biblioteca é testada contra vetores baseados em propriedades, entre bibliotecas e Wycheproof, e está sendo submetida a fuzzing no CI do GitHub.

Se você vir algo incomum: investigue e reporte.

Tempo constante

Estamos visando tempo constante algorítmico. O compilador JIT e o Garbage Collector tornam extremamente difícil alcançar resistência a ataques de temporização em uma linguagem de script. O que significa que qualquer outra biblioteca JS não pode ter tempo constante. Mesmo Rust, uma linguagem com tipagem estática e sem GC, torna mais difícil alcançar tempo constante em alguns casos. Se seu objetivo é segurança absoluta, não use nenhuma biblioteca JS — incluindo bindings para bibliotecas nativas. Use bibliotecas e linguagens de baixo nível.

Dentro desses limites, a multiplicação por escalar secreto fornece propriedades específicas e mensuráveis:

  • Sequência de operações fixa: multiply() usa tabelas de janela fixa com sinal e varreduras de tabela que não dependem dos dados — o número e a ordem das operações de ponto são independentes do valor do escalar.
  • Blinding de escalar: escalares secretos são adicionalmente mascarados como s + r·n com um r aleatório de 128 bits antes da multiplicação. Isso se aplica a todas as multiplicações em curvas de cofator 1 (p256, p384, p521, secp256k1), e a multiplicações de ponto base em todos os lugares.
  • Validação estatística: um harness de teste t de Welch no estilo dudect (benchmark/ct.ts) compara o tempo entre classes de escalares adversariais (esparsos vs densos, bits baixos vs altos, próximos da ordem, padrões de bits). A multiplicação de ponto base não mostra tempo distinguível em nenhuma curva, e a multiplicação de ponto aleatório não mostra nenhum nas curvas de Weierstrass (máx |t| ≤ 2,8 com 1000 amostras; limiar 4,5).

Limitação conhecida: em curvas de Edwards com cofator (ed25519, ed448), multiplicar um ponto não-base por um escalar secreto não é protegido por blinding. O mesmo harness detecta isso de forma confiável. A assinatura EdDSA não é afetada (ela só multiplica o ponto base com blinding), e X25519/X448 usam uma implementação separada de escada de Montgomery (também não afetada). Isso importa para protocolos que multiplicam pontos arbitrários de Edwards/Ristretto por escalares secretos de longa duração; prefira escalares que sejam de largura total por construção nesses casos. Note que a detectabilidade em um harness isolado não implica explorabilidade prática: tentamos extração de escalar em um cenário realista entre inquilinos / no navegador e não conseguimos recuperar escalares de Edwards mesmo com 100.000 amostras de temporização.

Dump de memória

Use linguagens de baixo nível em vez de JS / WASM se seu objetivo é segurança absoluta.

A biblioteca usa principalmente Uint8Arrays e bigints.

  • Uint8Arrays têm .fill(0) que instrui a preencher o conteúdo com zeros mas não há garantias em JS
  • bigints são imutáveis e não têm um método para zerar seu conteúdo: o usuário precisa esperar até o próximo ciclo de garbage collection
  • strings hexadecimais também são imutáveis: não há como zerá-las
  • await fn() escreverá todas as variáveis internas na memória. Com funções assíncronas não há garantias de quando o bloco de código seria executado. O que significa que o atacante pode ter bastante tempo para ler dados da memória.

Isso significa que alguns segredos podem permanecer na memória por mais tempo do que o previsto. No entanto, se um atacante pode ler a memória da aplicação, já está tudo perdido: não há como garantir qualquer coisa sobre zerar dados sensíveis sem uma suíte de testes complexa que fará dump da memória do processo e verificará que não há dados sensíveis restantes. Para JS isso significa testar todos os navegadores (incluindo mobile). E, é claro, será inútil sem usar a mesma suíte de testes na aplicação real que consome a biblioteca.

Segurança da cadeia de suprimentos

  • Commits são assinados com chaves PGP para prevenir falsificação. Certifique-se de verificar as assinaturas dos commits
  • Releases são feitas de forma transparente através de CI do GitHub sem token e Trusted Publishing. Certifique-se de verificar os logs de proveniência para autenticidade.
  • Releases raras são praticadas para minimizar a necessidade de reauditorias pelos usuários finais.
  • Dependências são minimizadas e estritamente fixadas para reduzir o risco da cadeia de suprimentos.
    • Usamos o mínimo de dependências possível.
    • Intervalos de versão são travados, e mudanças são verificadas com npm-diff.
  • Dependências de desenvolvimento são excluídas das instalações do usuário final; são usadas apenas para desenvolvimento e etapas de build.

Para este pacote, há 1 dependência; e algumas dependências de desenvolvimento:

  • noble-hashes fornece funcionalidade de hashing criptográfico
  • jsbt é usado para benchmarking / testes / ferramentas de build e é desenvolvido pelo mesmo autor
  • prettier, fast-check e typescript são usados para qualidade de código / geração de testes / compilação ts

Aleatoriedade

Contamos com o crypto.getRandomValues integrado, que é considerado um PRNG criptograficamente seguro.

Navegadores tiveram fraquezas no passado — e podem ter novamente — mas implementar um CSPRNG em espaço de usuário é ainda pior, pois não há fonte confiável de entropia de alta qualidade em espaço de usuário.

Computadores quânticos

Um computador quântico criptograficamente relevante, se construído, permitirá quebrar a criptografia de curva elíptica (tanto ECDSA / EdDSA quanto ECDH) usando o algoritmo de Shor.

Considere mudar para algoritmos mais novos / híbridos, como SPHINCS+. Eles estão disponíveis em noble-post-quantum.

O NIST proíbe criptografia clássica (RSA, DSA, ECDSA, ECDH) após 2035. O ASD australiano proíbe após 2030.

Velocidade```sh

npm run benchmark

root@kitploit:~
noble-curves gasta mais de 10 ms para gerar mais de 20 MB de pré-cálculos de pontos base.
Isto é feito **uma única vez** por curva.

A geração é adiada até que qualquer método (pubkey, sign, verify) seja chamado.
O utilizador pode forçar a geração de pré-cálculos chamando manualmente `Point.BASE.precompute(windowSize, false)`.
Consulte o código-fonte.

Resultados de benchmark em 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

Atualização

Versões do node.js suportadas:

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

v1 para v2

A v2 simplifica massivamente os internos, melhora a segurança, reduz o tamanho do bundle e prepara o caminho para o futuro. Tentámos manter a v2 o mais retrocompatível possível.

Caminho de atualização: atualize primeiro para curves v1.9.x. Corrija os avisos de depreciação e depois mude para a v2.

Módulos:

  • O pacote é agora apenas ESM. O ESM pode finalmente ser carregado a partir de common.js no node v20.19+
  • A extensão .js é agora obrigatória: @noble/curves/ed25519 => @noble/curves/ed25519.js. Isto permite a utilização nativa no navegador, sem transpiladores
  • p256, p384, p521 foram movidos para nist; jubjub foi movido para misc
  • As curvas pasta e bn254_weierstrass (NÃO bn254 baseada em emparelhamento) foram removidas

Novas funcionalidades:

  • webcrypto: wrapper amigável ao estilo noble sobre o WebCrypto incorporado
  • oprf: OPRFs RFC 9497 (funções pseudorrandómicas oblivious) para p256, p384, p521, ristretto255 e decaf448
  • weierstrass, edwards: novos métodos isValidSecretKey, isValidPublicKey
  • misc: curvas Brainpool brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
  • Mensagens de erro massivamente melhoradas e mais descritivas

Alterações disruptivas:

  • A maioria dos métodos agora só aceita Uint8Array; entradas em string hex são proibidas. Isto simplifica o raciocínio, melhora a segurança e reduz a maleabilidade. Point.fromHex é agora apenas para strings: use Point.fromBytes para Uint8Array
  • Assinatura e verificação ECDSA (secp256k1, p256, p384...):
    • Mensagens pré-hasheadas: os métodos agora esperam a mensagem não hasheada em vez de messageHash. Comportamento antigo: {prehash: false}
    • Assinaturas lowS por defeito. secp256k1 não é afetada: tem usado lowS desde o início. Comportamento antigo: {lowS: false}
    • Assinaturas Uint8Array (formato: 'compact') por defeito
    • verify: o formato der tem de ser explicitamente especificado em {format: 'der'}. Isto reduz a maleabilidade
    • verify: instâncias de Signature são proibidas: chame signature.toBytes() primeiro
  • Assinaturas BLS (bls12-381, bn254):
    • getPublicKey, sign, verify, signShortSignature etc foram movidos para dois novos namespaces: longSignatures (pubkeys G1, sigs G2) e shortSignatures (sigs G1, pubkeys G2)
    • verifyBatch agora espera um array de entradas {message: ..., publicKey: ...}[]

Renomeações (curves v1.9 destaca os nomes antigos como depreciados):

  • Pontos
    • ExtendedPoint, ProjectivePoint => Point
    • Coordenadas de Point px/ex, py/ey, pz/ez, et => X, Y, Z, T
    • toRawBytes, fromRawBytes => toBytes, fromBytes
    • Point.normalizeZ, Point.msm => métodos separados no submódulo abstract/curve.js
    • Point.fromPrivateKey(key) => Point.BASE.multiply(Point.Fn.fromBytes(key))
    • Propriedade CURVE com todo o tipo de coisas aleatórias => Point.CURVE(), que apenas fornece parâmetros de curva
    • RistrettoPoint => ristretto255.Point, DecafPoint => decaf448.Point
  • Assinaturas 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étodos hash-to-curve específicos de cada curva => *curve*_hasher. Exemplo: secp256k1.hashToCurve => secp256k1_hasher.hashToCurve()
  • Renomeações e melhorias massivas de tipos

Funcionalidades removidas: Point#multiplyAndAddUnsafe, Point#hasEvenY, Field.MASK

Contribuir e testar

npm install && npm run build && npm test irá compilar o código e executar os testes.

Existem suites adicionais: testes lentos de escalares grandes / curvas grandes npm run test:slow, e o harness de constância temporal npm run benchmark:ct.

Consulte paulmillr.com/noble para recursos úteis, artigos, documentação e demos relacionados com a biblioteca.

Licença

The MIT License (MIT)

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

Consulte o ficheiro LICENSE.

Baixar ferramenta
  • Escopo: módulos abstratos curve, hash-to-curve, modular, poseidon, utils, weierstrass e módulos de nível superior _shortw_utils e secp256k1
  • A auditoria foi financiada por Ryan Shea
  • Curvas personalizadas:
    • A criação de curvas foi massivamente simplificada e dividida em criação de pontos e criação de geradores de assinaturas: weierstrass() + ecdsa() / edwards() + eddsa(). weierstrass / edwards esperam parâmetros de curva simplificados (Fp tornou-se p); ecdsa / eddsa esperam a classe Point e a função de hash
    • pippenger: removido o argumento Fn desnecessário
    • Field#fromBytes() agora valida que os elementos estão no intervalo 0..order-1