Skip to content

Instantly share code, notes, and snippets.

@emlun
Created June 9, 2023 11:23
Show Gist options
  • Save emlun/ba41224cafb45592df94c9d09e9a2fee to your computer and use it in GitHub Desktop.
Save emlun/ba41224cafb45592df94c9d09e9a2fee to your computer and use it in GitHub Desktop.
Indent ASN.1 DER in hex
#!/usr/bin/env python3
import sys
from typing import Tuple
def is_container(value: bytes) -> bool:
return len(value) > 0 and value[0] in {0x30, 0x31}
def decode_next(b: bytes) -> Tuple[Tuple[bytes, bytes, bytes], bytes]:
if b[1] & 0x80 == 0:
length = b[1]
value_start = 2
value_end = value_start + length
else:
length_bytes = b[1] & 0x7f
value_start = 2 + length_bytes
length = int.from_bytes(b[2:2+length_bytes], 'big')
value_end = value_start + length
return (b[0:1], b[1:value_start], b[value_start:value_end]), b[value_end:]
def treeify(asn1: bytes):
items = []
tail = asn1
while len(tail) > 0:
(tag, length, value), tail = decode_next(tail)
if is_container(tag):
items.append((tag, length, treeify(value)))
else:
items.append((tag, length, value))
if len(items) == 1:
return items[0]
else:
return items
def indent(tree, depth=0) -> str:
tag, length, value = tree
if isinstance(value, list):
s = f"{' ' * depth}{tag.hex()} {length.hex()}"
for subvalue in value:
s += f"\n{indent(subvalue, depth=depth+1)}"
return s
elif isinstance(value, tuple):
s = f"{' ' * depth}{tag.hex()} {length.hex()}"
s += f"\n{indent(value, depth=depth+1)}"
return s
else:
return f"{' ' * depth}{tag.hex()} {length.hex()} {value.hex()}"
print(indent(treeify(sys.stdin.buffer.read())))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment