ASN.1 Decoder
Read any DER or BER blob as a tag, length and offset tree beside a synchronized hex view — entirely on this device.
Every value in the input, in the order the bytes appear. Press Tab to focus this tree, then the arrow keys to move; Enter opens or closes a branch.
Paste, drop or open a file and its tag tree appears here.
Sixteen bytes a row, with the offset on the left and printable ASCII on the right. The rows of the value picked in the tree are marked.
The bytes appear here once there is something to decode.
Reads up to 10 MB of bytes at once. A PEM block is read up to 65,536 characters, which is about 48 KB of DER. Walks 64 levels of nesting. A value deeper than that is marked at level 64 instead of walked. Shows up to 20,000 values. A blob with more is cut off there and says so.
A PRIVATE KEY block is in this input. It is hidden below and nothing left this device — but treat a private key pasted anywhere as exposed.
Bytes are decoded in this tab. There is no upload, no URL field and no third-party request on this page.
What you paste or open is never stored — not in this browser, not anywhere else. This tool keeps no copy of it between visits.
This page reads structure only: tags, lengths, offsets and the leaf encodings X.690 pins. It knows nothing about what a certificate or a key means.
A shared link carries the view, the format setting and which branches are open — the bytes you pasted cannot travel in it, because the link has no field for them.
This paste looks like credential-shaped text. It is not stored anywhere, and it cannot travel in a shared link — the link has no field for it.
Decode a certificate's fields · Decode a certificate request's fields
Press ? for shortcuts
Do it offline:$ openssl asn1parse -inform DER -in file.der
How to use it
- Paste the bytes, or drop the file on the input pane. A badge names the form that was read — PEM, hex, Base64 or raw bytes — and clicking it records the form you expected, so a disagreement between your expectation and the bytes is printed instead of passing unnoticed.
- Read the tree. Each row prints the tag, the byte offset its header starts at, how many bytes that header takes and the content length the length field declares; constructed rows open to show what they contain.
- Select a row and the hex view scrolls to its bytes and highlights them. Arrow keys move between rows, so the whole structure can be walked without the mouse.
- Copy one value's bytes as hex, copy the whole tree or the hex dump, or download your view settings as .json. A shared link carries those settings — never the bytes you pasted.
Paste a PEM block, hex or Base64 — or drop a .der file — and every tag, length and byte offset appears as a tree beside a hex view that follows your selection. This decoder reads structure, not meaning: it will happily walk a blob no certificate parser accepts, and it names the exact byte where a length stops making sense. The bytes stay in this tab.
How it works
ASN.1 describes what a value means; X.690 describes how it is written down. In the DER and BER rules every value is three parts in a row: a tag saying what kind of thing follows, a length saying how many bytes it occupies, and the content itself. A tag byte carries the class in its top two bits, one bit saying whether the content is further values rather than raw bytes, and a five-bit number; when that number is 31 the real number continues in base-128 across the following bytes, which is how [1000] in the fourth example fits. A length under 128 is one byte; above that, the first byte says how many length bytes follow. Because each header states its own size, the whole file can be walked with no schema at all — that walk is what this page shows.
DER is BER with the choices removed. BER lets a constructed value leave its length open with the byte 0x80 and close it later with two zero bytes, and lets a short length be written the long way; DER forbids both, which is why signatures over DER are reproducible. This decoder accepts BER, walks indefinite lengths and reports what it saw, so bytes rejected by a strict DER reader still open here with a note explaining exactly which rule they broke. It does not reassemble segmented strings: a BER string split into chunks is shown as the chunks it really is.
Structure is all this page claims. A tag number has no name attached to it in the bytes — an OBJECT IDENTIFIER decodes to a dotted number, and whether that number is a signature algorithm or something else is not written in the file. Limits: 10,485,760 bytes (10 MB) of input, 64 levels of nesting, 20,000 nodes; pasted PEM text is additionally capped at 65,536 characters, so a PEM block bigger than that has to be converted to DER first. Past a limit the decode stops and says so. Structural faults never stop it: a bad length becomes an error row inside the tree, carrying one of seven codes — TRUNCATED_TAG, TRUNCATED_LENGTH, TRUNCATED_CONTENT, CONTENT_OVERRUNS, INDEFINITE_ON_PRIMITIVE, DEPTH_CAP, NODE_CAP — and everything readable around it is still shown.
Examples
30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00SEQUENCE offset 0 header 2 length 13 constructed
OBJECT IDENTIFIER offset 2 header 2 length 9 → 1.2.840.113549.1.1.11
NULL offset 13 header 2 length 0Fifteen bytes, three values. The SEQUENCE header is two bytes and declares 13 more, so its content runs to the end; the OID inside occupies bytes 2 to 12 and decodes to a dotted number; the NULL at byte 13 has a length of zero, which is a real value, not a missing one. Spaces in the pasted hex are ignored.
02 09 00 ef 96 9d a7 17 38 b8 0dINTEGER offset 0 header 2 length 9 → ef969da71738b80dNine content bytes, eight shown. ASN.1 integers are signed, so a value whose first byte is 0x80 or higher needs a leading zero to stay positive — that zero is padding, not data, and command-line tools drop it too. The raw row keeps all nine bytes, so nothing is hidden; only the reading is trimmed.
30 80 02 01 2a 00 00SEQUENCE offset 0 header 2 length 3 constructed indefinite
INTEGER offset 2 header 2 length 1 → 2a
note This input uses indefinite-length encoding (length octet 0x80 closed by 00 00). That is valid BER but never valid DER, so a strict DER reader will reject these bytes.The length byte 0x80 means the writer did not know the size yet; the two zero bytes at the end close it. The row prints the span actually measured — 3 bytes — rather than the word the file uses, and the note names the rule these bytes break.
bf 87 68 02 05 00[1000] offset 0 header 4 length 2 constructed
NULL offset 4 header 2 length 0A context tag numbered 1000. The first byte ends in five 1 bits, the escape that says the number continues, and 87 68 carries it in base 128 — so the header is four bytes rather than two. The label has no name because a context tag only means something inside the schema that defined it.
30 03 02 08 01 ff ff ff ff ff ff ff ff ffSEQUENCE offset 0 header 2 length 3 constructed
INTEGER offset 2 header 2 length 8 → 01ffffffffffffff
! CONTENT_OVERRUNS The INTEGER at byte 2 declares 8 content bytes, which runs 7 bytes past the end of the value that contains it (byte 5, 1 byte of room). Decoding at this level stopped there. The two lengths disagree, so one of them is wrong.
[PRIVATE 2147483647] offset 5 header 6 length 0 constructed
! TRUNCATED_TAG The tag beginning at byte 5 encodes a tag number wider than this decoder reads (the ceiling is 2,147,483,647, five base-128 octets). Nothing after byte 5 could be read as ASN.1. A tag number this large usually means the bytes are not ASN.1, or the paste started mid-value.
note This input holds 2 top-level values, not one. All of them are shown. A file that should carry a single certificate or key usually holds exactly one — extra values here often mean two blobs were pasted together.Two lengths that disagree: the SEQUENCE says 3 bytes, the INTEGER inside it says 8. Both rows still appear, each naming the byte it failed at. The leftover bytes after the SEQUENCE cannot be a tag either, so they become a second error row instead of silence — openssl gives up after the first line here.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
A private key pasted here is decoded, never kept
A PRIVATE KEY fence raises a labelled notice and the key material is masked until you reveal it. Nothing is written to storage, no restore is offered, and the shared link carries view settings only. A private key that has been pasted anywhere is still worth treating as exposed.
Two size limits, and the PEM one is much lower
Raw bytes, hex and Base64 run to 10,485,760 bytes. Pasted PEM text stops at 65,536 characters — roughly 48 KB of DER — because the fence has to be scanned as text first. Past either limit the decode is declined outright rather than done halfway, and the message names the limit you hit.
Several values in one paste is normal here
Two blobs pasted together, or trailing bytes after the last value, produce a second root rather than an error: every top-level value found is shown, with a note counting them. Files meant to hold one structure usually do, so a count above one is worth a second look.
A 64-level cap turns a nesting bomb into 64 rows
Bytes that open a million nested values are a cheap way to crash a decoder. This one stops at 64 levels and marks the row DEPTH_CAP, and stops at 20,000 nodes with NODE_CAP; both leave everything decoded so far on screen.
Hex is read loosely, on purpose
Colons, spaces, newlines and a leading 0x are all accepted, so a dump copied from a terminal works without cleaning. An odd number of hex digits is refused rather than guessed at, because dropping or padding a nibble would shift every offset after it.
Text leaves are decoded, guesses are not
OBJECT IDENTIFIER, INTEGER, BIT STRING, the string types and the two time types have one unambiguous reading each, so those are printed. An OCTET STRING is left as bytes: whether it holds a nested structure, a hash or a UTF-8 label is a schema question this page cannot answer.
Common errors
There is nothing to decode yet. Paste a PEM block, hex or Base64, or drop a .der/.crt/.cer file — the bytes stay on this device either way.- The idle state, not a fault. It also appears when a PEM fence is present but empty — a header and footer with no body between them, which is what a truncated copy usually looks like.
This text is not PEM, hex or Base64, so there are no bytes to walk. Paste a -----BEGIN block, an unbroken run of hex digits, or a Base64 body — or drop the file itself, which needs no conversion.- Text has to become bytes before anything can be walked, and none of the three readings applied. The usual cause is a hex dump pasted with its offset column or ASCII gutter attached; dropping the file avoids the question entirely.
This input is 10,485,761 bytes, over the 10,485,760-byte (10 MB) limit this decoder reads. Decode the part you care about — a certificate is normally a few kilobytes, and a value larger than this is a payload rather than a structure.- The whole input is declined rather than truncated, because every offset printed after a cut would be wrong. For a file this size, openssl asn1parse reads it locally with no limit.
This PEM text is 65,591 characters, over the 65,536-character limit for reading a PEM block. Decode the single block you care about, or convert it to DER first — a raw DER file may be up to 10,485,760 bytes.- PEM is scanned as text, which is why its limit is far below the byte limit. Pasting one block instead of a whole chain usually clears it; converting the block to DER first raises the ceiling to the full 10 MB.
The INTEGER at byte 2 declares 8 content bytes, which runs 7 bytes past the end of the value that contains it (byte 5, 1 byte of room). Decoding at this level stopped there. The two lengths disagree, so one of them is wrong.- An inner length claims more room than its parent has. This is an error row inside the tree, not a refusal — the rows before it stay readable, and the byte named is where to start comparing against whatever wrote the file.
FAQ
What is the difference between DER and BER here?
BER allows several ways to write the same value; DER picks one of each, which is what makes a signature over it reproducible. This page reads both and notes every BER-only choice it meets — an indefinite length, or a length written the long way when the short form would do.
Why does my file show more than one top-level value?
Because there is more than one. Concatenated blobs and trailing bytes both produce extra roots, and all of them are shown with a count in a note rather than discarded.
Can this page tell me what a certificate contains?
No. It reads tags, lengths and offsets and prints the dotted form of an OBJECT IDENTIFIER; naming fields is a different job, and the certificate and CSR pages linked below do it.
Does it break when the bytes are damaged?
No — that is the case it is built for. A bad tag or length becomes an error row carrying one of seven codes and the byte offset it failed at, and the readable structure around it stays on screen.
How large an input will it take?
10,485,760 bytes of DER, 64 levels of nesting and 20,000 nodes; pasted PEM text is capped separately at 65,536 characters. Over a limit the decode is declined and the message names which one.
Do my bytes leave the browser?
No. The decode runs in this tab, a dropped file is read locally and never sent, nothing is stored between visits, and a shared link carries view settings only — the pasted bytes are not part of what a link can hold.
Why is a length shown that the file does not contain?
For an indefinite-length value there is no length in the file at all, so the row prints the span measured up to the closing marker. For a damaged value the row prints what the length field declares, next to the error saying how many bytes are really there.
Keyboard shortcuts
- ⌘/Ctrl + Enter
- Walk the pasted bytes again, input untouched.
- ⌘/Ctrl + S
- Download the view settings as a .json file, not the web page.
- ⌘/Ctrl + C
- Copy the whole tree as text while nothing is selected.
- ⌘/Ctrl + Shift + C
- Copy the whole tree as text even when a selection is live.
- v
- Cycle the panes: tree, hex, split (outside text fields).
- t
- Cycle the theme — registered by the page header, not by this tool.
- ? or ⌘/Ctrl + /
- Open this decoder's shortcut sheet.
- Esc
- Close the sheet; what you pasted is never cleared.