@@ -434,41 +434,43 @@ def to_bytes_der(self) -> bytes:
434434 format = serialization .PublicFormat .SubjectPublicKeyInfo
435435 )
436436
437- @staticmethod
438- def _encode_der_length (length : int ) -> bytes :
439- """Encode a DER length field."""
440- if length < 0 :
441- raise ValueError ("DER length must be non-negative" )
442- if length < 0x80 :
443- return bytes ([length ])
444-
445- length_bytes = length .to_bytes ((length .bit_length () + 7 ) // 8 , "big" )
446- return bytes ([0x80 | len (length_bytes )]) + length_bytes
447-
448- @staticmethod
449- def _encode_der_oid_component (value : int ) -> bytes :
450- """Encode one OID component in base-128 continuation format."""
437+ @classmethod
438+ def _encode_vlq (cls , value : int ) -> bytes :
439+ """
440+ Encode a value in Variable-Length Quantity (VLQ) format.
441+ """
451442 if value < 0 :
452- raise ValueError ("OID components must be non-negative" )
443+ raise ValueError ("VLQ value must be non-negative" )
453444 if value == 0 :
454445 return b"\x00 "
455446
456- base128 = []
447+ encoded = bytearray ()
457448 while value > 0 :
458- base128 . append ( value & 0x7F )
449+ encoded . insert ( 0 , value & 0x7F )
459450 value >>= 7
460451
461- encoded = bytearray ()
462- for i in range (len (base128 ) - 1 , - 1 , - 1 ):
463- byte = base128 [i ]
464- if i != 0 :
465- byte |= 0x80
466- encoded .append (byte )
452+ # Set the high bit (0x80) on all bytes except the last
453+ for i in range (len (encoded ) - 1 ):
454+ encoded [i ] |= 0x80
455+
467456 return bytes (encoded )
468457
469- @staticmethod
470- def _encode_der_oid (oid : str ) -> bytes :
471- """Encode a dotted OID string into DER OID bytes including tag and length."""
458+ @classmethod
459+ def _encode_der_length (cls , length : int ) -> bytes :
460+ """Encode a DER length field per X.690 standards."""
461+ if length < 0 :
462+ raise ValueError ("DER length must be non-negative" )
463+ if length < 0x80 :
464+ return bytes ([length ])
465+
466+ length_bytes = length .to_bytes ((length .bit_length () + 7 ) // 8 , "big" )
467+ return bytes ([0x80 | len (length_bytes )]) + length_bytes
468+
469+ @classmethod
470+ def _encode_der_oid (cls , oid : str ) -> bytes :
471+ """
472+ Encode a dotted OID string into DER OID bytes including tag and length.
473+ """
472474 parts = [int (part ) for part in oid .split ("." )]
473475 if len (parts ) < 2 :
474476 raise ValueError ("OID must contain at least two components" )
@@ -477,30 +479,33 @@ def _encode_der_oid(oid: str) -> bytes:
477479 if first not in (0 , 1 , 2 ):
478480 raise ValueError ("Invalid OID first component" )
479481 if second < 0 or (first < 2 and second > 39 ):
480- raise ValueError ("Invalid OID second component" )
482+ if not (first == 2 ):
483+ raise ValueError ("Invalid OID second component" )
481484
482- encoded = bytearray ([40 * first + second ])
485+ # Encode the combined root
486+ encoded = bytearray (cls ._encode_vlq (40 * first + second ))
483487
484488 for value in parts [2 :]:
485- encoded .extend (PublicKey . _encode_der_oid_component (value ))
489+ encoded .extend (cls . _encode_vlq (value ))
486490
487- return bytes ([0x06 ]) + PublicKey ._encode_der_length (len (encoded )) + bytes (encoded )
491+ return bytes ([0x06 ]) + cls ._encode_der_length (len (encoded )) + bytes (encoded )
488492
489- @staticmethod
490- def _encode_der_sequence (content : bytes ) -> bytes :
491- """Encode DER SEQUENCE for content bytes ."""
492- return bytes ([0x30 ]) + PublicKey ._encode_der_length (len (content )) + content
493+ @classmethod
494+ def _encode_der_sequence (cls , content : bytes ) -> bytes :
495+ """Encode DER SEQUENCE tag, length, and content per X.690 standards ."""
496+ return bytes ([0x30 ]) + cls ._encode_der_length (len (content )) + content
493497
494- @staticmethod
495- def _encode_der_bit_string (content : bytes ) -> bytes :
496- """Encode DER BIT STRING for content bytes."""
498+ @classmethod
499+ def _encode_der_bit_string (cls , content : bytes ) -> bytes :
500+ """
501+ Encode DER BIT STRING tag, length, and content per X.690 standards.
502+ """
497503 payload = bytes ([0x00 ]) + content
498- return bytes ([0x03 ]) + PublicKey ._encode_der_length (len (payload )) + payload
504+ return bytes ([0x03 ]) + cls ._encode_der_length (len (payload )) + payload
499505
500506 def to_bytes_der_ecdsa_compressed (self ) -> bytes :
501507 """
502- Returns DER-encoded SubjectPublicKeyInfo for secp256k1 using a compressed point.
503-
508+ Returns DER-encoded SubjectPublicKeyInfo for secp256k1 using a compressed SEC1 point.
504509 Raises:
505510 ValueError: If this key is not ECDSA secp256k1.
506511 """
@@ -512,7 +517,6 @@ def to_bytes_der_ecdsa_compressed(self) -> bytes:
512517 self ._encode_der_oid ("1.2.840.10045.2.1" )
513518 + self ._encode_der_oid ("1.3.132.0.10" )
514519 )
515-
516520 compressed_point = self .to_bytes_ecdsa (compressed = True )
517521 subject_public_key = self ._encode_der_bit_string (compressed_point )
518522
0 commit comments