Skip to content
 

DNSSEC verification with dig

DNSSEC is the (not so) new technology that will finally fix the trust problems inherent in the DNS, making spoofing and forging much harder or impossible. Or at least, that's what everyone hopes.

Unfortunately, although the idea behind the technology is simple (it basically boils down to using well-known public key cryptography techniques to verify signatures attached to DNS replies), the details are scaringly complex, and comprehension is not helped by the fact that the final specification in use today was changed a few times since the first proposal.

Without having to set up a real DNS server, it's possible to observe the verification process by using only the dig utility. As the man page reminds, to use it for DNSSEC validation, dig must have been built with the -DDIG_SIGCHASE option. Luckily, all the major distributions seem to have a DNSSEC-enabled dig.

The example here will verify the A record for the domain name www.eurid.eu. But really, this is just a more-or-less randomly picked example; as more and more TLD are being signed, it should be possible to verify any name that has a trust of chain up to the root. For more information on the status of which TLD domains are signed, this ICANN page provides up-to-date information. As shown there, the eu. TLD is signed and has DS records in the root, as do many others. At the time of this writing, the net. and com. zones are scheduled to be signed in the first months of 2011. That will probably be the time when DNSSEC really starts to take off.

Root keys

Before starting, dig needs to be given a trust anchor (which is a fancy name for one or more keys that are trusted by definition and do not need to be verified further. The role of these keys is similar to the root SSL certificates installed in the browser: when something is signed with them, the verification ends successfully).
The perfect keys to use (and, in an ideal world where DNSSEC is fully deployed, the only needed) are the root keys, that is, the keys found in the "." zone. Since in DNSSEC keys are stored in DNSKEY records, here's how to download them with dig:

$ dig . DNSKEY | grep -Ev '^($|;)' > root.keys
# check
$ cat root.keys 
.			86352	IN	DNSKEY	256 3 8 AwEAAcAPhPM4CQHqg6hZ49y2P3IdKZuF44QNCc50vjATD7W+je4va6dj Y5JpnNP0pIohKNYiCFap/b4Y9jjJGSOkOfkfBR8neI7X5LisMEGUjwRc rG8J9UYP1S1unTNqRcWyDYFH2q3KnIO08zImh5DiFt8yfCdKoqZUN1du p5hy0UWz
.			86352	IN	DNSKEY	257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=

Here is a clearer query that shows the root keys with their tags:

$ dig +multiline . DNSKEY

; <<>> DiG 9.7.2-P2 <<>> +multiline . DNSKEY
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53322
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;.			IN DNSKEY

;; ANSWER SECTION:
.			86400 IN DNSKEY	256 3 8 (
				AwEAAcAPhPM4CQHqg6hZ49y2P3IdKZuF44QNCc50vjAT
				D7W+je4va6djY5JpnNP0pIohKNYiCFap/b4Y9jjJGSOk
				OfkfBR8neI7X5LisMEGUjwRcrG8J9UYP1S1unTNqRcWy
				DYFH2q3KnIO08zImh5DiFt8yfCdKoqZUN1dup5hy0UWz
				) ; key id = 40288
.			86400 IN DNSKEY	257 3 8 (
				AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQ
				bSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh
				/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWA
				JQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXp
				oY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3
				LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGO
				Yl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGc
				LmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0=
				) ; key id = 19036

;; Query time: 109 msec
;; SERVER: 172.27.20.21#53(172.27.20.21)
;; WHEN: Mon Nov 15 23:41:59 2010
;; MSG SIZE  rcvd: 439

Here we see that the root keys that we put in the trusted keys file have id 40288 and 19036. This will become important later.
(Note: strictly speaking, only the key with id 19036 - the KSK - is necessary, because that's the one that ultimately signs the root DNSKEY RRset, but having both can't hurt.)
Getting the root keys using dig is good enough for this example; in practice, serious validating resolvers will obtain the keys in a secure way, or the keys will come bundled with the software, similar to the built-in SSL root certificates that are bundled with browsers.

Obviously since the keys are rolled periodically, the keys above will not be valid for long, and will need to be downloaded again if the experiment is to be repeated in the future. The key numbers shown here are those in effect at the time of writing, and will make no sense at all in some weeks, when the keys are rolled.

Also note that for this and the following commands the DNS server used by dig (ie, the one found in /etc/resolv.conf) needs to support DNSSEC (ie, returning signatures if asked) and the EDNS0 extensions which are mandatory when using DNSSEC.

Bottom-up verification

As said, let's verify the A record for www.eurid.eu (line numbers in the output added for the following explanation):

