+ /**
+ * Given a DS rrset and a DNSKEY rrset, match the DS to a DNSKEY and verify
+ * the DNSKEY rrset with that key.
+ *
+ * @param dnskey_rrset
+ * The DNSKEY rrset to match against. The security status of this
+ * rrset will be updated on a successful verification.
+ * @param ds_rrset
+ * The DS rrset to match with. This rrset must already be
+ * trusted.
+ *
+ * @return a KeyEntry. This will either contain the now trusted
+ * dnskey_rrset, a "null" key entry indicating that this DS
+ * rrset/DNSKEY pair indicate an secure end to the island of trust
+ * (i.e., unknown algorithms), or a "bad" KeyEntry if the dnskey
+ * rrset fails to verify. Note that the "null" response should
+ * generally only occur in a private algorithm scenario: normally
+ * this sort of thing is checked before fetching the matching DNSKEY
+ * rrset.
+ */
+ // public KeyEntry verifyNewDNSKEYs(SRRset dnskey_rrset, SRRset ds_rrset)
+ // {
+ // if (!dnskey_rrset.getName().equals(ds_rrset.getName()))
+ // {
+ // // log.debug("DNSKEY RRset did not match DS RRset by name!");
+ // return KeyEntry
+ // .newBadKeyEntry(ds_rrset.getName(), ds_rrset.getDClass());
+ // }
+ //
+ // // as long as this is false, we can consider this DS rrset to be
+ // // equivalent to no DS rrset.
+ // boolean hasUsefulDS = false;
+ //
+ // for (Iterator i = ds_rrset.rrs(); i.hasNext();)
+ // {
+ // DSRecord ds = (DSRecord) i.next();
+ //
+ // // Check to see if we can understand this DS.
+ // if (!supportsDigestID(ds.getDigestID())
+ // || !mVerifier.supportsAlgorithm(ds.getAlgorithm()))
+ // {
+ // continue;
+ // }
+ //
+ // // Once we see a single DS with a known digestID and algorithm, we
+ // // cannot return INSECURE (with a "null" KeyEntry).
+ // hasUsefulDS = true;
+ //
+ // DNSKEY : for (Iterator j = dnskey_rrset.rrs(); j.hasNext();)
+ // {
+ // DNSKEYRecord dnskey = (DNSKEYRecord) j.next();
+ //
+ // // Skip DNSKEYs that don't match the basic criteria.
+ // if (ds.getFootprint() != dnskey.getFootprint()
+ // || ds.getAlgorithm() != dnskey.getAlgorithm())
+ // {
+ // continue;
+ // }
+ //
+ // // Convert the candidate DNSKEY into a hash using the same DS hash
+ // // algorithm.
+ // byte[] key_hash = calculateDSHash(dnskey, ds.getDigestID());
+ // byte[] ds_hash = ds.getDigest();
+ //
+ // // see if there is a length mismatch (unlikely)
+ // if (key_hash.length != ds_hash.length)
+ // {
+ // continue DNSKEY;
+ // }
+ //
+ // for (int k = 0; k < key_hash.length; k++)
+ // {
+ // if (key_hash[k] != ds_hash[k]) continue DNSKEY;
+ // }
+ //
+ // // Otherwise, we have a match! Make sure that the DNSKEY verifies
+ // // *with this key*.
+ // byte res = mVerifier.verify(dnskey_rrset, dnskey);
+ // if (res == SecurityStatus.SECURE)
+ // {
+ // // log.trace("DS matched DNSKEY.");
+ // dnskey_rrset.setSecurityStatus(SecurityStatus.SECURE);
+ // return KeyEntry.newKeyEntry(dnskey_rrset);
+ // }
+ // // If it didn't validate with the DNSKEY, try the next one!
+ // }
+ // }
+ //
+ // // None of the DS's worked out.
+ //
+ // // If no DSs were understandable, then this is OK.
+ // if (!hasUsefulDS)
+ // {
+ // //
+ // log.debug("No usuable DS records were found -- treating as insecure.");
+ // return KeyEntry.newNullKeyEntry(ds_rrset.getName(), ds_rrset
+ // .getDClass(), ds_rrset.getTTL());
+ // }
+ // // If any were understandable, then it is bad.
+ // // log.debug("Failed to match any usable DS to a DNSKEY.");
+ // return KeyEntry.newBadKeyEntry(ds_rrset.getName(), ds_rrset.getDClass());
+ // }
+ /**
+ * Given a DNSKEY record, generate the DS record from it.
+ *
+ * @param keyrec
+ * the DNSKEY record in question.
+ * @param ds_alg
+ * The DS digest algorithm in use.
+ * @return the corresponding {@link org.xbill.DNS.DSRecord}
+ */
+ public static byte[] calculateDSHash(DNSKEYRecord keyrec, int ds_alg) {
+ DNSOutput os = new DNSOutput();
+
+ os.writeByteArray(keyrec.getName().toWireCanonical());
+ os.writeByteArray(keyrec.rdataToWireCanonical());
+
+ try {
+ MessageDigest md = null;
+ switch (ds_alg) {
+ case DSRecord.SHA1_DIGEST_ID:
+ md = MessageDigest.getInstance("SHA");
+ return md.digest(os.toByteArray());
+ case DSRecord.SHA256_DIGEST_ID:
+ md = MessageDigest.getInstance("SHA256");
+ return md.digest(os.toByteArray());
+ default:
+ // st_log.warn("Unknown DS algorithm: " + ds_alg);
+ return null;
+ }
+
+ } catch (NoSuchAlgorithmException e) {
+ // st_log.error("Error using DS algorithm: " + ds_alg, e);
+ return null;
+ }