azjezz/psl
PSL is a modern, well-typed standard library for PHP 8.4+, inspired by HHVM’s HSL. It offers safer, predictable APIs for async, collections, networking, I/O, crypto, terminal UI, and robust data validation—replacing brittle built-ins with consistent alternatives.
The DNSSEC component adds full DNSSEC validation to DNS resolution. It is a standalone package (php-standard-library/dnssec) that requires a Psl\DNS\ResolverInterface instance from the psl/dns package.
DNSSEC validation verifies that DNS responses have not been tampered with by checking cryptographic signatures (RRSIG), walking trust chains from the DNS root (DS/DNSKEY), and validating authenticated denial of existence proofs (NSEC/NSEC3).
To use DNSSEC, you need two things: a DNS resolver that requests DNSSEC records (dnssec: true), and the DNSSEC validation layer that wraps it.
@example('protocols/dnssec-basic.php')
Every DNSSEC-signed response includes RRSIG records alongside the answer records. Each RRSIG contains a cryptographic signature over a set of records, the signer's identity, and the key tag to locate the corresponding DNSKEY.
When SecureResolver receives a response, it verifies that the RRSIG signatures are valid using the zone's public keys (DNSKEY records). If any signature is invalid or expired, SignatureFailedException is thrown.
DNSSEC trust is established through a chain from the DNS root to the target zone. Each parent zone contains a DS (Delegation Signer) record that is a cryptographic hash of the child zone's DNSKEY. By verifying each link in the chain, TrustChainResolver proves that the zone's keys are authorized by the parent, all the way up to the root trust anchor.
The walk for example.com goes: root (.) DNSKEY > com. DS > com. DNSKEY > example.com. DS > example.com. DNSKEY.
When a domain does not exist (NXDOMAIN), the server must prove it. NSEC records list the names that DO exist in sorted order, proving there is no name between them. NSEC3 records do the same but with hashed names to prevent zone enumeration.
SecureResolver validates these proofs automatically. If the proof is missing or invalid, InvalidProofException is thrown.
TrustChainResolver uses the IANA root KSK as its trust anchor by default. For fully offline environments, StaticTrustChainResolver accepts pre-loaded DNSKEY records per zone, bypassing all network queries for trust chain resolution.
@example('protocols/dnssec-trust-anchor.php')
DNSSEC validation produces specific exceptions for each failure mode:
| Exception | Meaning |
|---|---|
SignatureFailedException |
RRSIG verification failed or crypto format is invalid |
BrokenTrustChainException |
DS/DNSKEY trust chain is incomplete or invalid |
InvalidProofException |
NSEC/NSEC3 proof does not check out |
UnsignedResponseException |
Expected DNSSEC-signed data but response was unsigned |
All exceptions extend Psl\DNSSEC\Exception\RuntimeException.
DNSSEC validation is expensive - each query triggers a trust chain walk from the root zone through every intermediate zone to the target. CachedTrustChainResolver caches the validated trust chain results so subsequent queries to the same TLD reuse the cached chain. Combine with CachedResolver on top to cache the final validated responses.
@example('protocols/dnssec-caching.php')
Compose DNSSEC validation with static entries, hosts file, search domains, split-horizon routing, multiple racing DNS-over-TLS nameservers, and caching. DNSSEC validation only wraps the public DNS path; trusted sources (static, internal, hosts file) are outside the validation boundary.
@example('protocols/dnssec-kitchen-sink.php')
| Algorithm | RFC |
|---|---|
| RSA/SHA-1 | RFC 4034 |
| RSA/SHA-256 | RFC 5702 |
| RSA/SHA-512 | RFC 5702 |
| ECDSA P-256/SHA-256 | RFC 6605 |
| ECDSA P-384/SHA-384 | RFC 6605 |
| Ed25519 | RFC 8080 |
| Ed448 | RFC 8080 |
| RFC | Coverage |
|---|---|
| RFC 4033 | DNSSEC introduction and requirements |
| RFC 4034 | DNSSEC resource records (RRSIG, DNSKEY, DS, NSEC) |
| RFC 4035 | DNSSEC protocol modifications and validation |
| RFC 5155 | NSEC3 hashed authenticated denial of existence |
| RFC 5702 | RSA/SHA-256 and RSA/SHA-512 for DNSSEC |
| RFC 6605 | ECDSA for DNSSEC (P-256/SHA-256, P-384/SHA-384) |
| RFC 8080 | Edwards-curve algorithms for DNSSEC (Ed25519, Ed448) |
See src/Psl/DNSSEC/ for the full API.
How can I help you explore Laravel packages today?