$ dig +sigchase +trusted-key=./root.keys www.eurid.eu. A | cat -n
     1	;; RRset to chase:
     2	www.eurid.eu.		558	IN	A	195.234.53.204
     3	
     4	
     5	;; RRSIG of the RRset to chase:
     6	www.eurid.eu.		558	IN	RRSIG	A 7 3 600 20101201125038 20101101115329 62990 eurid.eu. cq4Sh8HJkFt1VPM/p+1IGEvwMiw9KRG+2GPnfCvquJNfKioB+MpV21E8 h7uV25V/kndXGEh+r27FRBCmsMAftdcrTtB+5NCwcfP17LKOxvDc3Mg1 p4UvVjMK//xiT+yJoM61qsLLbbfFEoCYtz0fZee4Hf7FLlvyYtXNXQG9 P34=
     7	
     8	
     9	
    10	Launch a query to find a RRset of type DNSKEY for zone: eurid.eu.
    11	
    12	;; DNSKEYset that signs the RRset to chase:
    13	eurid.eu.		86366	IN	DNSKEY	257 3 7 AwEAAbu3N0HTlocsABTY4SmW5Et6kAwa1BHg2Jmjcy87VIvKrubLCjeO FLbC2hklqnlZvlyUI5DzmS3YW/1iGNQJ+u9Rdv63BWq1HPCimkxJasSQ vIff1zTYDujCucJgnn5Y3nVnJYaRvn3pmaQYmVA4jL/b3vuOmCI1jNxU NKnfxYXntYBEvfU2C824Bsv+ngKwAVIW/+3dtDhCsHfYzN8lIRHXR9yi G3/sLvFUDUH4n9qIwYGFQ00Kiv/j35VGWwruLS2nj98tw2zEgKg9otcu natVSltUnajuauaTamSTDU/cKk45QHumbQxqxQ6CMv3irDsfVYh85tUe MtiXTb4Sn7s=
    14	eurid.eu.		86366	IN	DNSKEY	256 3 7 AwEAAecbZhciFc12GqKd3NSd40FpZ4PyXwfvnQ7makOUaY+McBWnkK6h j/6TvR+/UafBjxPcL6Dmv9UG+FFdiJJtoukC7IapbPkquA8ItnQrJp0R xWAAkJq5MlftKUAJfZGUgSlRHc6UBCHGjrJnf2QHN/NIFz5BzSPrhLiP 1/2wbDEF
    15	
    16	
    17	;; RRSIG of the DNSKEYset that signs the RRset to chase:
    18	eurid.eu.		86366	IN	RRSIG	DNSKEY 7 2 86400 20101123113942 20101116113254 34023 eurid.eu. TNQhHOH+TdsOzWglBBOUL5gUM7oHZbeFBis9e3PbDXN+wsD2yrOwek2A XczHFrtWoQp6i3eDWOvLwF4DltAjCiVKU+oPAbTJLnVldhWKA4Q+loK2 hl9NE8Txf8lUdRnSlqnewxkbdh3Ml7zUfPgKYWpYxd6/oE6SvOGLvNB5 i6y2lIXqgNyIwd7xL7Y1d+Jvto3U308c/jcws3xWvGkKVoqDBTH3+aaL n+g7VzcnKKusSAPr/aG+LBjXcnL46kWsPnSafFU4Qnw0V+ls8CpL0do7 TbGLVNWu5NVTLCC92orTIYOPRigV/Yg2f+hIiQiwoMIJssJQBQ8drCB+ yc01lg==
    19	eurid.eu.		86366	IN	RRSIG	DNSKEY 7 2 86400 20101123113942 20101116113254 62990 eurid.eu. CdldAM01iqI684Cwe2AF6ZDh4J8ODkbM9Cey+1jUMbAgnORW/WONAUMl 7DFOzchltbBo/5s7kqzoBMUEp8P41dkuLancH9/dHI7pUUNnzprdFFQV 9G+4gIwD3as4og17oX+b1gkf8VyYx8qBEDtIxT9DPHYZ1FwUTX2mBlNf zck=
    20	
    21	
    22	
    23	Launch a query to find a RRset of type DS for zone: eurid.eu.
    24	
    25	;; DSset of the DNSKEYset
    26	eurid.eu.		86366	IN	DS	34023 7 1 C0C4ABA58090643AE17BA8493C4AD2295D4D1376
    27	
    28	
    29	;; RRSIG of the DSset of the DNSKEYset
    30	eurid.eu.		86366	IN	RRSIG	DS 7 2 86400 20101122031929 20101115023628 37319 eu. rPrB+fdy1/oBoDosNKQhvVrTI3VeOkYVcNZgthsqt7DwlWNJ5NrRKfnF KbVzuiMpAHCBT+dWb9SRimBqCYGHHxSXym6gkWlAA0qJLV9HHqKZ7RF8 Ogro4mrknmxIKjgh/SNWZ4u9AN7rzeA9vuJHeYV6S3UefQMlSh9Par2Y WeE=
    31	
    32	
    33	
    34	
    35	;; WE HAVE MATERIAL, WE NOW DO VALIDATION
    36	;; VERIFYING A RRset for www.eurid.eu. with DNSKEY:62990: success
    37	;; OK We found DNSKEY (or more) to validate the RRset
    38	;; Now, we are going to validate this DNSKEY by the DS
    39	;; OK a DS valids a DNSKEY in the RRset
    40	;; Now verify that this DNSKEY validates the DNSKEY RRset
    41	;; VERIFYING DNSKEY RRset for eurid.eu. with DNSKEY:34023: success
    42	;; OK this DNSKEY (validated by the DS) validates the RRset of the DNSKEYs, thus the DNSKEY validates the RRset
    43	;; Now, we want to validate the DS :  recursive call
    44	
    45	
    46	Launch a query to find a RRset of type DNSKEY for zone: eu.
    47	
    48	;; DNSKEYset that signs the RRset to chase:
    49	eu.			86366	IN	DNSKEY	257 3 7 AwEAAc8eyl1THSdL4ZHXK4i5q7OfkxnbY6pA3vzs1O4CeF8wkR5yIHmd xhXfP17uIj73Fpr4ZU+5mK4N3vmJKtWV0ML3ieO1bXvPpuNEEvXmkNOK EUSAfnk9CT8AlS5jiJz6hpzkYd6OFIrnQVgIqGWOqRdx+1sMXBO+IuKh gvYLunsSZyBTWftiHy11NeGMNPA4QO4fcS/IgJIjvpYtr0lhlmwiyS5k c6fz8CD1YmiSzIAIcrqBfOi6/VCarEFxZsEhRi+UFp3ipUz6s8zZ+T8x lDxgRyScApiudiZKor/omLn+JUo4hAaJFo0R2EbnZY7hiK71DkTA2yY+ 3VKuizDV0Kk=
    50	eu.			86366	IN	DNSKEY	256 3 7 AwEAAb7UvT6q/qhscgKJPNDxrnB0Y8mMUqWMD1E69J4vzBc6dqKMckyC H49Sq//3+5mVBshLV3EZORl5guWDIcwJtWeGIgpzRjqDIgkJrDy4mPq1 4qv4mR3gvpsEKCKdSTR8FH+rcKd3aB7SYQLaNF2gqaZloAqjMBnffVd2 xlc4bWVP
    51	
    52	
    53	;; RRSIG of the DNSKEYset that signs the RRset to chase:
    54	eu.			86366	IN	RRSIG	DNSKEY 7 1 86400 20101119124925 20101112114925 37319 eu. vafh1utSPWOs4EZ9OS0KCeZxxTJEPge+LTjcdR9aQUcxdqVHceqr48RK mKuwi6U+qzZ0mXYz06V3Gn2apqayWOxNg/geIVf+5DsKNwkgaaHr1zHi sCxKcLikSevxTH2g3PwbAq1PBPillnNpmasKUwJ97MRyhTT0kj9wUx56 tUs=
    55	eu.			86366	IN	RRSIG	DNSKEY 7 1 86400 20101119124925 20101112114925 61179 eu. UrsoJdsyKuxhClgR8IiRN5iq/IDrOp5ElZ9PKyA0wULZD3aQtHB4USSB t4fJzgN6KbaCBwBSSsG0eWi5U+krquvkzGxqlYJD+9+Gtm4HlZpxATQ5 2rIytsR+vtCmeu2YrC42lGa4iF0oQ2rfzQvonGezWtdPUDI6Z9VdLeFu muw3BQO87NIrWF00VaVVXZotdwRFH7EA29v7snbLL5BpSaiSBlGCALhk 2dEleVbg8YcKTg/cgr2fasHrN0lGc2Dv8l5Ph2U6GMIb2DBAC22RqYk8 HhrbTXDacgbMVtcYIBprQ9JN6jZSXxmzl5RDedeoUQJgRR7QQ4cOiRYZ MUJm4g==
    56	
    57	
    58	
    59	Launch a query to find a RRset of type DS for zone: eu.
    60	
    61	;; DSset of the DNSKEYset
    62	eu.			58008	IN	DS	61179 7 1 87E2B3544884B45F36A0DA72DADCB0239C4D73D4
    63	eu.			58008	IN	DS	61179 7 2 3B526BCC354AE085AD9984C9BE73D271411023EFF421EF184BCE41AC E3DE9F8B
    64	
    65	
    66	;; RRSIG of the DSset of the DNSKEYset
    67	eu.			58008	IN	RRSIG	DS 8 1 86400 20101122000000 20101114230000 40288 . oePYMoFkBkYf7fh2hLam99KyzlRddeh1zsIGtrfk30u074wP3Z2WdLUm FPF8LbNXLAAIo+XtKYH4LK8h36L44FhEtBoS2GL4GGIZasenjBHMEDx0 z6A3+lOED50djuoOBWCsRenS54KHXrNJ8cTS9D/Yg60/GMToMHLyAYUJ eMU=
    68	
    69	
    70	
    71	
    72	;; WE HAVE MATERIAL, WE NOW DO VALIDATION
    73	;; VERIFYING DS RRset for eurid.eu. with DNSKEY:37319: success
    74	;; OK We found DNSKEY (or more) to validate the RRset
    75	;; Now, we are going to validate this DNSKEY by the DS
    76	;; OK a DS valids a DNSKEY in the RRset
    77	;; Now verify that this DNSKEY validates the DNSKEY RRset
    78	;; VERIFYING DNSKEY RRset for eu. with DNSKEY:61179: success
    79	;; OK this DNSKEY (validated by the DS) validates the RRset of the DNSKEYs, thus the DNSKEY validates the RRset
    80	;; Now, we want to validate the DS :  recursive call
    81	
    82	
    83	Launch a query to find a RRset of type DNSKEY for zone: .
    84	
    85	;; DNSKEYset that signs the RRset to chase:
    86	.			86093	IN	DNSKEY	256 3 8 AwEAAcAPhPM4CQHqg6hZ49y2P3IdKZuF44QNCc50vjATD7W+je4va6dj Y5JpnNP0pIohKNYiCFap/b4Y9jjJGSOkOfkfBR8neI7X5LisMEGUjwRc rG8J9UYP1S1unTNqRcWyDYFH2q3KnIO08zImh5DiFt8yfCdKoqZUN1du p5hy0UWz
    87	.			86093	IN	DNSKEY	257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=
    88	
    89	
    90	;; RRSIG of the DNSKEYset that signs the RRset to chase:
    91	.			86093	IN	RRSIG	DNSKEY 8 0 86400 20101124235959 20101110000000 19036 . SmZKqR1XNc73PUkVI6YRlXwcxeLfUmvLpikKaxTg+HmYCyWrmxzmYv/1 onFpCl8EZ75sGwIM78QCIekH+V1Azoc29fOx/NyWh86wc4bUqouoLXCH 99rEz2024pu8ZaC7ly1/HO+SCCV0ALT03/UvdwloEBl60bqBXZvN44K7 RIBqeLFOdXMHa5G8dNlopZaKsV5+0CGD28CgkC07A5//sumpEzGDmeq2 9gAGHk4WIpBL2EzUtToJRfdygpelA4akf+c32PkQGEEkjeDCEi1XCiwn lTCBiGrDAqYW5ivUb26h0twVH7vJlDWCR57/Q7SroV4oljK1tXkSL8bL 9beusw==
    92	
    93	
    94	
    95	Launch a query to find a RRset of type DS for zone: .
    96	;; NO ANSWERS: no more
    97	
    98	;; WARNING There is no DS for the zone: .
    99	
   100	
   101	
   102	;; WE HAVE MATERIAL, WE NOW DO VALIDATION
   103	;; VERIFYING DS RRset for eu. with DNSKEY:40288: success
   104	;; OK We found DNSKEY (or more) to validate the RRset
   105	;; Ok, find a Trusted Key in the DNSKEY RRset: 40288
   106	;; Ok, find a Trusted Key in the DNSKEY RRset: 19036
   107	;; VERIFYING DNSKEY RRset for . with DNSKEY:19036: success
   108	
   109	;; Ok this DNSKEY is a Trusted Key, DNSSEC validation is ok: SUCCESS
   110	

