@@ -328,6 +328,91 @@ def test_from_bytes_invalid():
328328 PublicKey .from_bytes (data )
329329
330330
331+ # ------------------------------------------------------------------------------
332+ # Test: DER helper encoders and compressed DER export
333+ # ------------------------------------------------------------------------------
334+ def test_encode_der_length_short_and_long_forms ():
335+ assert PublicKey ._encode_der_length (0 ) == b"\x00 "
336+ assert PublicKey ._encode_der_length (0x7F ) == b"\x7f "
337+ assert PublicKey ._encode_der_length (0x80 ) == b"\x81 \x80 "
338+ assert PublicKey ._encode_der_length (0x0100 ) == b"\x82 \x01 \x00 "
339+ assert PublicKey ._encode_der_length (0x1000000 ) == b"\x84 \x01 \x00 \x00 \x00 "
340+
341+
342+ def test_encode_der_length_negative_raises ():
343+ with pytest .raises (ValueError , match = "non-negative" ):
344+ PublicKey ._encode_der_length (- 1 )
345+
346+
347+ def test_encode_der_oid_known_values ():
348+ # id-ecPublicKey
349+ assert PublicKey ._encode_der_oid ("1.2.840.10045.2.1" ) == bytes .fromhex ("06072a8648ce3d0201" )
350+ # secp256k1
351+ assert PublicKey ._encode_der_oid ("1.3.132.0.10" ) == bytes .fromhex ("06052b8104000a" )
352+
353+
354+ def test_encode_der_oid_combined_root_multibyte ():
355+ # "2.999" -> 2*40 + 999 = 1079, encoded as VLQ: 0x88 0x37
356+ result = PublicKey ._encode_der_oid ("2.999.1" )
357+ assert result == bytes .fromhex ("0603883701" )
358+ assert result [0 ] == 0x06 # OID tag
359+ assert result [1 ] == 0x03 # Length of OID content
360+
361+
362+ def test_encode_der_oid_invalid_components_raise ():
363+ for oid in ("1" , "3.1.1" , "1.40.1" , "9.999.1" ):
364+ with pytest .raises (ValueError , match = f"Invalid OID structure for '{ oid } '" ):
365+ PublicKey ._encode_der_oid (oid )
366+
367+ with pytest .raises (ValueError , match = "non-negative" ):
368+ PublicKey ._encode_der_oid ("1.2.-1" )
369+
370+ with pytest .raises (ValueError , match = "invalid literal for int()" ):
371+ PublicKey ._encode_der_oid ("1.999bit" )
372+ with pytest .raises (ValueError ):
373+ PublicKey ._encode_der_oid ("" )
374+ with pytest .raises (ValueError ):
375+ PublicKey ._encode_der_oid ("..." )
376+
377+
378+ def test_encode_der_sequence_and_bit_string ():
379+ assert PublicKey ._encode_der_sequence (b"\x01 \x02 " ) == b"\x30 \x02 \x01 \x02 "
380+ assert PublicKey ._encode_der_bit_string (b"\xaa \xbb " ) == b"\x03 \x03 \x00 \xaa \xbb "
381+
382+
383+ def test_to_bytes_der_ecdsa_compressed_structure_and_roundtrip (ecdsa_keypair ):
384+ _ , pub = ecdsa_keypair
385+ public_key = PublicKey (pub )
386+
387+ der = public_key .to_bytes_der_ecdsa_compressed ()
388+ compressed_point = public_key .to_bytes_ecdsa (compressed = True )
389+
390+ # Fixed SPKI prefix for secp256k1 compressed-point encoding.
391+ expected_prefix = bytes .fromhex ("3036301006072a8648ce3d020106052b8104000a032200" )
392+ assert der .startswith (expected_prefix )
393+ assert der [len (expected_prefix ) :] == compressed_point
394+
395+ # Ensure produced DER is parseable and preserves the same public key bytes.
396+ loaded = PublicKey .from_der (der )
397+ assert loaded .is_ecdsa ()
398+ assert loaded .to_bytes_ecdsa (compressed = True ) == compressed_point
399+
400+
401+ def test_to_bytes_der_ecdsa_compressed_rejects_ed25519 (ed25519_keypair ):
402+ _ , pub = ed25519_keypair
403+ public_key = PublicKey (pub )
404+
405+ with pytest .raises (ValueError , match = "only supported for ECDSA" ):
406+ public_key .to_bytes_der_ecdsa_compressed ()
407+
408+
409+ def test_encode_vlq_values ():
410+ assert PublicKey ._encode_vlq (0 ) == b"\x00 "
411+ assert PublicKey ._encode_vlq (127 ) == b"\x7f "
412+ assert PublicKey ._encode_vlq (128 ) == b"\x81 \x00 "
413+ assert PublicKey ._encode_vlq (0x4000 ) == b"\x81 \x80 \x00 "
414+
415+
331416# ------------------------------------------------------------------------------
332417# Test: from_string_xxx
333418# ------------------------------------------------------------------------------
0 commit comments