Asn1

Minimal DER ASN.1 encoder/decoder used to assemble and inspect CMS/CAdES structures, RFC 3161 timestamp messages, and OCSP requests.

Namespace: Com\Tecnick\Pdf\Sign\Cms

class Asn1

Source: src/Cms/Asn1.php:38

Minimal DER ASN.1 encoder/decoder used to assemble and inspect CMS/CAdES structures, RFC 3161 timestamp messages, and OCSP requests. Only the subset of ASN.1 needed by PDF signatures is implemented.

Methods

assertMinimalInteger()

Assert that a DER INTEGER content string is minimally encoded.

The minimality half of decodeInteger(), for fields carrying an integer too wide to decode, such as a certificate serial number of up to 20 octets (RFC 5280 section 4.1.2.2).

public assertMinimalInteger(string $value): void

Parameters:

  • $value (string): Content octets (without tag/length).

Throws:

  • Exception: If the value is empty or non-minimally encoded.

Source: src/Cms/Asn1.php:568

assertSingleElement()

Assert that a string is exactly one complete DER element of the given tag.

public assertSingleElement(string $value, int $tag, string $label): void

Parameters:

  • $value (string)
  • $tag (int): Expected identifier octet.
  • $label (string): Name of the value, for the error message.

Throws:

  • Exception: If the value is empty, truncated, trailed, or of another tag.

Source: src/Cms/Asn1.php:370

decodeAlgorithmIdentifier()

Decode an X.509 AlgorithmIdentifier to the dotted form of its OID.

RFC 5280 section 4.1.1.2 shapes it as SEQUENCE { algorithm OBJECT IDENTIFIER, parameters ANY DEFINED BY algorithm OPTIONAL }, so one element may follow the OID and nothing may follow that. Both layers are bounded here rather than in each reader.

public decodeAlgorithmIdentifier(string $algorithmIdDer, string $label): string

Parameters:

  • $algorithmIdDer (string): Complete DER of the AlgorithmIdentifier.
  • $label (string): Name of the field, for the error messages.

Returns: string

Throws:

  • Exception: If the structure is malformed, trailed, or names no OID.

Source: src/Cms/Asn1.php:473

decodeBitString()

Read the octets of a DER BIT STRING element, without the unused-bits count.

Every BIT STRING read here holds whole octets (a signature, a public key), so a non-zero unused-bits count is refused.

public decodeBitString(array{tag: int, value: string, raw: string} $element): string

Parameters:

  • $element (array{tag: int, value: string, raw: string}): Parsed TLV.

Returns: string

Throws:

  • Exception: If the element is not a BIT STRING of whole octets.

Source: src/Cms/Asn1.php:716

decodeExtensions()

Decode an X.509 Extensions SEQUENCE into an OID to value-and-criticality map.

The shape is the one RFC 5280 section 4.1 defines: a SEQUENCE of SEQUENCE { extnID OBJECT IDENTIFIER, critical BOOLEAN DEFAULT FALSE, extnValue OCTET STRING }.

The input has to be exactly one Extensions SEQUENCE with no trailing bytes. An OID that appears twice is refused: RFC 5280 sections 4.2 and 5.2 admit at most one instance of each type.

public decodeExtensions(string $extensionsDer, string $label): array<string,array{critical: bool, value: string}>

Parameters:

  • $extensionsDer (string): Complete DER of the Extensions SEQUENCE, or ’’ when the field is absent.
  • $label (string): Name of the field, for the error messages.

Returns: array<string,array{critical: bool, value: string}>

Throws:

  • Exception: If the structure is malformed, trailed, or an OID appears twice.

Source: src/Cms/Asn1.php:394

decodeGeneralizedTime()

Decode a DER GeneralizedTime content string to a Unix timestamp.

The seconds must be present and the zone must be Z (X.690 section 11.7). The fractional part is refused unless the caller opts in; when accepted it must hold at least one digit and no trailing zero (X.690 section 11.7), and is dropped once validated.

Every field is range-checked by re-encoding the result and comparing it with the input, since gmmktime() wraps an out-of-range field rather than failing.

public decodeGeneralizedTime(string $value, bool $allowFraction = false): int

Parameters:

  • $value (string): Content octets (without tag/length).
  • $allowFraction (bool): Accept a fraction-of-second part, admitted by RFC 3161 section 2.4.2 for a token’s genTime.

Returns: int

Throws:

  • Exception: If the value is not a DER GeneralizedTime.

Source: src/Cms/Asn1.php:631

decodeInteger()

Decode a DER INTEGER content string to a PHP integer.

The content octets are two’s complement (X.690 section 8.3), so the sign bit is honoured. A value too wide for a PHP integer is rejected.

public decodeInteger(string $value): int

Parameters:

  • $value (string): Content octets (without tag/length).

Returns: int

Throws:

  • Exception: If the value is empty, non-minimal, or out of range.

Source: src/Cms/Asn1.php:597

decodeObjectIdentifier()

Decode a DER OBJECT IDENTIFIER content string to its dotted form.

The inverse of encodeObjectIdentifier(): the first subidentifier carries both leading arcs (X.690 section 8.19.4), and the rest are base-128 with continuation bits.

public decodeObjectIdentifier(string $value): string

Parameters:

  • $value (string): Content octets (without tag/length).

Returns: string

Throws:

  • Exception: If the value is empty, truncated, or non-minimally encoded.

Source: src/Cms/Asn1.php:736

decodeTime()

Decode a DER Time CHOICE element to a Unix timestamp.

X.509 carries validity and revocation instants as a CHOICE of UTCTime and GeneralizedTime, so a reader has to accept whichever the issuer used.

public decodeTime(array{tag: int, value: string, raw: string} $element): int

Parameters:

  • $element (array{tag: int, value: string, raw: string}): Parsed TLV.