Good, the verification succeeded. But what happened? Let's go through the steps.

First, the RRset that needs to be verified is identified (a single item RRset here): quite obviously, that is (line 2)

www.eurid.eu.		558	IN	A	195.234.53.204

The signature for that record is given in line 6:

www.eurid.eu.		558	IN	RRSIG	A 7 3 600 20101201125038 20101101115329 62990 eurid.eu. cq4Sh8HJkFt1VPM/p+1IGEvwMiw9KRG+2GPnfCvquJNfKioB+MpV21E8 h7uV25V/kndXGEh+r27FRBCmsMAftdcrTtB+5NCwcfP17LKOxvDc3Mg1 p4UvVjMK//xiT+yJoM61qsLLbbfFEoCYtz0fZee4Hf7FLlvyYtXNXQG9 P34=

The interesting part of the signature is that it was created using the key with tag 62990, and the signer name is eurid.eu. (this will be useful in a second).

Since signatures are created using a private key, to verify the signature we need to have the corresponding public key, and that's what dig requests and shows in lines 13 and 14:

eurid.eu.		86366	IN	DNSKEY	257 3 7 AwEAAbu3N0HTlocsABTY4SmW5Et6kAwa1BHg2Jmjcy87VIvKrubLCjeO FLbC2hklqnlZvlyUI5DzmS3YW/1iGNQJ+u9Rdv63BWq1HPCimkxJasSQ vIff1zTYDujCucJgnn5Y3nVnJYaRvn3pmaQYmVA4jL/b3vuOmCI1jNxU NKnfxYXntYBEvfU2C824Bsv+ngKwAVIW/+3dtDhCsHfYzN8lIRHXR9yi G3/sLvFUDUH4n9qIwYGFQ00Kiv/j35VGWwruLS2nj98tw2zEgKg9otcu natVSltUnajuauaTamSTDU/cKk45QHumbQxqxQ6CMv3irDsfVYh85tUe MtiXTb4Sn7s=
eurid.eu.		86366	IN	DNSKEY	256 3 7 AwEAAecbZhciFc12GqKd3NSd40FpZ4PyXwfvnQ7makOUaY+McBWnkK6h j/6TvR+/UafBjxPcL6Dmv9UG+FFdiJJtoukC7IapbPkquA8ItnQrJp0R xWAAkJq5MlftKUAJfZGUgSlRHc6UBCHGjrJnf2QHN/NIFz5BzSPrhLiP 1/2wbDEF

