EVP_DigestSign succeeds with SLH-DSA raw private keys that fail key_check/pairwise_check
#31.055 aperta il 1 mag 2026
Metriche repository
- Star
- (30.157 star)
- Metriche merge PR
- (Nessuna PR mergiata in 30 g)
Descrizione
Summary
For SLH-DSA raw private keys imported with EVP_PKEY_new_raw_private_key_ex(), OpenSSL accepts exact-length component-mutated private keys.
For these mutated keys, EVP_PKEY_check() and EVP_PKEY_pairwise_check() reject the key, but EVP_DigestSign() still succeeds and produces a signature that does not verify under the public key exported from the same EVP_PKEY object.
This report is not claiming that EVP_PKEY_check() or EVP_PKEY_pairwise_check() are broken. The behavior I would like to clarify is whether signing should proceed after these consistency checks would reject the key.
Minimal reproducer
A minimal standalone reproducer is attached:
openssl_slh_dsa_raw_private_key_consistency_repro.cpp
The reproducer:
- Generates an
SLH-DSA-SHA2-128skey. - Exports the raw private key with
EVP_PKEY_get_raw_private_key(). - Mutates one byte in selected raw private-key components while preserving the exact raw private-key length.
- Re-imports the mutated raw private key with
EVP_PKEY_new_raw_private_key_ex(). - Runs
EVP_PKEY_public_check(),EVP_PKEY_private_check(),EVP_PKEY_check(), andEVP_PKEY_pairwise_check(). - Calls
EVP_DigestSign(). - Verifies the resulting signature using the public key exported from the same imported
EVP_PKEYobject.
Observed behavior
OpenSSL version: OpenSSL 3.5.6 7 Apr 2026
algorithm,mutation,raw_private_len,import,public_check,private_check,key_check,pairwise_check,sign,self_verify,exported_public_verify,public_export,public_import,sig_len
SLH-DSA-SHA2-128s,valid,64,accept,1,1,1,1,success,1,1,yes,yes,7856
SLH-DSA-SHA2-128s,mutate_SK_seed,64,accept,1,1,0,0,success,0,0,yes,yes,7856
SLH-DSA-SHA2-128s,mutate_PK_seed,64,accept,1,1,0,0,success,0,0,yes,yes,7856
SLH-DSA-SHA2-128s,mutate_PK_root,64,accept,1,1,0,0,success,0,0,yes,yes,7856
[RESULT] signing succeeded with mutated raw private keys that failed key_check/pairwise_check; the signatures did not verify
exit_code=1
The valid control behaves as expected.
For the mutated SK.seed, PK.seed, and PK.root cases:
- raw private-key import succeeds;
EVP_PKEY_public_check()andEVP_PKEY_private_check()return1;EVP_PKEY_check()andEVP_PKEY_pairwise_check()return0;EVP_DigestSign()succeeds;- the produced signature fails verification with the same imported key object;
- the produced signature also fails verification with the public key exported from that same key object.
Expected behavior / clarification request
Since EVP_PKEY_check() and EVP_PKEY_pairwise_check() reject these imported SLH-DSA keys, I would expect either:
EVP_DigestSign()to reject such keys before producing a signature; or- the documentation to clarify that callers must explicitly run
EVP_PKEY_check()orEVP_PKEY_pairwise_check()after raw private key import, because signing may otherwise succeed with an inconsistent key and produce an unverifiable signature.
Could you clarify whether the current behavior is intentional?
Environment
OpenSSL 3.5.6 7 Apr 2026
Algorithm: SLH-DSA-SHA2-128s
Compiler: g++ 11.4.0 with -std=c++17
Platform: linux-x86_64
Attachments
openssl_slh_dsa_raw_private_key_consistency_repro.cpprun_output_openssl_3_5_6.txtenv_openssl_3_5_6_sanitized.txt
env_openssl_3_5_6_sanitized.txt openssl_slh_dsa_raw_private_key_consistency_repro.cpp run_output_openssl_3_5_6.txt