Returns: int

Throws:

  • Exception: If the element is neither a UTCTime nor a GeneralizedTime.

Source: src/Cms/Asn1.php:697

decodeUtcTime()

Decode a DER UTCTime content string to a Unix timestamp.

DER requires the YYMMDDHHMMSSZ form (X.690 section 11.8). The two-digit year is read as 1950-2049, per RFC 5280 section 4.1.2.5.1.

public decodeUtcTime(string $value): int

Parameters:

  • $value (string): Content octets (without tag/length).

Returns: int

Throws:

  • Exception: If the value is not a DER UTCTime.

Source: src/Cms/Asn1.php:674

encodeBase128Int()

Encode a non-negative integer in base-128 with continuation bits.

public encodeBase128Int(int $value): string

Parameters:

  • $value (int): Integer value; must not be negative.

Returns: string

Throws:

Source: src/Cms/Asn1.php:264

encodeBoolean()

Encode a DER BOOLEAN.

public encodeBoolean(bool $value): string

Parameters:

  • $value (bool)

Returns: string

Source: src/Cms/Asn1.php:138

encodeContext()

Wrap pre-encoded content in a context-specific constructed tag [n].

The multi-octet tag form (X.690 section 8.1.2.4) is not emitted, so tag numbers of 31 and above are rejected.

public encodeContext(int $number, string $value): string

Parameters:

  • $number (int): Context tag number; must be 0..30.
  • $value (string)

Returns: string

Throws:

  • Exception: If the tag number is out of range or the length cannot be encoded.

Source: src/Cms/Asn1.php:191

encodeInteger()

Encode a non-negative integer as a DER INTEGER.

public encodeInteger(int $value): string

Parameters:

  • $value (int): Integer value; must not be negative.

Returns: string

Throws:

  • Exception: If the value is negative or the length cannot be encoded.

Source: src/Cms/Asn1.php:82

encodeIntegerBytes()

Encode a big-endian magnitude byte string as a DER INTEGER.

Trims superfluous leading zero octets and prepends a zero octet when the most significant bit is set, so the value stays non-negative.

public encodeIntegerBytes(string $bytes): string

Parameters:

  • $bytes (string)

Returns: string

Throws:

Source: src/Cms/Asn1.php:115

encodeLength()

Encode a DER length octet sequence.

public encodeLength(int $length): string

Parameters:

  • $length (int): Number of content octets; must not be negative.

Returns: string

Throws:

  • Exception: If the length is negative or too large to encode.

Source: src/Cms/Asn1.php:47

encodeNull()

Encode a DER NULL.

public encodeNull(): string

Returns: string

Source: src/Cms/Asn1.php:146

encodeObjectIdentifier()

Encode a dotted OID string as a DER OBJECT IDENTIFIER.

The first two arcs share one subidentifier with the value 40*arc0 + arc1, itself base-128 encoded (X.690 sections 8.19.2 and 8.19.4). The root arc is limited to 0..2, and the second arc to 0..39 under roots 0 and 1.

public encodeObjectIdentifier(string $oid): string

Parameters:

  • $oid (string)

Returns: string

Throws:

  • Exception: If the OID is malformed or the length cannot be encoded.

Source: src/Cms/Asn1.php:209

encodeOctetString()

Encode a DER OCTET STRING.

public encodeOctetString(string $value): string

Parameters:

  • $value (string)

Returns: string

Throws:

Source: src/Cms/Asn1.php:156

encodeSequence()

Wrap pre-encoded content in a DER SEQUENCE.

public encodeSequence(string $value): string

Parameters:

  • $value (string)

Returns: string

Throws:

Source: src/Cms/Asn1.php:166

encodeSet()

Wrap pre-encoded content in a DER SET.

public encodeSet(string $value): string

Parameters:

  • $value (string)

Returns: string

Throws:

Source: src/Cms/Asn1.php:176

readLength()

Read a DER length starting at the given offset.

The indefinite form and non-minimal long forms are rejected: DER requires the definite form with the fewest possible octets (X.690 section 10.1). The octet count is also capped so the accumulated length always fits a PHP integer, which on a 32-bit build is narrower than the 4-octet DER maximum.

public readLength(string $data, int &$offset): int

Parameters:

  • $data (string)
  • $offset (int): Read cursor; advanced past the length octets.

Returns: int

Throws:

  • Exception: If the length is malformed or unsupported.

Source: src/Cms/Asn1.php:515

readOptionalTlv()

Read one DER TLV triplet, or null when the cursor is at the end of the data.

public readOptionalTlv(string $data, int &$offset): array{tag: int, value: string, raw: string}|null

Parameters:

  • $data (string)
  • $offset (int): Read cursor; advanced past the parsed element.

Returns: array{tag: int, value: string, raw: string}|null

Throws:

  • Exception: If the structure or length is malformed.

Source: src/Cms/Asn1.php:332

readSingleElement()

Read a string that has to be exactly one complete DER element of the given tag.

public readSingleElement(string $value, int $tag, string $label): array{tag: int, value: string, raw: string}

Parameters:

  • $value (string)
  • $tag (int): Expected identifier octet.
  • $label (string): Name of the value, for the error message.

Returns: array{tag: int, value: string, raw: string}

Throws:

  • Exception: If the value is empty, truncated, trailed, or of another tag.

Source: src/Cms/Asn1.php:347

readTlv()

Read one DER TLV triplet starting at the given offset.

public readTlv(string $data, int &$offset): array{tag: int, value: string, raw: string}

Parameters:

  • $data (string)
  • $offset (int): Read cursor; advanced past the parsed element.

Returns: array{tag: int, value: string, raw: string}

Throws:

  • Exception: If the structure or length is malformed.

Source: src/Cms/Asn1.php:295