---
title: "ASN.1 / DER decoder — Crypto for Laravel | Roundly"
description: "A strict, bounded X.690 DER reader for the raw certificate-extension bytes that openssl_x509_parse() can’t give you."
url: https://roundly-consulting.com/open-source/docs/crypto-for-laravel/asn1-der
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Crypto for Laravel](https://roundly-consulting.com/open-source/docs/crypto-for-laravel.md)

# ASN.1 / DER decoder

Asn1\\DerDecoder is a strict X.690 reader. It exists because openssl\_x509\_parse() pretty-prints unknown extensions into lossy text, so anything that needs an extension’s actual bytes — an Apple WebAuthn nonce, say — needs a real DER walk:

```php
use RoundlyConsulting\Crypto\Facades\Crypto;

// The Apple WebAuthn nonce extension: SEQUENCE { [1] { OCTET STRING nonce } }
$element = Crypto::derDecoder()->decode($certificate->extension('1.2.840.113635.100.8.2')?->der ?? '');

$nonce = $element->tagged(1)?->children()[0]->octetString();
```

Or call the classes the facade fronts directly:

```php
use RoundlyConsulting\Crypto\Asn1\DerDecoder;

// The Apple WebAuthn nonce extension: SEQUENCE { [1] { OCTET STRING nonce } }
$element = (new DerDecoder)->decode($certificate->extension('1.2.840.113635.100.8.2')?->der ?? '');

$nonce = $element->tagged(1)?->children()[0]->octetString();

$element->children();          // list<DerElement>, in encoding order
$element->oid();               // '1.2.840.113635.100.8.2' — dotted decimal
$element->integer();           // int, or raw bytes when wider than 64 bits
$element->boolean();           // DER's 0x00 / 0xFF only
$element->isNull();

(new DerDecoder)->decodeFirst($bytes);   // element + bytesRead, for walking a run of TLVs
```

decode() reads exactly one element and treats trailing bytes as an error; decodeFirst() returns a DerResult with the element and bytesRead, for walking a run of TLVs. The decoder is a container singleton and is also reachable as Crypto::derDecoder().

## DerElement readers

| Member | Notes |
| --- | --- |
| `class / tag / constructed / contents` | The TagClass (Universal, Application, ContextSpecific, Private), the tag number (the high-tag form is supported), the form and the raw contents octets. |
| `children()` | Child elements of a constructed element, in encoding order; throws on a primitive. |
| `tagged($tag)` | The first child with that context-specific tag — how an optional \[n\] field is located. |
| `oid()` | The OBJECT IDENTIFIER in dotted decimal. |
| `integer()` | An int, or raw two’s-complement bytes when wider than 64 bits. |
| `octetString()` | The OCTET STRING contents, verbatim. |
| `boolean()` | DER’s 0x00 / 0xFF only. |
| `isNull()` | Whether the element is NULL — a predicate that reports rather than throws. |

Constructed elements are parsed eagerly, and each typed reader refuses a tag it does not admit (MalformedDerException::unexpectedTag) rather than guessing.

## Strictness and bounds

- Indefinite lengths (that is BER), non-minimal length or tag encodings and the reserved 0xFF length form are rejected.
- Padded INTEGERs and OID subidentifiers, BER-lax BOOLEANs and NULLs carrying content are rejected.
- A declared length past the end of the buffer is rejected — never an over-read.
- Trailing bytes after the top-level element and a constructed/primitive form mismatch are rejected.
- Work is bounded three ways: 64 KiB of input, 16 levels of nesting and 4096 elements.

Everything hostile is a MalformedDerException, never a PHP warning, and the decoder is fuzz-tested. It is a parser, never a trust store — what an extension’s contents mean is your call, made in your code.

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/crypto-for-laravel.md)