Of these two keys, the first is a so-called Key Signing Key (KSK), and the second is a Zone Signing Key (ZSK). This is encoded in the fifth field: in that value, bit 0 is called the SEP (Secure Entry Point) and is set for the KSK, and not set for the ZSK (hence they usually have the two values 257 and 256 respectively). As a related note, the KSK is longer than the ZSK; this is usually the case, because the KSK is rolled less frequently (as changing it needs to involve the parent zone, while rolling the ZSK can be done independently and thus more often).

Although dig doesn't show the tags above, the KSK has tag 34023, and the ZSK has tag 62990. To check that, we can run something like this:

$ dig +multiline eurid.eu. DNSKEY

; <<>> DiG 9.7.2-P2 <<>> +multiline eurid.eu. DNSKEY
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36198
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;eurid.eu.		IN DNSKEY

;; ANSWER SECTION:
eurid.eu.		86400 IN DNSKEY	257 3 7 (
				AwEAAbu3N0HTlocsABTY4SmW5Et6kAwa1BHg2Jmjcy87
				VIvKrubLCjeOFLbC2hklqnlZvlyUI5DzmS3YW/1iGNQJ
				+u9Rdv63BWq1HPCimkxJasSQvIff1zTYDujCucJgnn5Y
				3nVnJYaRvn3pmaQYmVA4jL/b3vuOmCI1jNxUNKnfxYXn
				tYBEvfU2C824Bsv+ngKwAVIW/+3dtDhCsHfYzN8lIRHX
				R9yiG3/sLvFUDUH4n9qIwYGFQ00Kiv/j35VGWwruLS2n
				j98tw2zEgKg9otcunatVSltUnajuauaTamSTDU/cKk45
				QHumbQxqxQ6CMv3irDsfVYh85tUeMtiXTb4Sn7s=
				) ; key id = 34023
eurid.eu.		86400 IN DNSKEY	256 3 7 (
				AwEAAecbZhciFc12GqKd3NSd40FpZ4PyXwfvnQ7makOU
				aY+McBWnkK6hj/6TvR+/UafBjxPcL6Dmv9UG+FFdiJJt
				oukC7IapbPkquA8ItnQrJp0RxWAAkJq5MlftKUAJfZGU
				gSlRHc6UBCHGjrJnf2QHN/NIFz5BzSPrhLiP1/2wbDEF
				) ; key id = 62990

;; Query time: 42 msec
;; SERVER: 172.27.20.21#53(172.27.20.21)
;; WHEN: Tue Nov 16 21:04:17 2010
;; MSG SIZE  rcvd: 450

So, as expected, our signature on the A record was created with the ZSK (normally the KSK is only used to sign DNSKEY RRsets, although DNSSEC does not enforce that), tag 62990. So far so good.

But then, the DNSKEY records are themselves a RRset, and, like any other RRset, that has to be signed. We are walking the trust of chain: to verify the A record, we must verify its signature; to verify that signature, we need to have the public key that created it; that key is part of a RRset, and to verify it we need to verify its signature (and we're not done yet). That signature is exactly what we find in lines 18 and 19:

eurid.eu.		86366	IN	RRSIG	DNSKEY 7 2 86400 20101123113942 20101116113254 34023 eurid.eu. TNQhHOH+TdsOzWglBBOUL5gUM7oHZbeFBis9e3PbDXN+wsD2yrOwek2A XczHFrtWoQp6i3eDWOvLwF4DltAjCiVKU+oPAbTJLnVldhWKA4Q+loK2 hl9NE8Txf8lUdRnSlqnewxkbdh3Ml7zUfPgKYWpYxd6/oE6SvOGLvNB5 i6y2lIXqgNyIwd7xL7Y1d+Jvto3U308c/jcws3xWvGkKVoqDBTH3+aaL n+g7VzcnKKusSAPr/aG+LBjXcnL46kWsPnSafFU4Qnw0V+ls8CpL0do7 TbGLVNWu5NVTLCC92orTIYOPRigV/Yg2f+hIiQiwoMIJssJQBQ8drCB+ yc01lg==
eurid.eu.		86366	IN	RRSIG	DNSKEY 7 2 86400 20101123113942 20101116113254 62990 eurid.eu. CdldAM01iqI684Cwe2AF6ZDh4J8ODkbM9Cey+1jUMbAgnORW/WONAUMl 7DFOzchltbBo/5s7kqzoBMUEp8P41dkuLancH9/dHI7pUUNnzprdFFQV 9G+4gIwD3as4og17oX+b1gkf8VyYx8qBEDtIxT9DPHYZ1FwUTX2mBlNf zck=

We have two signatures here. One was created using the key with tag 34023 (the KSK), and the other was created using the key with tag 62990 (the ZSK). Both are signatures of the DNSKEY RRset; this RRset is, effectively, self-signed. How can we proceed further in the verification then? We need to have something in the parent zone (eu. here) that links into the eurid.eu. zone and allows us to climb further up in the chain of trust towards the root.

That "something" is called a DS record, which essentially is a cryptographic hash of the child zone's KSK, signed by the parent zone (ie, with the parent zone's key); if we trust the parent zone (we don't yet; we're still climbing the chain), we can then trust the KSK in the child zone. The DS record is shown in line 26:

eurid.eu.		86366	IN	DS	34023 7 1 C0C4ABA58090643AE17BA8493C4AD2295D4D1376

This record comes from the eu. zone, the parent of eurid.eu. As the fifth field shows, this is a hash of the child zone's KSK (tag 34023), which we encountered previously.
I said earlier that the DS record is signed (it must be, to be any good); and indeed, line 30 has the signature:

