Last active
November 24, 2024 01:38
-
-
Save mildsunrise/774362a0a7f09cd7e41abbd86d063e71 to your computer and use it in GitHub Desktop.
low-level DER formatting in python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def der_tag(tag_type: int, composed = False, tag_class = 0): | |
assert 0 <= tag_class < 4 and 0 <= tag_type < 31 # FIXME: long tag types not implemented | |
return bytes([ tag_class << 6 | int(composed) << 5 | tag_type ]) | |
def der_length(x: int): | |
if x < 128: return bytes([x]) | |
n = (x.bit_length() + 7) // 8 | |
assert n < 127 | |
return bytes([ 128 | n ]) + x.to_bytes(n) | |
def der_wrap(payload: bytes, raw: bool, tag_type: int, composed = False, tag_class = 0): | |
if raw: return payload | |
return (der_tag(tag_type, composed, tag_class) + der_length(len(payload))) + payload | |
der_null = der_wrap(b'', False, 5) | |
def der_integer(x: int, raw=False): | |
n = (~x if x < 0 else x).bit_length() // 8 + 1 | |
return der_wrap(x.to_bytes(n, signed=True), raw, 2) | |
def der_bitstring(x: bytes, unused_bits=0, raw=False): | |
return der_wrap(bytes([unused_bits]) + x, raw, 3) | |
def der_octetstring(x: bytes, raw=False): | |
return der_wrap(x, raw, 4) | |
def der_oid(*oid: int, raw=False): | |
assert all(i >= 0 for i in oid) | |
assert oid[0] < 2 and (oid[0] == 1 or oid[1] < 40) | |
oid = (oid[0]*40 + oid[1], *oid[2:]) | |
return der_wrap(b''.join(map(oid_varint, oid)), raw, 6) | |
def der_utf8string(x: str, raw=False): | |
return der_wrap(x.encode('utf-8'), raw, 12) | |
def der_ia5string(x: str, raw=False): | |
return der_wrap(x.encode('ascii'), raw, 22) | |
def der_sequence(*tags: bytes, raw=False): | |
return der_wrap(b''.join(tags), raw, 16, True) | |
def oid_varint(x: int): | |
n = max((x.bit_length() + 6) // 7, 1) | |
return bytes((x >> (i*7)) & 127 | (min(i, 1) << 7) for i in reversed(range(n))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment