First up: this is gonna be a tricky topic.
Very RFC-heavy stuff comming up.
So, I got introduced to DNSSEC and to all that comes with it. I thought: ok, before you even try to verify whole chain for some records I have in my domain, first try to verify the root zone. And I'm stuck with that. Maybe it's something simple, but strangely there's not much info out there google will return - so this may require knowledge of some who really into this stuff.
After grinding throuhg lot of RFCs I got this little snipped up to reuqest DNSKEY + DNSSEC for "<root>" zone over my gateway (wich das a recursive stub resolver build in wich by itself just relays the query to my isp - wich maybe doin just some caching but also just relays up to next higher name-server wich end up in request of best availble nameserver):
192.168.178.1 is may gateway (may some users recognize this very ip - yes, it's an AVM FritzBox)
According to WireShark the outgoing request is valid and well-formed - no exception there. I do get a response from my gateway wich looks like this (note: already split up into headers and data-blocks):
DNSKEY-RR for key 19036 (the old root-KSK)
DNSKEY-RR for key 20326 (the new root-KSK)
DNSKEY-RR for key 2134 (current ZSK)
At first I got stuck on how to "de-cipher" the public key to load it with openssl - turns out to find out one has to read the obsoleted RFC define the old KEY an SIG records - it's explained in there, that first comes a length-byte wich is either 1 or 3 - then the public exponent - in this case 0x010001 - the the rest up to RDATA-LENGTH is the modulus. I converted them by hand to fit in standard openssl RSAPublicKey-format - and then just used openssl -pubout to get standard PEM for the current root-KSK - wich, at least until up to this point, I think is the current root of the whole DNSSEC - correct me right here if I'm wrong.
Now I try to verify the RRSIG-RR - and failed hard. The RFC says: signature is build-up by hashing specific order of data - in this very case it should be
RDATA of RRSIG-RR excluding the signature itself - wich is this part
According to RFC this "header"-part inside RDATA is made up of some fields like some timestamps, key-id, name-label ...
After RDATA of RRSIG then there should all matching RR in canonical order concatenated. As there are two KSK and one ZSK - the ZSK has flags 256 - the ZSK both has 257 - so, my guess here is, that at this point the ZSK should come first as the flag-byte differs. Then the two KSK should follow in the order of first key-19036 - as it's public key starts with a 0xA8 - followed by key-20326 - as it's public key starts with a 0xAC.
Oh - and all TTL-fields MUST be set to the value of the RRSIG-originalTTL-field - wich I have done by hand.
So, in sum I should end up with this big block:
As this is HEX I used xxd -r -p to convert it to binary - then used openssl dgst -verify root.pem -signature rrset.sig rrset - but it fails.
Has anyone the knowledge about DNSSEC and DNS to tell me where I messed up? Or am I using openssl dgst wrong? It has some flags like -sha256, -hex and -binary - maybe the signature fails as I try to use the wrong algorithm.
I didn't yet bothered to set up java to use java.security.Signature wich I can init with SHA256withRSA - splice in the extracted public key and just push in the raw bytes I'm getting from response.
Why I bother to try to implement it: I want to use some not common used DNS-RR wich my registrar provides to by set via an API to do some crypto stuff in one of my other projects.
Oh, and btw: two additional things:
1) Could anybody tell why google just can'T get a page or a link where I could had gotten the current public-key outside of DNS?
2) If my initial request is spoofed - how can I make sure to have the real root-key otherwise then just hard-code it into my code?
Wich returned TRUE - so I got the order of the RR right - what got wrong? For what ever reason there sneaked some random data in my rrset.sig file - after correcting this I now also get VERIFY OK from openssl.
nvm - at least now there is some code posted to verify the DNS root zone DNSKEY with signature and stuff.
Here's the public key in PEM wich I wasnt able to find using google:
The last question still remain: with out hard-coding this public key into my code as trust-anchor - how I can verify I didn't got spoofed by initial DNSKEY lookup? I guess impossible - right? But if some evil is eager to set-up a whole fake DNS system to spoof my routing - I guess one should has also access to my code to replace hard-coded public-key. I should stop trying to worry about un-avoidable issues. As long as there is access a hacker could always replace crypto root trust anchors with its own.