eurid.eu.		86366	IN	RRSIG	DS 7 2 86400 20101122031929 20101115023628 37319 eu. rPrB+fdy1/oBoDosNKQhvVrTI3VeOkYVcNZgthsqt7DwlWNJ5NrRKfnF KbVzuiMpAHCBT+dWb9SRimBqCYGHHxSXym6gkWlAA0qJLV9HHqKZ7RF8 Ogro4mrknmxIKjgh/SNWZ4u9AN7rzeA9vuJHeYV6S3UefQMlSh9Par2Y WeE=

This tells us that the signature was generated with the key with tag 37319 and the signer name is eu. . Let's see:

$ $ dig +multiline eu. DNSKEY

; <<>> DiG 9.7.2-P2 <<>> +multiline eu. DNSKEY
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42913
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;eu.			IN DNSKEY

;; ANSWER SECTION:
eu.			86400 IN DNSKEY	256 3 7 (
				AwEAAb7UvT6q/qhscgKJPNDxrnB0Y8mMUqWMD1E69J4v
				zBc6dqKMckyCH49Sq//3+5mVBshLV3EZORl5guWDIcwJ
				tWeGIgpzRjqDIgkJrDy4mPq14qv4mR3gvpsEKCKdSTR8
				FH+rcKd3aB7SYQLaNF2gqaZloAqjMBnffVd2xlc4bWVP
				) ; key id = 37319
eu.			86400 IN DNSKEY	257 3 7 (
				AwEAAc8eyl1THSdL4ZHXK4i5q7OfkxnbY6pA3vzs1O4C
				eF8wkR5yIHmdxhXfP17uIj73Fpr4ZU+5mK4N3vmJKtWV
				0ML3ieO1bXvPpuNEEvXmkNOKEUSAfnk9CT8AlS5jiJz6
				hpzkYd6OFIrnQVgIqGWOqRdx+1sMXBO+IuKhgvYLunsS
				ZyBTWftiHy11NeGMNPA4QO4fcS/IgJIjvpYtr0lhlmwi
				yS5kc6fz8CD1YmiSzIAIcrqBfOi6/VCarEFxZsEhRi+U
				Fp3ipUz6s8zZ+T8xlDxgRyScApiudiZKor/omLn+JUo4
				hAaJFo0R2EbnZY7hiK71DkTA2yY+3VKuizDV0Kk=
				) ; key id = 61179

;; Query time: 128 msec
;; SERVER: 172.27.20.21#53(172.27.20.21)
;; WHEN: Tue Nov 16 21:14:16 2010
;; MSG SIZE  rcvd: 444

Sure enough, the ZSK with tag 37319 is there.

At this point, dig has enough data to perform the first round of verifications (lines 35-43), which is successful. But we're not done yet: to verify the signature on the DS, we need to trust the key that was used to generate that signature (ie, key 37319). So dig goes out again and fetches the DNSKEY RRset for eu. (lines 49-50):

eu.			86366	IN	DNSKEY	257 3 7 AwEAAc8eyl1THSdL4ZHXK4i5q7OfkxnbY6pA3vzs1O4CeF8wkR5yIHmd xhXfP17uIj73Fpr4ZU+5mK4N3vmJKtWV0ML3ieO1bXvPpuNEEvXmkNOK EUSAfnk9CT8AlS5jiJz6hpzkYd6OFIrnQVgIqGWOqRdx+1sMXBO+IuKh gvYLunsSZyBTWftiHy11NeGMNPA4QO4fcS/IgJIjvpYtr0lhlmwiyS5k c6fz8CD1YmiSzIAIcrqBfOi6/VCarEFxZsEhRi+UFp3ipUz6s8zZ+T8x lDxgRyScApiudiZKor/omLn+JUo4hAaJFo0R2EbnZY7hiK71DkTA2yY+ 3VKuizDV0Kk=
eu.			86366	IN	DNSKEY	256 3 7 AwEAAb7UvT6q/qhscgKJPNDxrnB0Y8mMUqWMD1E69J4vzBc6dqKMckyC H49Sq//3+5mVBshLV3EZORl5guWDIcwJtWeGIgpzRjqDIgkJrDy4mPq1 4qv4mR3gvpsEKCKdSTR8FH+rcKd3aB7SYQLaNF2gqaZloAqjMBnffVd2 xlc4bWVP

(btw, these are the same keys we got separately a moment ago to check the key tags). At this point, the process should be clear: dig requests the signatures for the above RRset (lines 54 and 55), which are self-signed, and thus it needs to get the DS record from the parent of eu., which finally is the root zone: lines 62 and 63 are the DS RRset for eu. in the root zone, and the signature is at line 67, created with key 40288, which is the root's ZSK (dig hasn't got it yet, but if you go back to the paragraph where we downloaded the root keys you'll see it).

After another round of verifications (lines 72-80), dig goes on to verify the signatures on the DS records, so it requests the DNSKEY RRset for the root zone (lines 86 and 87) and the associated signature (line 91). Note that this signature is created with key 19036 which is the root's KSK.

But key 19036 is also one of the keys we originally put in the root.keys file (along with key 40288, as said). After dig tries to fetch a DS record for the root which does not exist, it finally realizes that the keys it wants to verify are trusted because they are in the supplied trusted key file (lines 105 and 106). At this stage, dig has successfully verified the whole chain of trust from www.eurid.eu up to the root, and declares success (line 109).

As mentioned previously, since ultimately it is the KSK that is used to create the topmost signature, the verification would have been successful even if the trusted key file had contained only the KSK (tag 19036). It would have failed, instead, if the only trusted key had been the ZSK (40288).

Top-down verification

The validation we just performed is a so-called "bottom-up" validation, similar to what happens when SSL certificates are verified: every stage validates the previous one, going up until a trusted key is found, at which point the whole chain (not yet validated until then) suddenly is declared valid by the transitive property of trust. In the DNSSEC world, this means starting from the domain name to verify, and going up towards the root.

But given the way trust chains are built in DNSSEC, it should also be possible to perform a "top-down" validation, starting from the root and going down towards the domain name that needs to be verified. Indeed, dig permits to run a "top-down" validation, using the +topdown option.

