@@ -70,7 +70,7 @@ def test_hmac_should_reject_nonstring_key(self):
70
70
def test_hmac_should_accept_unicode_key (self ):
71
71
algo = HMACAlgorithm (HMACAlgorithm .SHA256 )
72
72
73
- algo .prepare_key ("awesome" )
73
+ algo .prepare_key ("awesome" * 5 ) # 35 characters > 32 bytes minimum
74
74
75
75
@pytest .mark .parametrize (
76
76
"key" ,
@@ -101,12 +101,12 @@ def test_hmac_jwk_should_parse_and_verify(self):
101
101
@pytest .mark .parametrize ("as_dict" , (False , True ))
102
102
def test_hmac_to_jwk_returns_correct_values (self , as_dict ):
103
103
algo = HMACAlgorithm (HMACAlgorithm .SHA256 )
104
- key : Any = algo .to_jwk ("secret " , as_dict = as_dict )
104
+ key : Any = algo .to_jwk ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa " , as_dict = as_dict )
105
105
106
106
if not as_dict :
107
107
key = json .loads (key )
108
108
109
- assert key == {"kty" : "oct" , "k" : "c2VjcmV0 " }
109
+ assert key == {"kty" : "oct" , "k" : "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWE " }
110
110
111
111
def test_hmac_from_jwk_should_raise_exception_if_not_hmac_key (self ):
112
112
algo = HMACAlgorithm (HMACAlgorithm .SHA256 )
@@ -122,6 +122,57 @@ def test_hmac_from_jwk_should_raise_exception_if_empty_json(self):
122
122
with pytest .raises (InvalidKeyError ):
123
123
algo .from_jwk (keyfile .read ())
124
124
125
+ # CVE-2025-45768: Test minimum key length enforcement
126
+ @pytest .mark .parametrize (
127
+ "hash_alg,min_length,weak_key" ,
128
+ [
129
+ (HMACAlgorithm .SHA256 , 32 , b"short" ), # 5 bytes, too short for HS256
130
+ (HMACAlgorithm .SHA256 , 32 , b"a" * 31 ), # 31 bytes, just under minimum
131
+ (HMACAlgorithm .SHA384 , 48 , b"b" * 47 ), # 47 bytes, just under minimum
132
+ (HMACAlgorithm .SHA512 , 64 , b"c" * 63 ), # 63 bytes, just under minimum
133
+ ],
134
+ )
135
+ def test_hmac_should_reject_weak_keys (self , hash_alg , min_length , weak_key ):
136
+ """Test that HMAC keys below minimum length are rejected (CVE-2025-45768)"""
137
+ algo = HMACAlgorithm (hash_alg )
138
+
139
+ with pytest .raises (InvalidKeyError ) as excinfo :
140
+ algo .prepare_key (weak_key )
141
+
142
+ error_msg = str (excinfo .value )
143
+ assert f"at least { min_length * 8 } bits" in error_msg
144
+ assert f"Key provided is { len (weak_key ) * 8 } bits" in error_msg
145
+
146
+ @pytest .mark .parametrize (
147
+ "hash_alg,adequate_key" ,
148
+ [
149
+ (HMACAlgorithm .SHA256 , b"a" * 32 ), # 32 bytes for HS256
150
+ (HMACAlgorithm .SHA384 , b"b" * 48 ), # 48 bytes for HS384
151
+ (HMACAlgorithm .SHA512 , b"c" * 64 ), # 64 bytes for HS512
152
+ ],
153
+ )
154
+ def test_hmac_should_accept_adequate_keys (self , hash_alg , adequate_key ):
155
+ """Test that HMAC keys at or above minimum length are accepted"""
156
+ algo = HMACAlgorithm (hash_alg )
157
+
158
+ # Should not raise an exception
159
+ prepared_key = algo .prepare_key (adequate_key )
160
+ assert prepared_key == adequate_key
161
+
162
+ def test_hmac_from_jwk_should_reject_weak_keys (self ):
163
+ """Test that weak HMAC keys are rejected when loaded from JWK (CVE-2025-45768)"""
164
+ algo = HMACAlgorithm (HMACAlgorithm .SHA256 )
165
+
166
+ # Create a JWK with a weak key (5 bytes)
167
+ weak_jwk = {"kty" : "oct" , "k" : "c2hvcnQ" } # base64url("short") - only 5 bytes
168
+
169
+ with pytest .raises (InvalidKeyError ) as excinfo :
170
+ algo .from_jwk (weak_jwk )
171
+
172
+ error_msg = str (excinfo .value )
173
+ assert "at least 256 bits" in error_msg
174
+ assert "40 bits" in error_msg # 5 bytes * 8 = 40 bits
175
+
125
176
@crypto_required
126
177
def test_rsa_should_parse_pem_public_key (self ):
127
178
algo = RSAAlgorithm (RSAAlgorithm .SHA256 )
@@ -173,6 +224,75 @@ def test_rsa_verify_should_return_false_if_signature_invalid(self):
173
224
result = algo .verify (message , pub_key , sig )
174
225
assert not result
175
226
227
+ # CVE-2025-45768: Test RSA minimum key size enforcement
228
+ @crypto_required
229
+ def test_rsa_should_reject_weak_keys (self ):
230
+ """Test that RSA keys below 2048 bits are rejected (CVE-2025-45768)"""
231
+ from cryptography .hazmat .primitives .asymmetric import rsa
232
+
233
+ algo = RSAAlgorithm (RSAAlgorithm .SHA256 )
234
+
235
+ # Generate a weak 1024-bit RSA key
236
+ weak_private_key = rsa .generate_private_key (
237
+ public_exponent = 65537 , key_size = 1024
238
+ )
239
+ weak_public_key = weak_private_key .public_key ()
240
+
241
+ # Test with private key
242
+ with pytest .raises (InvalidKeyError ) as excinfo :
243
+ algo .prepare_key (weak_private_key )
244
+
245
+ error_msg = str (excinfo .value )
246
+ assert "at least 2048 bits" in error_msg
247
+ assert "1024 bits" in error_msg
248
+
249
+ # Test with public key
250
+ with pytest .raises (InvalidKeyError ) as excinfo :
251
+ algo .prepare_key (weak_public_key )
252
+
253
+ error_msg = str (excinfo .value )
254
+ assert "at least 2048 bits" in error_msg
255
+ assert "1024 bits" in error_msg
256
+
257
+ @crypto_required
258
+ def test_rsa_should_accept_adequate_keys (self ):
259
+ """Test that RSA keys at or above 2048 bits are accepted"""
260
+ from cryptography .hazmat .primitives .asymmetric import rsa
261
+
262
+ algo = RSAAlgorithm (RSAAlgorithm .SHA256 )
263
+
264
+ # Generate a strong 2048-bit RSA key
265
+ strong_private_key = rsa .generate_private_key (
266
+ public_exponent = 65537 , key_size = 2048
267
+ )
268
+ strong_public_key = strong_private_key .public_key ()
269
+
270
+ # Should not raise exceptions
271
+ prepared_private = algo .prepare_key (strong_private_key )
272
+ prepared_public = algo .prepare_key (strong_public_key )
273
+
274
+ assert prepared_private == strong_private_key
275
+ assert prepared_public == strong_public_key
276
+
277
+ @crypto_required
278
+ def test_rsa_from_jwk_should_reject_weak_keys (self ):
279
+ """Test that weak RSA keys are rejected when loaded from JWK (CVE-2025-45768)"""
280
+ from cryptography .hazmat .primitives .asymmetric import rsa
281
+
282
+ # Generate a weak 1024-bit RSA key and convert to JWK
283
+ weak_key = rsa .generate_private_key (public_exponent = 65537 , key_size = 1024 )
284
+
285
+ # Convert to JWK format (this will work since to_jwk doesn't validate)
286
+ weak_jwk = RSAAlgorithm .to_jwk (weak_key , as_dict = True )
287
+
288
+ # Now try to load it back - should fail
289
+ with pytest .raises (InvalidKeyError ) as excinfo :
290
+ RSAAlgorithm .from_jwk (weak_jwk )
291
+
292
+ error_msg = str (excinfo .value )
293
+ assert "at least 2048 bits" in error_msg
294
+ assert "1024 bits" in error_msg
295
+
176
296
@crypto_required
177
297
def test_ec_jwk_public_and_private_keys_should_parse_and_verify (self ):
178
298
tests = {
0 commit comments