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 は NIST 曲線の P-224〜P-521 に限られます(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 で作成した証明書は証明書デコーダーで解析できます。