@noble/curves 用纯 TypeScript 实现椭圆曲线密码学,没有任何依赖,并经过多次审计。它是 ethers v6、viem 以及许多比特币和 Nostr 工具底层的引擎,也是 WebCrypto 缺少某条曲线时的常见选择:它覆盖 P-256、P-384、P-521、secp256k1 和 Brainpool r1 曲线,带预哈希和上下文变体的 Ed25519 和 Ed448,以及 BIP-340 Schnorr 签名。
它的默认设置都是严格的。签名是 64 字节的紧凑 r‖s,nonce 遵循 RFC 6979——本次检查复现了该 RFC 的 P-256 测试向量——s 总是被规范化到低半区。验证同样严格:node:crypto 生成的每个 high-S 签名都被拒绝,每个 low-S 签名都被接受。来自 OpenSSL、Java、Go 或 WebCrypto 的签名大约一半是 high-S,因此验证它们需要 lowS: false,DER 输入则需要 format: "der"——不加这个选项时,70 字节的 DER 数据块会抛出长度错误。
第 2 版改变了第一个参数的含义。在 1.x 中,sign() 和 verify() 接收你计算好的哈希;在 2.x 中,它们用曲线对应的哈希函数自行对消息计算哈希,本次检查也确认,1.9.7 只有在传入消息的 SHA-256 时才能复现该 RFC 的向量。因此,升级后未加修改的代码会计算两次哈希,与其他任何库都无法互通;如果你手里确实是摘要,应传入 prehash: false。第 1 版还不会对 P-256 签名做规范化,因此在 1.x 中验证通过的签名,在 2.x 中可能验证失败。
密钥只能是原始字节:32 字节的秘密标量,以及以 SEC1 点表示的公钥——默认为压缩形式(33 字节),也可按需使用未压缩形式。它不读取 SPKI、PKCS#8 和 JWK,因此来自 OpenSSL 或 JWKS 的密钥需要先解包;JWK 转换器和椭圆曲线可视化演示可以帮上忙。这个包中没有后量子代码,后量子代码由同一作者另行发布。
示例展示了让 noble 与 OpenSSL 风格的签名方互通的两个选项——format 和 lowS——以及 noble 自身签名时的确定性输出。要手动比较同一签名的不同编码,可以使用 DER ⇄ 原始格式转换器;对于钱包签名,以太坊签名验证工具运行的就是同一套曲线代码。