33Tests for ML-KEM-1024 (Kyber) and ML-DSA-87 (Dilithium5).
44Covers:
55- Key generation conformance to NIST spec
6+ - Dilithium Signature generation and verification
67- OTP encryption using Kyber key exchange
78- Hash chain tamper detection
89"""
910
1011import pytest
12+ import secrets
1113from core .crypto import (
1214 generate_kem_keys ,
1315 generate_sign_keys ,
16+ create_signature ,
17+ verify_signature ,
1418 generate_kyber_shared_secrets ,
1519 decrypt_kyber_shared_secrets ,
1620 otp_encrypt_with_padding ,
17- otp_decrypt_with_padding
21+ otp_decrypt_with_padding ,
22+ random_number_range
1823)
1924from core .constants import (
2025 OTP_PADDING_LIMIT ,
21- OTP_PADDING_LENGTH
26+ OTP_PADDING_LENGTH ,
27+ ML_KEM_1024_SK_LEN ,
28+ ML_KEM_1024_PK_LEN ,
29+ ML_DSA_87_NAME ,
30+ ML_DSA_87_SK_LEN ,
31+ ML_DSA_87_PK_LEN ,
32+ ML_DSA_87_SIGN_LEN
2233)
2334from core .trad_crypto import sha3_512
2435
25- # NIST-specified key sizes (bytes)
26- ML_KEM_1024_SK_LEN = 3168
27- ML_KEM_1024_PK_LEN = 1568
28- ML_DSA_87_SK_LEN = 4864
29- ML_DSA_87_PK_LEN = 2592
30- HASH_SIZE = 64 # SHA3-512 output size in bytes
36+ HASH_SIZE = 64 # SHA3-512 output size in bytes
37+
38+
39+ def test_random_number_range ():
40+ min_val , max_val = 100 , 10000
41+
42+ # Check multiple values fall in range
43+ for _ in range (10000 ):
44+ num = random_number_range (min_val , max_val )
45+ assert min_val <= num <= max_val , f"{ num } out of range { min_val } -{ max_val } "
3146
3247
3348def test_mlkem_keygen_basic ():
@@ -56,12 +71,12 @@ def test_mldsa_keygen_basic():
5671 seen_public_keys = set ()
5772
5873 for _ in range (50 ):
59- private_key , public_key = generate_sign_keys (algorithm = "Dilithium5" )
74+ private_key , public_key = generate_sign_keys (algorithm = ML_DSA_87_NAME )
6075
6176 assert private_key not in seen_private_keys , "Duplicate private key detected"
6277 assert public_key not in seen_public_keys , "Duplicate public key detected"
6378
64- assert private_key != public_key , "Private and public keys must differ "
79+ assert private_key != public_key , "Private and public keys are identical "
6580 assert isinstance (private_key , bytes ) and isinstance (public_key , bytes ), "Keys must be bytes"
6681 assert len (private_key ) == ML_DSA_87_SK_LEN , "Private key length mismatch with spec"
6782 assert len (public_key ) == ML_DSA_87_PK_LEN , "Public key length mismatch with spec"
@@ -70,6 +85,35 @@ def test_mldsa_keygen_basic():
7085 seen_public_keys .add (public_key )
7186
7287
88+ def test_signature_verifcation ():
89+ """Validate ML-DSA-87 signature creation and verification"""
90+ private_key , public_key = generate_sign_keys (algorithm = "Dilithium5" )
91+
92+ assert private_key != public_key , "Private and public keys are identical"
93+
94+ message = "Hello, World!" .encode ("utf-8" )
95+ signature = create_signature (ML_DSA_87_NAME , message , private_key )
96+
97+ assert isinstance (signature , bytes ), "Signature must be bytes"
98+ assert len (signature ) == ML_DSA_87_SIGN_LEN , "Signature length mismatch with spec"
99+
100+ verify = verify_signature (ML_DSA_87_NAME , message , signature , public_key )
101+
102+ assert isinstance (verify , bool ), "Verification result must be bool"
103+ assert verify == True , "Verification failed"
104+
105+ message = "Hi, World!" .encode ()
106+ verify = verify_signature (ML_DSA_87_NAME , message , signature , public_key )
107+
108+ assert isinstance (verify , bool ), "Verification result must be bool"
109+ assert verify == False , "Verification shouldn't have succeeded"
110+
111+
112+
113+
114+
115+
116+
73117def test_kem_otp_encryption ():
74118 """Full Kyber OTP exchange and tamper detection test."""
75119 # Alice creates ephemeral ML-KEM-1024 keypair for PFS
0 commit comments