A @noble/curves implementa criptografia de curvas elípticas em TypeScript puro, sem dependências, e passou por várias auditorias. É o motor por trás do ethers v6, do viem e de muitas ferramentas de Bitcoin e Nostr, e a resposta habitual quando falta uma curva no WebCrypto: cobre P-256, P-384, P-521, secp256k1 e as curvas Brainpool r1, Ed25519 e Ed448 com as variantes de pré-hash e de contexto, além de assinaturas Schnorr BIP-340.
Os padrões são os estritos. Uma assinatura tem 64 bytes de r‖s compacto, o nonce segue a RFC 6979 — o vetor de teste P-256 da RFC foi reproduzido — e o s é sempre normalizado para a metade inferior. A verificação é igualmente estrita: todas as assinaturas high-S produzidas pelo node:crypto foram rejeitadas, e todas as low-S, aceitas. Assinaturas do OpenSSL, do Java, do Go ou do WebCrypto são high-S em cerca de metade das vezes, então verificá-las exige lowS: false, e uma entrada DER exige format: "der" — sem isso, um blob DER de 70 bytes lança um erro de comprimento.
A versão 2 mudou o significado do primeiro argumento. Na 1.x, sign() e verify() recebiam um hash calculado por você; na 2.x, elas próprias calculam o hash da mensagem com a função de hash da curva, e o teste confirmou que a 1.9.7 só reproduz o vetor da RFC quando recebe o SHA-256 da mensagem. Por isso, um código atualizado sem mudanças calcula o hash duas vezes e falha contra todas as outras bibliotecas; passe prehash: false quando você realmente tiver um digest. A versão 1 também deixava as assinaturas P-256 sem normalização, então assinaturas que eram verificadas na 1.x podem falhar na 2.x.
As chaves são apenas bytes brutos: um escalar secreto de 32 bytes e chaves públicas como pontos SEC1 — comprimidos (33 bytes) por padrão, não comprimidos sob demanda. SPKI, PKCS#8 e JWK não são lidos, então chaves vindas do OpenSSL ou de um JWKS precisam ser desempacotadas antes; o conversor de JWK e o laboratório de curvas ajudam nisso. Não há código pós-quântico neste pacote; o mesmo autor o publica separadamente.
O exemplo mostra as duas opções que fazem o noble interoperar com um signatário no estilo do OpenSSL — format e lowS — e a saída determinística do seu próprio signatário. Para comparar manualmente uma assinatura em diferentes codificações, use o conversor DER ⇄ bruto; para assinaturas de carteiras, o verificador de assinaturas Ethereum roda sobre o mesmo código de curvas.