$ dig +sigchase +topdown +trusted-key=./root.keys www.eurid.eu. A | cat -n
     1	ns name: 198.41.0.4
     2	ns name: 192.228.79.201
     3	ns name: 192.33.4.12
     4	ns name: 128.8.10.90
     5	ns name: 192.203.230.10
     6	ns name: 192.5.5.241
     7	ns name: 192.112.36.4
     8	ns name: 128.63.2.53
     9	ns name: 192.36.148.17
    10	ns name: 192.58.128.30
    11	ns name: 193.0.14.129
    12	ns name: 199.7.83.42
    13	ns name: 202.12.27.33
    14	
    15	Launch a query to find a RRset of type A for zone: www.eurid.eu. with nameservers:
    16	.			518385	IN	NS	a.root-servers.net.
    17	.			518385	IN	NS	b.root-servers.net.
    18	.			518385	IN	NS	c.root-servers.net.
    19	.			518385	IN	NS	d.root-servers.net.
    20	.			518385	IN	NS	e.root-servers.net.
    21	.			518385	IN	NS	f.root-servers.net.
    22	.			518385	IN	NS	g.root-servers.net.
    23	.			518385	IN	NS	h.root-servers.net.
    24	.			518385	IN	NS	i.root-servers.net.
    25	.			518385	IN	NS	j.root-servers.net.
    26	.			518385	IN	NS	k.root-servers.net.
    27	.			518385	IN	NS	l.root-servers.net.
    28	.			518385	IN	NS	m.root-servers.net.
    29	
    30	no response but there is a delegation in authority section:eu.
    31	
    32	
    33	Launch a query to find a RRset of type DNSKEY for zone: .
    34	
    35	;; DNSKEYset:
    36	.			86400	IN	DNSKEY	256 3 8 AwEAAcAPhPM4CQHqg6hZ49y2P3IdKZuF44QNCc50vjATD7W+je4va6dj Y5JpnNP0pIohKNYiCFap/b4Y9jjJGSOkOfkfBR8neI7X5LisMEGUjwRc rG8J9UYP1S1unTNqRcWyDYFH2q3KnIO08zImh5DiFt8yfCdKoqZUN1du p5hy0UWz
    37	.			86400	IN	DNSKEY	257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=
    38	
    39	
    40	;; RRSIG of the DNSKEYset:
    41	.			86400	IN	RRSIG	DNSKEY 8 0 86400 20101124235959 20101110000000 19036 . SmZKqR1XNc73PUkVI6YRlXwcxeLfUmvLpikKaxTg+HmYCyWrmxzmYv/1 onFpCl8EZ75sGwIM78QCIekH+V1Azoc29fOx/NyWh86wc4bUqouoLXCH 99rEz2024pu8ZaC7ly1/HO+SCCV0ALT03/UvdwloEBl60bqBXZvN44K7 RIBqeLFOdXMHa5G8dNlopZaKsV5+0CGD28CgkC07A5//sumpEzGDmeq2 9gAGHk4WIpBL2EzUtToJRfdygpelA4akf+c32PkQGEEkjeDCEi1XCiwn lTCBiGrDAqYW5ivUb26h0twVH7vJlDWCR57/Q7SroV4oljK1tXkSL8bL 9beusw==
    42	
    43	;; Ok, find a Trusted Key in the DNSKEY RRset: 40288
    44	;; Ok, find a Trusted Key in the DNSKEY RRset: 19036
    45	;; VERIFYING DNSKEY RRset for . with DNSKEY:19036: success
    46	
    47	;; DSset:
    48	eu.			86400	IN	DS	61179 7 1 87E2B3544884B45F36A0DA72DADCB0239C4D73D4
    49	eu.			86400	IN	DS	61179 7 2 3B526BCC354AE085AD9984C9BE73D271411023EFF421EF184BCE41AC E3DE9F8B
    50	
    51	
    52	;; RRSIGset of DSset
    53	eu.			86400	IN	RRSIG	DS 8 1 86400 20101123000000 20101115230000 40288 . H6evquVeN2Nb6MZacZn0Bt64ViDiOcFcu9hpTJs6f4Q3iLjs6X6f4/wi p2SJOeD3VJ78E7PD8wOdzbFfjm8/MnQd5wZNavaH+Jegj1pb9q1GzBfr qM9Oq6gjnCLK3TiYh9WKlz4q0OQPBUQBvO293/R0bQu6hCCA2DHF16qw bkM=
    54	
    55	;; VERIFYING DS RRset for eu. with DNSKEY:40288: success
    56	ns name: 194.0.1.19
    57	ns name: 195.47.235.130
    58	ns name: 193.2.221.60
    59	ns name: 217.29.76.13
    60	ns name: 91.200.16.100
    61	ns name: 194.146.106.90
    62	ns name: 195.66.241.178
    63	
    64	Launch a query to find a RRset of type A for zone: www.eurid.eu. with nameservers:
    65	eu.			172800	IN	NS	x.nic.eu.
    66	eu.			172800	IN	NS	p.nic.eu.
    67	eu.			172800	IN	NS	l.eu.dns.be.
    68	eu.			172800	IN	NS	m.nic.eu.
    69	eu.			172800	IN	NS	a.nic.eu.
    70	eu.			172800	IN	NS	y.nic.eu.
    71	eu.			172800	IN	NS	l.nic.eu.
    72	
    73	no response but there is a delegation in authority section:eurid.eu.
    74	
    75	
    76	Launch a query to find a RRset of type DNSKEY for zone: eu.
    77	
    78	;; DNSKEYset:
    79	eu.			86400	IN	DNSKEY	257 3 7 AwEAAc8eyl1THSdL4ZHXK4i5q7OfkxnbY6pA3vzs1O4CeF8wkR5yIHmd xhXfP17uIj73Fpr4ZU+5mK4N3vmJKtWV0ML3ieO1bXvPpuNEEvXmkNOK EUSAfnk9CT8AlS5jiJz6hpzkYd6OFIrnQVgIqGWOqRdx+1sMXBO+IuKh gvYLunsSZyBTWftiHy11NeGMNPA4QO4fcS/IgJIjvpYtr0lhlmwiyS5k c6fz8CD1YmiSzIAIcrqBfOi6/VCarEFxZsEhRi+UFp3ipUz6s8zZ+T8x lDxgRyScApiudiZKor/omLn+JUo4hAaJFo0R2EbnZY7hiK71DkTA2yY+ 3VKuizDV0Kk=
    80	eu.			86400	IN	DNSKEY	256 3 7 AwEAAb7UvT6q/qhscgKJPNDxrnB0Y8mMUqWMD1E69J4vzBc6dqKMckyC H49Sq//3+5mVBshLV3EZORl5guWDIcwJtWeGIgpzRjqDIgkJrDy4mPq1 4qv4mR3gvpsEKCKdSTR8FH+rcKd3aB7SYQLaNF2gqaZloAqjMBnffVd2 xlc4bWVP
    81	
    82	
    83	;; RRSIG of the DNSKEYset:
    84	eu.			86400	IN	RRSIG	DNSKEY 7 1 86400 20101119124925 20101112114925 37319 eu. vafh1utSPWOs4EZ9OS0KCeZxxTJEPge+LTjcdR9aQUcxdqVHceqr48RK mKuwi6U+qzZ0mXYz06V3Gn2apqayWOxNg/geIVf+5DsKNwkgaaHr1zHi sCxKcLikSevxTH2g3PwbAq1PBPillnNpmasKUwJ97MRyhTT0kj9wUx56 tUs=
    85	eu.			86400	IN	RRSIG	DNSKEY 7 1 86400 20101119124925 20101112114925 61179 eu. UrsoJdsyKuxhClgR8IiRN5iq/IDrOp5ElZ9PKyA0wULZD3aQtHB4USSB t4fJzgN6KbaCBwBSSsG0eWi5U+krquvkzGxqlYJD+9+Gtm4HlZpxATQ5 2rIytsR+vtCmeu2YrC42lGa4iF0oQ2rfzQvonGezWtdPUDI6Z9VdLeFu muw3BQO87NIrWF00VaVVXZotdwRFH7EA29v7snbLL5BpSaiSBlGCALhk 2dEleVbg8YcKTg/cgr2fasHrN0lGc2Dv8l5Ph2U6GMIb2DBAC22RqYk8 HhrbTXDacgbMVtcYIBprQ9JN6jZSXxmzl5RDedeoUQJgRR7QQ4cOiRYZ MUJm4g==
    86	
    87	;; OK a DS valids a DNSKEY in the RRset
    88	;; Now verify that this DNSKEY validates the DNSKEY RRset
    89	;; VERIFYING DNSKEY RRset for eu. with DNSKEY:61179: success
    90	
    91	;; DSset:
    92	eurid.eu.		86400	IN	DS	34023 7 1 C0C4ABA58090643AE17BA8493C4AD2295D4D1376
    93	
    94	
    95	;; RRSIGset of DSset
    96	eurid.eu.		86400	IN	RRSIG	DS 7 2 86400 20101122031929 20101115023628 37319 eu. rPrB+fdy1/oBoDosNKQhvVrTI3VeOkYVcNZgthsqt7DwlWNJ5NrRKfnF KbVzuiMpAHCBT+dWb9SRimBqCYGHHxSXym6gkWlAA0qJLV9HHqKZ7RF8 Ogro4mrknmxIKjgh/SNWZ4u9AN7rzeA9vuJHeYV6S3UefQMlSh9Par2Y WeE=
    97	
    98	;; VERIFYING DS RRset for eurid.eu. with DNSKEY:37319: success
    99	ns name: 91.200.16.100
   100	ns name: 195.66.241.178
   101	ns name: 195.47.235.130
   102	
   103	Launch a query to find a RRset of type A for zone: www.eurid.eu. with nameservers:
   104	eurid.eu.		86400	IN	NS	a.nic.eu.
   105	eurid.eu.		86400	IN	NS	l.nic.eu.
   106	eurid.eu.		86400	IN	NS	p.nic.eu.
   107	
   108	
   109	
   110	Launch a query to find a RRset of type DNSKEY for zone: eurid.eu.
   111	
   112	;; DNSKEYset:
   113	eurid.eu.		86400	IN	DNSKEY	257 3 7 AwEAAbu3N0HTlocsABTY4SmW5Et6kAwa1BHg2Jmjcy87VIvKrubLCjeO FLbC2hklqnlZvlyUI5DzmS3YW/1iGNQJ+u9Rdv63BWq1HPCimkxJasSQ vIff1zTYDujCucJgnn5Y3nVnJYaRvn3pmaQYmVA4jL/b3vuOmCI1jNxU NKnfxYXntYBEvfU2C824Bsv+ngKwAVIW/+3dtDhCsHfYzN8lIRHXR9yi G3/sLvFUDUH4n9qIwYGFQ00Kiv/j35VGWwruLS2nj98tw2zEgKg9otcu natVSltUnajuauaTamSTDU/cKk45QHumbQxqxQ6CMv3irDsfVYh85tUe MtiXTb4Sn7s=
   114	eurid.eu.		86400	IN	DNSKEY	256 3 7 AwEAAecbZhciFc12GqKd3NSd40FpZ4PyXwfvnQ7makOUaY+McBWnkK6h j/6TvR+/UafBjxPcL6Dmv9UG+FFdiJJtoukC7IapbPkquA8ItnQrJp0R xWAAkJq5MlftKUAJfZGUgSlRHc6UBCHGjrJnf2QHN/NIFz5BzSPrhLiP 1/2wbDEF
   115	
   116	
   117	;; RRSIG of the DNSKEYset:
   118	eurid.eu.		86400	IN	RRSIG	DNSKEY 7 2 86400 20101123113942 20101116113254 34023 eurid.eu. TNQhHOH+TdsOzWglBBOUL5gUM7oHZbeFBis9e3PbDXN+wsD2yrOwek2A XczHFrtWoQp6i3eDWOvLwF4DltAjCiVKU+oPAbTJLnVldhWKA4Q+loK2 hl9NE8Txf8lUdRnSlqnewxkbdh3Ml7zUfPgKYWpYxd6/oE6SvOGLvNB5 i6y2lIXqgNyIwd7xL7Y1d+Jvto3U308c/jcws3xWvGkKVoqDBTH3+aaL n+g7VzcnKKusSAPr/aG+LBjXcnL46kWsPnSafFU4Qnw0V+ls8CpL0do7 TbGLVNWu5NVTLCC92orTIYOPRigV/Yg2f+hIiQiwoMIJssJQBQ8drCB+ yc01lg==
   119	eurid.eu.		86400	IN	RRSIG	DNSKEY 7 2 86400 20101123113942 20101116113254 62990 eurid.eu. CdldAM01iqI684Cwe2AF6ZDh4J8ODkbM9Cey+1jUMbAgnORW/WONAUMl 7DFOzchltbBo/5s7kqzoBMUEp8P41dkuLancH9/dHI7pUUNnzprdFFQV 9G+4gIwD3as4og17oX+b1gkf8VyYx8qBEDtIxT9DPHYZ1FwUTX2mBlNf zck=
   120	
   121	;; OK a DS valids a DNSKEY in the RRset
   122	;; Now verify that this DNSKEY validates the DNSKEY RRset
   123	;; VERIFYING DNSKEY RRset for eurid.eu. with DNSKEY:34023: success
   124	;; VERIFYING A RRset for www.eurid.eu. with DNSKEY:62990: success
   125	
   126	;; The Answer:
   127	www.eurid.eu.		600	IN	A	195.234.53.204
   128	
   129	
   130	;; FINISH : we have validate the DNSSEC chain of trust: SUCCESS
   131	
   132	;; cleanandgo

