Skip to content

Instantly share code, notes, and snippets.

@mildsunrise
Last active November 24, 2024 01:38
Show Gist options
  • Save mildsunrise/774362a0a7f09cd7e41abbd86d063e71 to your computer and use it in GitHub Desktop.
Save mildsunrise/774362a0a7f09cd7e41abbd86d063e71 to your computer and use it in GitHub Desktop.
low-level DER formatting in python
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