GnuTLS 为许多 GNU 和 Linux 组件提供 TLS、X.509 和 PKCS 处理,并附带 certtool 和 gnutls-cli。它的抽象接口 gnutls_privkey_* 和 gnutls_pubkey_* 对软件密钥、PKCS#11 令牌和 TPM 的用法完全相同。本页的事实基于 Alpine 3.24.2 的软件包检查得出,即 GnuTLS 3.8.13,它用 Nettle 完成底层运算。从 GnuTLS 3.8.10 起,后量子算法只能由可选的 leancrypto 库提供,而这个软件包没有链接它。
gnutls_privkey_sign_data 使用随机 nonce,以 DER 形式返回 ECDSA 签名;标志 GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE 会切换到 RFC 6979,启用后精确复现了 RFC 中的 P-256 测试向量。s 没有经过规范化,high-S 签名也能验证通过。gnutls_privkey_sign_hash2 对你自行计算的摘要签名。
验证失败时返回负的错误码,而且各种失败看起来都一样:原始 r‖s 签名、3 字节的数据块,以及针对其他数据的有效签名,都返回 GNUTLS_E_PK_SIG_VERIFY_FAILED(-89)。可以用 DER ⇄ 原始格式转换器排除编码问题。
ECDSA 仅限于 P-224 到 P-521 的 NIST 曲线——gnutls_ecc_curve_get_id("SECP256K1") 返回 0,即未知——而 Ed25519 和 Ed448 的签名与验证均成功。头文件声明了 GNUTLS_PK_MLKEM768 和 GNUTLS_PK_MLDSA65,但这个构建两者都没有实现:它们不在 gnutls_pk_list() 中,生成 ML-DSA-65 密钥会报错 GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM,而 gnutls-cli --list 列出的 TLS 组包含 X25519 和 X448,却没有 ML-KEM 混合组。针对这些常量能编译通过的代码,在运行时仍可能失败,因此要检查运行时列表。可以用证书解码器查看 certtool 生成的证书。