001: // Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
002:
003: package org.xbill.DNS;
004:
005: import java.util.*;
006:
007: /**
008: * Constants and functions relating to DNSSEC (algorithm constants).
009: * DNSSEC provides authentication for DNS information. RRsets are
010: * signed by an appropriate key, and a SIG record is added to the set.
011: * A KEY record is obtained from DNS and used to validate the signature,
012: * The KEY record must also be validated or implicitly trusted - to
013: * validate a key requires a series of validations leading to a trusted
014: * key. The key must also be authorized to sign the data.
015: * @see SIGRecord
016: * @see KEYRecord
017: * @see RRset
018: *
019: * @author Brian Wellington
020: */
021:
022: public class DNSSEC {
023:
024: public static class Algorithm {
025: private Algorithm() {
026: }
027:
028: /** RSA/MD5 public key (deprecated) */
029: public static final int RSAMD5 = 1;
030:
031: /** Diffie Hellman key */
032: public static final int DH = 2;
033:
034: /** DSA public key */
035: public static final int DSA = 3;
036:
037: /** Elliptic Curve key */
038: public static final int ECC = 4;
039:
040: /** RSA/SHA1 public key */
041: public static final int RSASHA1 = 5;
042:
043: /** Indirect keys; the actual key is elsewhere. */
044: public static final int INDIRECT = 252;
045:
046: /** Private algorithm, specified by domain name */
047: public static final int PRIVATEDNS = 253;
048:
049: /** Private algorithm, specified by OID */
050: public static final int PRIVATEOID = 254;
051:
052: private static Mnemonic algs = new Mnemonic("DNSSEC algorithm",
053: Mnemonic.CASE_UPPER);
054:
055: static {
056: algs.setMaximum(0xFF);
057: algs.setNumericAllowed(true);
058:
059: algs.add(RSAMD5, "RSAMD5");
060: algs.add(DH, "DH");
061: algs.add(DSA, "DSA");
062: algs.add(ECC, "ECC");
063: algs.add(RSASHA1, "RSASHA1");
064: algs.add(INDIRECT, "INDIRECT");
065: algs.add(PRIVATEDNS, "PRIVATEDNS");
066: algs.add(PRIVATEOID, "PRIVATEOID");
067: }
068:
069: /**
070: * Converts an algorithm into its textual representation
071: */
072: public static String string(int alg) {
073: return algs.getText(alg);
074: }
075:
076: /**
077: * Converts a textual representation of an algorithm into its numeric
078: * code. Integers in the range 0..255 are also accepted.
079: * @param s The textual representation of the algorithm
080: * @return The algorithm code, or -1 on error.
081: */
082: public static int value(String s) {
083: return algs.getValue(s);
084: }
085: }
086:
087: public static final int RSAMD5 = Algorithm.RSAMD5;
088: public static final int RSA = Algorithm.RSAMD5;
089: public static final int DH = Algorithm.DH;
090: public static final int DSA = Algorithm.DSA;
091: public static final int RSASHA1 = Algorithm.RSASHA1;
092:
093: public static final int Failed = -1;
094: public static final int Insecure = 0;
095: public static final int Secure = 1;
096:
097: private DNSSEC() {
098: }
099:
100: private static void digestSIG(DNSOutput out, SIGBase sig) {
101: out.writeU16(sig.getTypeCovered());
102: out.writeU8(sig.getAlgorithm());
103: out.writeU8(sig.getLabels());
104: out.writeU32(sig.getOrigTTL());
105: out.writeU32(sig.getExpire().getTime() / 1000);
106: out.writeU32(sig.getTimeSigned().getTime() / 1000);
107: out.writeU16(sig.getFootprint());
108: sig.getSigner().toWireCanonical(out);
109: }
110:
111: /**
112: * Creates a byte array containing the concatenation of the fields of the
113: * SIG record and the RRsets to be signed/verified. This does not perform
114: * a cryptographic digest.
115: * @param sig The SIG record used to sign/verify the rrset.
116: * @param rrset The data to be signed/verified.
117: * @return The data to be cryptographically signed or verified.
118: */
119: public static byte[] digestRRset(RRSIGRecord sig, RRset rrset) {
120: DNSOutput out = new DNSOutput();
121: digestSIG(out, sig);
122:
123: int size = rrset.size();
124: Record[] records = new Record[size];
125:
126: Iterator it = rrset.rrs();
127: Name name = rrset.getName();
128: Name wild = null;
129: int sigLabels = sig.getLabels() + 1; // Add the root label back.
130: if (name.labels() > sigLabels)
131: wild = name.wild(name.labels() - sigLabels);
132: while (it.hasNext()) {
133: Record rec = (Record) it.next();
134: if (wild != null)
135: rec = rec.withName(wild);
136: records[--size] = rec;
137: }
138: Arrays.sort(records);
139: for (int i = 0; i < records.length; i++)
140: out.writeByteArray(records[i].toWireCanonical());
141: return out.toByteArray();
142: }
143:
144: /**
145: * Creates a byte array containing the concatenation of the fields of the
146: * SIG record and the message to be signed/verified. This does not perform
147: * a cryptographic digest.
148: * @param sig The SIG record used to sign/verify the rrset.
149: * @param msg The message to be signed/verified.
150: * @param previous If this is a response, the signature from the query.
151: * @return The data to be cryptographically signed or verified.
152: */
153: public static byte[] digestMessage(SIGRecord sig, Message msg,
154: byte[] previous) {
155: DNSOutput out = new DNSOutput();
156: digestSIG(out, sig);
157:
158: if (previous != null)
159: out.writeByteArray(previous);
160:
161: msg.toWire(out);
162: return out.toByteArray();
163: }
164:
165: }
|