@@ -13,43 +13,53 @@ 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- If value is not encoded, it will be encoded as ASCII.
21- If input string is not ASCII, and UnicodeEncodeError is raised.
20+ Tag and length are DER encoded. If tag value or length exceed 255, an OverflowError is raised.
2221
23- If encoded value is longer than 255 bytes, an OverflowError is raised.
22+ If value is not encoded, it will be encoded as ASCII.
23+ If input string is not ASCII, a UnicodeEncodeError is raised.
2424
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.
45- If input string is not ASCII, and UnicodeEncodeError is raised.
46-
47- If encoded value is longer than 255 bytes, an OverflowError is raised.
41+ If input string is not ASCII, a UnicodeEncodeError is raised.
4842
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+ If value exceeds 255, an OverflowError is raised.
60+
61+ @param value: the integer to encode
62+ @return: DER encoded byte array
63+ """
64+ value_bytes = value .to_bytes (1 , "big" ) # raises OverflowError if value >= 256
65+ return (0x81 ).to_bytes (1 , "big" ) + value_bytes if value >= 0x80 else value_bytes
0 commit comments