Skip to main content

DNS Security: DNSSEC, KSK/ZSK, and the Chain of Trust

·4 mins

Why DNSSEC? #

Plain DNS has no integrity check — a resolver has no way to tell a legitimate answer from a forged one. DNSSEC adds digital signatures to DNS records so a resolver can cryptographically verify that a response came from the zone’s real holder and wasn’t tampered with in transit.

It relies on three new record types:

  • DNSKEY — the zone’s public key(s)
  • RRSIG — a signature over a set of records (an RRset), created with the zone’s private key
  • DS (Delegation Signer) — a hash of a child zone’s KSK, published in the parent zone

The two-key model: KSK and ZSK #

DNSSEC separates duties between two key pairs, distinguished by the DNSKEY record’s flag field (RFC 4034):

KeyFlagRole
ZSK (Zone Signing Key)256Signs the zone’s regular records (A, MX, CNAME, etc.)
KSK (Key Signing Key)257Signs the DNSKEY RRset itself (i.e., signs the keys, not the data)

Both public keys are published together inside the same DNSKEY RRset.

Verification flow #

  1. The resolver fetches the DNSKEY RRset, the A RRset, RRSIG(DNSKEY), and RRSIG(A).
  2. It verifies RRSIG(DNSKEY) using the KSK public key — confirming the DNSKEY set (including the ZSK) is internally consistent.
  3. Once the ZSK is trusted, it verifies RRSIG(A) using the ZSK public key — confirming the A records are authentic.

For RSA signatures, verification recovers a hash from the signature using the public key and compares it to a locally computed hash. For ECDSA (which AWS uses), verification is a combined pass/fail operation rather than one that hands back a recoverable hash — but the underlying intent is the same: prove the data matches what the private key actually signed.

Breaking the circularity: the DS record #

Step 2 above has a gap: the KSK public key used to verify RRSIG(DNSKEY) comes from the very DNSKEY set being validated. An attacker could supply a fake DNSKEY set with a matching fake KSK and fake RRSIG(DNSKEY), and the check would still pass.

What breaks this circularity is the DS record in the parent zone:

  • The parent zone (e.g. .com) holds a DS record for the child zone (e.g. example.com) that is a hash of the legitimate KSK public key.
  • That DS record is itself signed by the parent’s own keys.
  • The resolver hashes the KSK from the DNSKEY set and compares it against the DS record obtained from the parent. A match means the parent vouches for this KSK.
  • The parent’s own keys are, in turn, vouched for by its parent, all the way up to the root trust anchor, which the resolver trusts inherently.

Complete validation flow:

  1. Get the DNSKEY set, RRSIG(DNSKEY), A set, and RRSIG(A).
  2. Validate the KSK against the parent’s DS record (hash the KSK, compare to the DS record) — confirms the KSK is genuine, breaking the circular trust problem.
  3. Verify RRSIG(DNSKEY) with the now-trusted KSK — confirms the DNSKEY set, including the ZSK, is authentic.
  4. Verify RRSIG(A) with the now-trusted ZSK — confirms the A records are authentic.
  5. The DS record itself is trusted because it’s signed by the parent, chaining up to the root.

AWS Route 53 implementation #

  • Route 53 DNSSEC signing uses ECDSAP256SHA256 (algorithm 13, based on the ECC_NIST_P256 curve) for both the KSK and ZSK.
  • The KSK is backed by an asymmetric customer managed key in AWS KMS. That KMS key must be created in us-east-1, because Route 53 is a global service whose control plane runs in us-east-1 — KMS keys are regional, so they must live in the same region as the control plane that uses them.
  • The ZSK is managed and rotated automatically by Route 53 itself.

Sources: