coincurve 用 CFFI 封装 libsecp256k1,并提供预编译的 wheel,因此 Python 代码无需编译器就能用上 Bitcoin Core 所用的同一套常量时间 secp256k1 实现。21.0.0 版只发布了 CPython 3.10 到 3.13 的 wheel;在 Python 3.14 上,pip 会退回到从源代码构建,而在没有 C 工具链的 slim 镜像中构建会失败——这就是本次检查在 Python 3.12 上运行的原因。
默认设置适合比特币,而不适合以太坊。sign() 用 SHA-256 对消息计算哈希,使用 RFC 6979 nonce(本次检查与一个独立的参考签名实现结果一致),并返回 s 已处于低半区的 DER 签名。以太坊、Nostr 和大多数钱包使用 keccak-256 计算哈希,或者直接对 32 字节的摘要签名,因此要传入 hasher 或 hasher=None;保留默认值会对错误的哈希生成看似有效的签名。
验证继承了 libsecp256k1 的严格性。对于由有效签名镜像得到的 high-S 形式,verify() 返回 False——来自 OpenSSL、Java 或云 KMS 的签名,如果不先对 s 做规范化,大约有一半会验证失败。非 DER 输入会抛出 ValueError: The DER-encoded signature could not be parsed.,而不是返回 False;原始的 64 字节签名需要先重新编码为 DER 再交给 verify(),DER ⇄ 原始格式转换器可以同时显示这两种形式。
除了普通 ECDSA,sign_recoverable() 返回 65 字节的 r ‖ s ‖ 恢复 ID 形式,PublicKey.from_signature_and_message() 可以恢复出公钥——以太坊正是这样从签名推导出地址的;sign_schnorr() 为 Taproot 和 Nostr 生成 BIP-340 签名。公钥是 SEC1 点,默认为压缩形式;私钥是 32 字节的原始标量,to_pem()/to_der() 写出 PKCS#8。
示例展示了两种模式:默认的 SHA-256,以及按以太坊的要求对 keccak 摘要做可恢复签名。可以用比特币消息验证工具或以太坊签名验证工具核对结果。