@@ -13,43 +13,52 @@ def from_hex(value: str) -> bytes:
1313 return bytes .fromhex (value .removeprefix ("0x" ))
1414
1515
16- def tlv (tag : int | IntEnum , * value : bytes | str | None ) -> bytes :
16+ def tlv (tag : int | IntEnum , value : bytes | str | None = None ) -> bytes :
1717 """
1818 Encode a value in TLV format (Tag-Length-Value)
1919
20+ Tag and length are DER encoded. If tag value or length exceed 255 bytes, an OverflowError is raised.
21+
2022 If value is not encoded, it will be encoded as ASCII.
2123 If input string is not ASCII, and UnicodeEncodeError is raised.
2224
23- If encoded value is longer than 255 bytes, an OverflowError is raised.
24-
2525 @param tag: the tag (can be an enum)
26- @param value: the value (can be already encoded, or a string)
26+ @param value: the value (can be already encoded, a string or None )
2727 @return: encoded TLV
2828 """
29- values_encoded = bytearray ()
30- for v in value :
31- if v is not None :
32- values_encoded .extend (v .encode ("ascii" , errors = "strict" ) if isinstance (v , str ) else v )
33- return (
34- (tag .value if isinstance (tag , IntEnum ) else tag ).to_bytes (1 , "big" )
35- + len (values_encoded ).to_bytes (1 , "big" )
36- + values_encoded
37- )
3829
30+ return der_encode_int (tag .value if isinstance (tag , IntEnum ) else tag ) + length_value (value )
3931
40- def length_value (value : bytes | str | None ) -> bytes :
32+
33+ def length_value (
34+ value : bytes | str | None ,
35+ ) -> bytes :
4136 """
42- Prepend the length of the value encoded on 1 byte to the value itself.
37+ Prepend the length (DER encoded) of the value encoded to the value itself.
38+ If length exceeds 255 bytes, an OverflowError is raised.
4339
4440 If value is not encoded, it will be encoded as ASCII.
4541 If input string is not ASCII, and UnicodeEncodeError is raised.
4642
47- If encoded value is longer than 255 bytes, an OverflowError is raised.
48-
4943 @param value: the value (can be already encoded, or a string)
5044 @return: encoded TLV
5145 """
5246 if value is None :
5347 return (0 ).to_bytes (1 , "big" )
54- value_encoded = value .encode ("ascii" , errors = "strict" ) if isinstance (value , str ) else value
55- return len (value_encoded ).to_bytes (1 , "big" ) + value_encoded
48+ match value :
49+ case bytes ():
50+ value_encoded = value
51+ case str ():
52+ value_encoded = value .encode ("ascii" , errors = "strict" )
53+ return der_encode_int (len (value_encoded )) + value_encoded
54+
55+
56+ def der_encode_int (value : int ) -> bytes :
57+ """
58+ Encode an integer in DER format.
59+
60+ @param value: the integer to encode
61+ @return: DER encoded byte array
62+ """
63+ value_bytes = value .to_bytes (1 , "big" ) # raises OverflowError if value >= 256
64+ return (0x81 ).to_bytes (1 , "big" ) + value_bytes if value >= 0x80 else value_bytes
0 commit comments