Again, success. But the route to that result was different this time. To better follow the events, it helps (more than in the bottom-up case) to capture the network traffic with tcpdump or wireshark while the top-down verification is being performed.
Some detail in the following explanation are not evident from the output of dig, and have been gathered by looking at the captured traffic.

Here, dig starts out by looking for the root zone name servers (lines 1-13). Then it picks one of the root servers previously obtained, and asks for tha A record of www.eurid.eu. (lines 15-28). This looks like the beginning of what normal DNS servers do when resolving a name that they don't know: query the root servers. (Spoiler: this is indeed what dig will do, this being a top-down validation; but in the process, dig will also look for the relevant DNSSEC records and perform validation as it goes down the chain of referrals.)

Obviously, the chosen root server knows nothing about the requested A record, but it returns a referral to the eu. name servers (line 30). A non-DNSSEC resolver would just follow the referral at this stage and query one of the referred-to servers.

But before doing that and leaving the root zone, dig makes a last request for the root zone DNSKEY records and associated signatures (lines 35-41). After that, dig sees (lines 43 and 44) that the keys it just received are trusted (because they are in the trusted key file specified on the command line), and thus declares the signature created with them valid (line 45).
The previously obtained referral also included, in the authority section, the DS records of the eu. zone, along wth its signature, which are shown in lines 48-49 and 53 respectively. Since the DS signature was generated with the ZSK (40288), and dig is trusting that key already (because it is in the trusted key file, and even if it wasn't, because it was signed with the KSK, which is trusted), dig declares the DS record valid (line 55). Note that the DS records hashes the eu. KSK, tag 61179.

Now dig is finally ready to follow the referral it was given, and thus it picks one of the servers it was referred to (lines 56-62) and repeats the original query (lines 64-71). Again, no direct answer but a referral to the eurid.eu. nameservers is returned (line 73). Similarly to what it did for the root, before following the referral dig requests the DNSKEY records and associated signatures for eu. (lines 78-85), and the authority section of the reply will contain, along with the actual nameservers for eurid.eu., the signed DS records for eurid.eu. (lines 91-96).

Now dig finds that the KSK key mentioned in the parent DS record (61179) is indeed part of the DNSKEY RRset for eu., and its hash matches that in the DS (line 87). This makes it trusted, because the parent vouched for its validity by means of the DS record it signed. Since this key is now trusted, dig can verify the signature for the eu. DNSKEY RRset that was created with key 61179 (lines 88-89). Now an important point is that the signature covers the whole DNSKEY RRset, and that RRset also includes the ZSK (37319). Since the RRset has been verified, key 37319 also becomes trusted.

From the last referral, dig also has the DS data for eurid.eu. (it was in the authority section of the reply), which is signed with the eu.'s ZSK (37319), which has just become trusted. So, dig can now successfully verify the signature on the DS record (line 98). The DS references key 34023 in the child (eurid.eu.).

At this point, dig leaves eu. and follows the referral to eurid.eu.. The process repeats one more time. However, this time the queried server is authoritative for eurid.eu., and has the answer.
Lines 99-101 show the available servers for eurid.eu., and dig queries one of them in lines 103-106. The server returns a proper answer (notice there's no mention of referrals, unlike the previous queries). However, to verify the answer, dig needs to have the zone keys, and it asks for them and their signature in lines 113-114 (DNSKEY) and lines 118-119 (signatures). As it did previously, first it checks that the key 34023 that was mentioned at the parent DS is contained in the DNSKEY RRset and hashes to the value found in the DS (line 121). With that, it can verify that the DNSKEY signature created with that key is valid (line 123), and this also makes the ZSK (62990) valid because it's in the same RRset covered by the verified signature. But the ZSK, 62990, is also the key that was used to sign the A record for www.eurid.eu., which dig can thus now validate (line 124). This is the last, definitive validation step; it is successful, and dig eventually declares success (line 130).

Conclusion

Hopefully this analysis shows that the DNSSEC verification process isn't too complicated; it's just a bit involved, due to the way the chain of trust is built in DNSSEC. Readers are invited to report any error or inaccuracy they may find.

The two verification methods differ in that in the bottom-up verification dig always queries the same server (the one it finds in resolv.conf), while in the top-down verification it uses that server only to get the initial list of root servers, but after that it autonomously queries the authoritative servers for each zone it traverses.

A good DNSSEC debugging tool, which seems to use the top-down approach, is at this page provided by VeriSign. Another debugger, which offers graphical diagrams of the chain of trust, is here. However, both tools seems to validate only A/AAAA records.

4 Comments

  1. Aleksandar says:

    Why does it fail on google? I thought they must be DNSSEC enabled. Just wondering if it is some crazy ISP DNS spoofing or google don't have it yet. Because your example domain from above worked for me.

    $ dig +sigchase +trusted-key=./root.keys google.com. A | cat -n
    1 ;; RRset to chase:
    2 google.com. 28 IN A 74.125.228.4
    3 google.com. 28 IN A 74.125.228.5
    4 google.com. 28 IN A 74.125.228.6
    5 google.com. 28 IN A 74.125.228.7
    6 google.com. 28 IN A 74.125.228.8
    7 google.com. 28 IN A 74.125.228.9
    8 google.com. 28 IN A 74.125.228.14
    9 google.com. 28 IN A 74.125.228.0
    10 google.com. 28 IN A 74.125.228.1
    11 google.com. 28 IN A 74.125.228.2
    12 google.com. 28 IN A 74.125.228.3
    13
    14
    15
    16 Launch a query to find a RRset of type RRSIG for zone: google.com.
    17
    18 ;; RRSIG is missing for continue validation: FAILED