## 20190921 AK ---- [[HowToDocuments/FingerprintsViaDNSSEC/CZ|česky]] | [[HowToDocuments/FingerprintsViaDNSSEC/CY|cymraeg]] | [[HowToDocuments/FingerprintsViaDNSSEC/DE|deutsch]] | '''english''' | [[HowToDocuments/FingerprintsViaDNSSEC/ES|español]] | [[HowToDocuments/FingerprintsViaDNSSEC/FR|français]] | [[HowToDocuments/FingerprintsViaDNSSEC/NL|nederlands]] | [[HowToDocuments/FingerprintsViaDNSSEC/PT|português]] --- [[HowToDocuments|more step-by-step guides]] ---- == Verify fingerprints via DNSSEC == To verify if the fingerprints of the downloaded root certificates are correct you can use DNSSEC-protected TXT records under the cacert.org domain. The information about the fingerprints is stored in the DNS zone _fp.cacert.org - the underscore indicates non-host information. For each generation of root certificates a new sub-directory will be created. The current one is "g1". To list all available certificates of a specific generation you can query the label _certs for that sub-directory given a DNS query for _certs.g1._fp.cacert.org yielding the two names "root_X0F class3_X0E" as the certificates. Each of those references in turn provides both an URL ("_url") and a set of fingerprints (_md5, _sha1, _sha256) needed for the verified download of that certificate. To download the current (g1) root certificate you'd thus look for the download URL at _url.root_X0F.g1._fp.cacert.org and verify the SHA2-256 fingerprint given at _sha256.root_X0F.g1._fp.cacert.org. Fingerprints are always uppercase and without any delimiters. /!\ When using commands and scripts, always start with the heading record _certs.g1._fp.cacert.org, currently yielding "root_X0F class3_X0E". Where material uses "root class3" instead it is outdated and should be implementing the first query. For short test on Linux the below code can do the check. For production use MAKE sure that the DNS responses are validated. This can be achieved by installation of a validating stub resolver [1, 2]. Please refer to your distributions advice on how to properly setup DNSSEC if necessary. {{{ $ host -t TXT _url.root_X0F.g1._fp.cacert.org. _url.root_X0F.g1._fp.cacert.org descriptive text "http://www.cacert.org/certs/root_X0F.crt" $ host -t TXT _sha256.root_X0F.g1._fp.cacert.org. _sha256.root_X0F.g1._fp.cacert.org descriptive text "07EDBD824A4988CFEF4215DA20D48C2B41D71529D7C900F570926F277CC230C5" $ wget -O root_X0F.crt 'http://www.cacert.org/certs/root_X0F.crt' $ openssl x509 -in root_X0F.crt -noout -fingerprint -sha256 | tr -d : SHA256 Fingerprint=07EDBD824A4988CFEF4215DA20D48C2B41D71529D7C900F570926F277CC230C5 }}} In Windows, the same information can be obtained using nslookup: {{{ >nslookup Default Server: my.dnssrv.eu Address: 2001:470:6f:458:c56d:5931:992:4708 > set type=TXT > _url.root_X0F.g1._fp.cacert.org. Server: my.dnssrv.eu Address: 2001:470:6f:458:c56d:5931:992:4708 Non-authoritative answer: _url.root_X0F.g1._fp.cacert.org text = "http://www.cacert.org/certs/root_X0F.crt" > _sha256.root_X0F.g1._fp.cacert.org. Server: my.dnssrv.eu Address: 2001:470:6f:458:c56d:5931:992:4708 Non-authoritative answer: _sha256.root_X0F.g1._fp.cacert.org text = "07EDBD824A4988CFEF4215DA20D48C2B41D71529D7C900F570926F277CC230C5" > _url.class3_X0E.g1._fp.cacert.org. Server: my.dnssrv.eu Address: 2001:470:6f:458:c56d:5931:992:4708 Non-authoritative answer: _url.class3_X0E.g1._fp.cacert.org text = "http://www.cacert.org/certs/class3_X0E.crt" > _sha256.class3_X0E.g1._fp.cacert.org. Server: my.dnssrv.eu Address: 2001:470:6f:458:c56d:5931:992:4708 Non-authoritative answer: _sha256.class3_X0E.g1._fp.cacert.org text = "F6873D70D67596C2ACBA34401E69738B52701DD6AB06B49749BC55150936D544" > exit }}} A small script doing the validation (if the system resolver is properly configured) can be seen below. The exit status is 0 on success, or non-zero otherwise (error 3, 4 and 5 may indicate a system resolver dropping DNSSEC records). /!\ The script does not work, at least on Ubuntu 15.10 platform. It ends with the result code of 3 on the line 8. /!\ * The updated script with the original lines commented just before the changed ones: [[attachment:CAcert-roots-fingerprint-test.sh]]. These are changed lines, according to the original script listed below: 8, 10, 24, 26, 33, 35. * Reasons: 1. There is no flag "ad" in the "dig" output; it is replaced by "rd" in the script. 1. There are no lines containing " RRSIG" in the "dig" output. {{{#!highlight bash #!/bin/bash # Fetch list of available root certificates (names) TMP_RESPONSE=___root___$$.tmp dig +nocmd +comments +nostats +norrcomments +dnssec IN TXT _certs.g1._fp.cacert.org. > ${TMP_RESPONSE} || exit 1 grep -q '^;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: ' ${TMP_RESPONSE} || exit 2 grep '^;; flags:' ${TMP_RESPONSE} | cut '-d;' -f3 | cut -d: -f2 | grep -q ad || exit 3 grep '^; EDNS:' ${TMP_RESPONSE} | tr ";," "\n\n" | grep flags | cut -d: -f2 | grep -q do || exit 4 grep -v '^;' ${TMP_RESPONSE} | grep -q RRSIG || exit 5 ROOTS=$(grep -v '^;' "${TMP_RESPONSE}" | grep -v " RRSIG " | grep TXT | cut '-d"' -f2 | head -1) printf "Found roots: %s\n\n" "$ROOTS" rm -f -- "${TMP_RESPONSE}" for a in $ROOTS; do printf "Downloading %s ...\n" "$a" # Fetch the download URL of the current certificate in the list TMP_ROOT=___root___$$.tmp dig +nocmd +comments +nostats +norrcomments +dnssec IN TXT "_url.$a.g1._fp.cacert.org." > ${TMP_ROOT} || exit 11 grep -q '^;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: ' ${TMP_ROOT} || exit 12 grep '^;; flags:' ${TMP_ROOT} | cut '-d;' -f3 | cut -d: -f2 | grep -q ad || exit 13 grep '^; EDNS:' ${TMP_ROOT} | tr ";," "\n\n" | grep flags | cut -d: -f2 | grep -q do || exit 14 grep -v '^;' ${TMP_ROOT} | grep -q RRSIG || exit 15 CRT_URL=$(grep -v '^;' ${TMP_ROOT} | grep -v " RRSIG " | grep TXT | cut '-d"' -f2 | head -1) # Fetch the SHA2-256 fingerprint of the current certificate in the list TMP_ROOT_FP=___root___$$.tmp dig +nocmd +comments +nostats +norrcomments +dnssec IN TXT "_sha256.$a.g1._fp.cacert.org." > ${TMP_ROOT_FP} || exit 21 grep -q '^;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: ' ${TMP_ROOT_FP} || exit 22 grep '^;; flags:' ${TMP_ROOT_FP} | cut '-d;' -f3 | cut -d: -f2 | grep -q ad || exit 23 grep '^; EDNS:' ${TMP_ROOT_FP} | tr ";," "\n\n" | grep flags | cut -d: -f2 | grep -q do || exit 24 grep -v '^;' ${TMP_ROOT_FP} | grep -q RRSIG || exit 25 CRT_FP=$(grep -v '^;' ${TMP_ROOT_FP} | grep -v " RRSIG " | grep TXT | cut '-d"' -f2 | head -1) # Download the current certificate in the list from the obtained URL wget --quiet -O "___CRT___$a.crt" "$CRT_URL" || exit 31 # Calculate fingerprint of the downloaded certificate file DL_FP=$(openssl x509 -in "___CRT___$a.crt" -noout -fingerprint -sha256 | cut -d= -f2 | tr -d :) printf "Found Certificate for Root \"%s\":\n- CRT URL:\t%s\n- CRT FP:\t%s\n- DL FP:\t%s\n\n" "$a" "$CRT_URL" "$CRT_FP" "$DL_FP" # Compare fingerprints of the downloaded certificate with the fetched value from DNS if [ ! "$CRT_FP" == "$DL_FP" ]; then printf 'Verification Failed!' exit 32 fi rm -f -- "$TMP_ROOT" "$TMP_ROOT_FP" done }}} The above script should produce the following output: {{{ _certs.g1._fp.cacert.org. 21599 IN TXT "root_X0F class3_X0E" Found roots: root_X0F class3_X0E Downloading root_X0F ... _url.root_X0F.g1._fp.cacert.org. 20558 IN TXT "http://www.cacert.org/certs/root_X0F.crt" _sha256.root_X0F.g1._fp.cacert.org. 20632 IN TXT "07EDBD824A4988CFEF4215DA20D48C2B41D71529D7C900F570926F277CC230C5" Found Certificate for Root "root_X0F": - CRT URL: http://www.cacert.org/certs/root_X0F.crt - CRT FP: 07EDBD824A4988CFEF4215DA20D48C2B41D71529D7C900F570926F277CC230C5 - DL FP: 07EDBD824A4988CFEF4215DA20D48C2B41D71529D7C900F570926F277CC230C5 Downloading class3_X0E ... _url.class3_X0E.g1._fp.cacert.org. 20651 IN TXT "http://www.cacert.org/certs/class3_X0E.crt" _sha256.class3_X0E.g1._fp.cacert.org. 20680 IN TXT "F6873D70D67596C2ACBA34401E69738B52701DD6AB06B49749BC55150936D544" Found Certificate for Root "class3_X0E": - CRT URL: http://www.cacert.org/certs/class3_X0E.crt - CRT FP: F6873D70D67596C2ACBA34401E69738B52701DD6AB06B49749BC55150936D544 - DL FP: F6873D70D67596C2ACBA34401E69738B52701DD6AB06B49749BC55150936D544 }}} [1] [http://askubuntu.com/questions/51367/how-do-i-configure-my-caching-nameserver-to-validate-dnssec] [2] [https://wiki.debian.org/DNSSEC] ---- . CategoryTutorials . CategoryStepByStep