// Copyright (c) 1999-2010 Brian Wellington (bwelling@xbill.org)

package org.xbill.DNS;

import java.io.*;
import java.math.*;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
import java.util.*;

/**
 * Constants and methods relating to DNSSEC.
 *
 * DNSSEC provides authentication for DNS information.
 * @see RRSIGRecord
 * @see DNSKEYRecord
 * @see RRset
 *
 * @author Brian Wellington
 */

public class DNSSEC {

public static class Algorithm {
	private Algorithm() {}

	/** RSA/MD5 public key (deprecated) */
	public static final int RSAMD5 = 1;

	/** Diffie Hellman key */
	public static final int DH = 2;

	/** DSA public key */
	public static final int DSA = 3;

	/** RSA/SHA1 public key */
	public static final int RSASHA1 = 5;

	/** DSA/SHA1, NSEC3-aware public key */
	public static final int DSA_NSEC3_SHA1 = 6;

	/** RSA/SHA1, NSEC3-aware public key */
	public static final int RSA_NSEC3_SHA1 = 7;

	/** RSA/SHA256 public key */
	public static final int RSASHA256 = 8;

	/** RSA/SHA512 public key */
	public static final int RSASHA512 = 10;

	/** ECDSA Curve P-256 with SHA-256 public key **/
	public static final int ECDSAP256SHA256 = 13;

	/** ECDSA Curve P-384 with SHA-384 public key **/
	public static final int ECDSAP384SHA384 = 14;

	/** Indirect keys; the actual key is elsewhere. */
	public static final int INDIRECT = 252;

	/** Private algorithm, specified by domain name */
	public static final int PRIVATEDNS = 253;

	/** Private algorithm, specified by OID */
	public static final int PRIVATEOID = 254;

	private static Mnemonic algs = new Mnemonic("DNSSEC algorithm",
						    Mnemonic.CASE_UPPER);

	static {
		algs.setMaximum(0xFF);
		algs.setNumericAllowed(true);

		algs.add(RSAMD5, "RSAMD5");
		algs.add(DH, "DH");
		algs.add(DSA, "DSA");
		algs.add(RSASHA1, "RSASHA1");
		algs.add(DSA_NSEC3_SHA1, "DSA-NSEC3-SHA1");
		algs.add(RSA_NSEC3_SHA1, "RSA-NSEC3-SHA1");
		algs.add(RSASHA256, "RSASHA256");
		algs.add(RSASHA512, "RSASHA512");
		algs.add(ECDSAP256SHA256, "ECDSAP256SHA256");
		algs.add(ECDSAP384SHA384, "ECDSAP384SHA384");
		algs.add(INDIRECT, "INDIRECT");
		algs.add(PRIVATEDNS, "PRIVATEDNS");
		algs.add(PRIVATEOID, "PRIVATEOID");
	}

	/**
	 * Converts an algorithm into its textual representation
	 */
	public static String
	string(int alg) {
		return algs.getText(alg);
	}

	/**
	 * Converts a textual representation of an algorithm into its numeric
	 * code.  Integers in the range 0..255 are also accepted.
	 * @param s The textual representation of the algorithm
	 * @return The algorithm code, or -1 on error.
	 */
	public static int
	value(String s) {
		return algs.getValue(s);
	}
}

private
DNSSEC() { }

private static void
digestSIG(DNSOutput out, SIGBase sig) {
	out.writeU16(sig.getTypeCovered());
	out.writeU8(sig.getAlgorithm());
	out.writeU8(sig.getLabels());
	out.writeU32(sig.getOrigTTL());
	out.writeU32(sig.getExpire().getTime() / 1000);
	out.writeU32(sig.getTimeSigned().getTime() / 1000);
	out.writeU16(sig.getFootprint());
	sig.getSigner().toWireCanonical(out);
}

/**
 * Creates a byte array containing the concatenation of the fields of the
 * SIG record and the RRsets to be signed/verified.  This does not perform
 * a cryptographic digest.
 * @param rrsig The RRSIG record used to sign/verify the rrset.
 * @param rrset The data to be signed/verified.
 * @return The data to be cryptographically signed or verified.
 */
public static byte []
digestRRset(RRSIGRecord rrsig, RRset rrset) {
	DNSOutput out = new DNSOutput();
	digestSIG(out, rrsig);

	int size = rrset.size();
	Record [] records = new Record[size];

	Iterator it = rrset.rrs();
	Name name = rrset.getName();
	Name wild = null;
	int sigLabels = rrsig.getLabels() + 1; // Add the root label back.
	if (name.labels() > sigLabels)
		wild = name.wild(name.labels() - sigLabels);
	while (it.hasNext())
		records[--size] = (Record) it.next();
	Arrays.sort(records);

	DNSOutput header = new DNSOutput();
	if (wild != null)
		wild.toWireCanonical(header);
	else
		name.toWireCanonical(header);
	header.writeU16(rrset.getType());
	header.writeU16(rrset.getDClass());
	header.writeU32(rrsig.getOrigTTL());
	for (int i = 0; i < records.length; i++) {
		out.writeByteArray(header.toByteArray());
		int lengthPosition = out.current();
		out.writeU16(0);
		out.writeByteArray(records[i].rdataToWireCanonical());
		int rrlength = out.current() - lengthPosition - 2;
		out.save();
		out.jump(lengthPosition);
		out.writeU16(rrlength);
		out.restore();
	}
	return out.toByteArray();
}

/**
 * Creates a byte array containing the concatenation of the fields of the
 * SIG(0) record and the message to be signed.  This does not perform
 * a cryptographic digest.
 * @param sig The SIG record used to sign the rrset.
 * @param msg The message to be signed.
 * @param previous If this is a response, the signature from the query.
 * @return The data to be cryptographically signed.
 */
public static byte []
digestMessage(SIGRecord sig, Message msg, byte [] previous) {
	DNSOutput out = new DNSOutput();
	digestSIG(out, sig);

	if (previous != null)
		out.writeByteArray(previous);

	msg.toWire(out);
	return out.toByteArray();
}

/**
 * A DNSSEC exception.
 */
public static class DNSSECException extends Exception {
	DNSSECException(String s) {
		super(s);
	}
}

/**
 * An algorithm is unsupported by this DNSSEC implementation.
 */
public static class UnsupportedAlgorithmException extends DNSSECException {
	UnsupportedAlgorithmException(int alg) {
		super("Unsupported algorithm: " + alg);
	}
}

/**
 * The cryptographic data in a DNSSEC key is malformed.
 */
public static class MalformedKeyException extends DNSSECException {
	MalformedKeyException(KEYBase rec) {
		super("Invalid key data: " + rec.rdataToString());
	}
}

/**
 * A DNSSEC verification failed because fields in the DNSKEY and RRSIG records
 * do not match.
 */
public static class KeyMismatchException extends DNSSECException {
	private KEYBase key;
	private SIGBase sig;

	KeyMismatchException(KEYBase key, SIGBase sig) {
		super("key " +
		      key.getName() + "/" +
		      DNSSEC.Algorithm.string(key.getAlgorithm()) + "/" +
		      key.getFootprint() + " " +
		      "does not match signature " +
		      sig.getSigner() + "/" +
		      DNSSEC.Algorithm.string(sig.getAlgorithm()) + "/" +
		      sig.getFootprint());
	}
}

/**
 * A DNSSEC verification failed because the signature has expired.
 */
public static class SignatureExpiredException extends DNSSECException {
	private Date when, now;

	SignatureExpiredException(Date when, Date now) {
		super("signature expired");
		this.when = when;
		this.now = now;
	}

	/**
	 * @return When the signature expired
	 */
	public Date
	getExpiration() {
		return when;
	}

	/**
	 * @return When the verification was attempted
	 */
	public Date
	getVerifyTime() {
		return now;
	}
}

/**
 * A DNSSEC verification failed because the signature has not yet become valid.
 */
public static class SignatureNotYetValidException extends DNSSECException {
	private Date when, now;

	SignatureNotYetValidException(Date when, Date now) {
		super("signature is not yet valid");
		this.when = when;
		this.now = now;
	}

	/**
	 * @return When the signature will become valid
	 */
	public Date
	getExpiration() {
		return when;
	}

	/**
	 * @return When the verification was attempted
	 */
	public Date
	getVerifyTime() {
		return now;
	}
}

/**
 * A DNSSEC verification failed because the cryptographic signature
 * verification failed.
 */
public static class SignatureVerificationException extends DNSSECException {
	SignatureVerificationException() {
		super("signature verification failed");
	}
}

/**
 * The key data provided is inconsistent.
 */
public static class IncompatibleKeyException extends IllegalArgumentException {
	IncompatibleKeyException() {
		super("incompatible keys");
	}
}

private static int
BigIntegerLength(BigInteger i) {
	return (i.bitLength() + 7) / 8;
}

private static BigInteger
readBigInteger(DNSInput in, int len) throws IOException {
	byte [] b = in.readByteArray(len);
	return new BigInteger(1, b);
}

private static BigInteger
readBigInteger(DNSInput in) {
	byte [] b = in.readByteArray();
	return new BigInteger(1, b);
}

private static void
writeBigInteger(DNSOutput out, BigInteger val) {
	byte [] b = val.toByteArray();
	if (b[0] == 0)
		out.writeByteArray(b, 1, b.length - 1);
	else
		out.writeByteArray(b);
}

private static PublicKey
toRSAPublicKey(KEYBase r) throws IOException, GeneralSecurityException {
	DNSInput in = new DNSInput(r.getKey());
	int exponentLength = in.readU8();
	if (exponentLength == 0)
		exponentLength = in.readU16();
	BigInteger exponent = readBigInteger(in, exponentLength);
	BigInteger modulus = readBigInteger(in);

	KeyFactory factory = KeyFactory.getInstance("RSA");
	return factory.generatePublic(new RSAPublicKeySpec(modulus, exponent));
}

private static PublicKey
toDSAPublicKey(KEYBase r) throws IOException, GeneralSecurityException,
	MalformedKeyException
{
	DNSInput in = new DNSInput(r.getKey());

	int t = in.readU8();
	if (t > 8)
		throw new MalformedKeyException(r);

	BigInteger q = readBigInteger(in, 20);
	BigInteger p = readBigInteger(in, 64 + t*8);
	BigInteger g = readBigInteger(in, 64 + t*8);
	BigInteger y = readBigInteger(in, 64 + t*8);

	KeyFactory factory = KeyFactory.getInstance("DSA");
	return factory.generatePublic(new DSAPublicKeySpec(y, p, q, g));
}

private static class ECKeyInfo {
	int length;
	public BigInteger p, a, b, gx, gy, n;
	EllipticCurve curve;
	ECParameterSpec spec;

	ECKeyInfo(int length, String p_str, String a_str, String b_str,
		  String gx_str, String gy_str, String n_str)
	{
		this.length = length;
		p = new BigInteger(p_str, 16);
		a = new BigInteger(a_str, 16);
		b = new BigInteger(b_str, 16);
		gx = new BigInteger(gx_str, 16);
		gy = new BigInteger(gy_str, 16);
		n = new BigInteger(n_str, 16);
		curve = new EllipticCurve(new ECFieldFp(p), a, b);
		spec = new ECParameterSpec(curve, new ECPoint(gx, gy), n, 1);
	}
}

// RFC 5114 Section 2.6
private static final ECKeyInfo ECDSA_P256 = new ECKeyInfo(32,
	"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
	"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
	"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
	"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
	"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
	"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");

// RFC 5114 Section 2.7
private static final ECKeyInfo ECDSA_P384 = new ECKeyInfo(48,
	"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
	"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
	"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
	"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
	"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
	"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973");

private static PublicKey
toECDSAPublicKey(KEYBase r, ECKeyInfo keyinfo) throws IOException,
	GeneralSecurityException, MalformedKeyException
{
	DNSInput in = new DNSInput(r.getKey());

	// RFC 6605 Section 4
	BigInteger x = readBigInteger(in, keyinfo.length);
	BigInteger y = readBigInteger(in, keyinfo.length);
	ECPoint q = new ECPoint(x, y);

	KeyFactory factory = KeyFactory.getInstance("EC");
	return factory.generatePublic(new ECPublicKeySpec(q, keyinfo.spec));
}

/** Converts a KEY/DNSKEY record into a PublicKey */
static PublicKey
toPublicKey(KEYBase r) throws DNSSECException {
	int alg = r.getAlgorithm();
	try {
		switch (alg) {
		case Algorithm.RSAMD5:
		case Algorithm.RSASHA1:
		case Algorithm.RSA_NSEC3_SHA1:
		case Algorithm.RSASHA256:
		case Algorithm.RSASHA512:
			return toRSAPublicKey(r);
		case Algorithm.DSA:
		case Algorithm.DSA_NSEC3_SHA1:
			return toDSAPublicKey(r);
		case Algorithm.ECDSAP256SHA256:
			return toECDSAPublicKey(r, ECDSA_P256);
		case Algorithm.ECDSAP384SHA384:
			return toECDSAPublicKey(r, ECDSA_P384);
		default:
			throw new UnsupportedAlgorithmException(alg);
		}
	}
	catch (IOException e) {
		throw new MalformedKeyException(r);
	}
	catch (GeneralSecurityException e) {
		throw new DNSSECException(e.toString());
	}
}

private static byte []
fromRSAPublicKey(RSAPublicKey key) {
	DNSOutput out = new DNSOutput();
	BigInteger exponent = key.getPublicExponent();
	BigInteger modulus = key.getModulus();
	int exponentLength = BigIntegerLength(exponent);

	if (exponentLength < 256)
		out.writeU8(exponentLength);
	else {
		out.writeU8(0);
		out.writeU16(exponentLength);
	}
	writeBigInteger(out, exponent);
	writeBigInteger(out, modulus);

	return out.toByteArray();
}

private static byte []
fromDSAPublicKey(DSAPublicKey key) {
	DNSOutput out = new DNSOutput();
	BigInteger q = key.getParams().getQ();
	BigInteger p = key.getParams().getP();
	BigInteger g = key.getParams().getG();
	BigInteger y = key.getY();
	int t = (p.toByteArray().length - 64) / 8;

	out.writeU8(t);
	writeBigInteger(out, q);
	writeBigInteger(out, p);
	writeBigInteger(out, g);
	writeBigInteger(out, y);

	return out.toByteArray();
}

private static byte []
fromECDSAPublicKey(ECPublicKey key) {
	DNSOutput out = new DNSOutput();

	BigInteger x = key.getW().getAffineX();
	BigInteger y = key.getW().getAffineY();

	writeBigInteger(out, x);
	writeBigInteger(out, y);

	return out.toByteArray();
}

/** Builds a DNSKEY record from a PublicKey */
static byte []
fromPublicKey(PublicKey key, int alg) throws DNSSECException
{

	switch (alg) {
	case Algorithm.RSAMD5:
	case Algorithm.RSASHA1:
	case Algorithm.RSA_NSEC3_SHA1:
	case Algorithm.RSASHA256:
	case Algorithm.RSASHA512:
		if (! (key instanceof RSAPublicKey))
			throw new IncompatibleKeyException();
		return fromRSAPublicKey((RSAPublicKey) key);
	case Algorithm.DSA:
	case Algorithm.DSA_NSEC3_SHA1:
		if (! (key instanceof DSAPublicKey))
			throw new IncompatibleKeyException();
		return fromDSAPublicKey((DSAPublicKey) key);
	case Algorithm.ECDSAP256SHA256:
	case Algorithm.ECDSAP384SHA384:
		if (! (key instanceof ECPublicKey))
			throw new IncompatibleKeyException();
		return fromECDSAPublicKey((ECPublicKey) key);
	default:
		throw new UnsupportedAlgorithmException(alg);
	}
}

/**
 * Convert an algorithm number to the corresponding JCA string.
 * @param alg The algorithm number.
 * @throws UnsupportedAlgorithmException The algorithm is unknown.
 */
public static String
algString(int alg) throws UnsupportedAlgorithmException {
	switch (alg) {
	case Algorithm.RSAMD5:
		return "MD5withRSA";
	case Algorithm.DSA:
	case Algorithm.DSA_NSEC3_SHA1:
		return "SHA1withDSA";
	case Algorithm.RSASHA1:
	case Algorithm.RSA_NSEC3_SHA1:
		return "SHA1withRSA";
	case Algorithm.RSASHA256:
		return "SHA256withRSA";
	case Algorithm.RSASHA512:
		return "SHA512withRSA";
	case Algorithm.ECDSAP256SHA256:
		return "SHA256withECDSA";
	case Algorithm.ECDSAP384SHA384:
		return "SHA384withECDSA";
	default:
		throw new UnsupportedAlgorithmException(alg);
	}
}

private static final int ASN1_SEQ = 0x30;
private static final int ASN1_INT = 0x2;

private static final int DSA_LEN = 20;

private static byte []
DSASignaturefromDNS(byte [] dns) throws DNSSECException, IOException {
	if (dns.length != 1 + DSA_LEN * 2)
		throw new SignatureVerificationException();

	DNSInput in = new DNSInput(dns);
	DNSOutput out = new DNSOutput();

	int t = in.readU8();

	byte [] r = in.readByteArray(DSA_LEN);
	int rlen = DSA_LEN;
	if (r[0] < 0)
		rlen++;

	byte [] s = in.readByteArray(DSA_LEN);
        int slen = DSA_LEN;
        if (s[0] < 0)
                slen++;

	out.writeU8(ASN1_SEQ);
	out.writeU8(rlen + slen + 4);

	out.writeU8(ASN1_INT);
	out.writeU8(rlen);
	if (rlen > DSA_LEN)
		out.writeU8(0);
	out.writeByteArray(r);

	out.writeU8(ASN1_INT);
	out.writeU8(slen);
	if (slen > DSA_LEN)
		out.writeU8(0);
	out.writeByteArray(s);

	return out.toByteArray();
}

private static byte []
DSASignaturetoDNS(byte [] signature, int t) throws IOException {
	DNSInput in = new DNSInput(signature);
	DNSOutput out = new DNSOutput();

	out.writeU8(t);

	int tmp = in.readU8();
	if (tmp != ASN1_SEQ)
		throw new IOException();
	int seqlen = in.readU8();

	tmp = in.readU8();
	if (tmp != ASN1_INT)
		throw new IOException();
	int rlen = in.readU8();
	if (rlen == DSA_LEN + 1) {
		if (in.readU8() != 0)
			throw new IOException();
	} else if (rlen != DSA_LEN)
		throw new IOException();
	byte [] bytes = in.readByteArray(DSA_LEN);
	out.writeByteArray(bytes);

	tmp = in.readU8();
	if (tmp != ASN1_INT)
		throw new IOException();
	int slen = in.readU8();
	if (slen == DSA_LEN + 1) {
		if (in.readU8() != 0)
			throw new IOException();
	} else if (slen != DSA_LEN)
		throw new IOException();
	bytes = in.readByteArray(DSA_LEN);
	out.writeByteArray(bytes);

	return out.toByteArray();
}

private static byte []
ECDSASignaturefromDNS(byte [] signature, ECKeyInfo keyinfo)
	throws DNSSECException, IOException
{
	if (signature.length != keyinfo.length * 2)
		throw new SignatureVerificationException();

	DNSInput in = new DNSInput(signature);
	DNSOutput out = new DNSOutput();

	byte [] r = in.readByteArray(keyinfo.length);
	int rlen = keyinfo.length;
	if (r[0] < 0)
		rlen++;

	byte [] s = in.readByteArray(keyinfo.length);
	int slen = keyinfo.length;
	if (s[0] < 0)
		slen++;

	out.writeU8(ASN1_SEQ);
	out.writeU8(rlen + slen + 4);

	out.writeU8(ASN1_INT);
	out.writeU8(rlen);
	if (rlen > keyinfo.length)
		out.writeU8(0);
	out.writeByteArray(r);

	out.writeU8(ASN1_INT);
	out.writeU8(slen);
	if (slen > keyinfo.length)
		out.writeU8(0);
	out.writeByteArray(s);

	return out.toByteArray();
}

private static byte []
ECDSASignaturetoDNS(byte [] signature, ECKeyInfo keyinfo) throws IOException {
	DNSInput in = new DNSInput(signature);
	DNSOutput out = new DNSOutput();

	int tmp = in.readU8();
	if (tmp != ASN1_SEQ)
		throw new IOException();
	int seqlen = in.readU8();

	tmp = in.readU8();
	if (tmp != ASN1_INT)
		throw new IOException();
	int rlen = in.readU8();
	if (rlen == keyinfo.length + 1) {
		if (in.readU8() != 0)
			throw new IOException();
	} else if (rlen != keyinfo.length)
		throw new IOException();
	byte[] bytes = in.readByteArray(keyinfo.length);
	out.writeByteArray(bytes);

	tmp = in.readU8();
	if (tmp != ASN1_INT)
		throw new IOException();
	int slen = in.readU8();
	if (slen == keyinfo.length + 1) {
		if (in.readU8() != 0)
			throw new IOException();
	} else if (slen != keyinfo.length)
		throw new IOException();
	bytes = in.readByteArray(keyinfo.length);
	out.writeByteArray(bytes);

	return out.toByteArray();
}

private static void
verify(PublicKey key, int alg, byte [] data, byte [] signature)
throws DNSSECException
{
	if (key instanceof DSAPublicKey) {
		try {
			signature = DSASignaturefromDNS(signature);
		}
		catch (IOException e) {
			throw new IllegalStateException();
		}
	} else if (key instanceof ECPublicKey) {
		try {
			switch (alg) {
			case Algorithm.ECDSAP256SHA256:
				signature = ECDSASignaturefromDNS(signature,
								  ECDSA_P256);
				break;
			case Algorithm.ECDSAP384SHA384:
				signature = ECDSASignaturefromDNS(signature,
								  ECDSA_P384);
				break;
			default:
				throw new UnsupportedAlgorithmException(alg);
			}
		}
		catch (IOException e) {
			throw new IllegalStateException();
		}
	}

	try {
		Signature s = Signature.getInstance(algString(alg));
		s.initVerify(key);
		s.update(data);
		if (!s.verify(signature))
			throw new SignatureVerificationException();
	}
	catch (GeneralSecurityException e) {
		throw new DNSSECException(e.toString());
	}
}

private static boolean
matches(SIGBase sig, KEYBase key)
{
	return (key.getAlgorithm() == sig.getAlgorithm() &&
		key.getFootprint() == sig.getFootprint() &&
		key.getName().equals(sig.getSigner()));
}

/**
 * Verify a DNSSEC signature.
 * @param rrset The data to be verified.
 * @param rrsig The RRSIG record containing the signature.
 * @param key The DNSKEY record to verify the signature with.
 * @throws UnsupportedAlgorithmException The algorithm is unknown
 * @throws MalformedKeyException The key is malformed
 * @throws KeyMismatchException The key and signature do not match
 * @throws SignatureExpiredException The signature has expired
 * @throws SignatureNotYetValidException The signature is not yet valid
 * @throws SignatureVerificationException The signature does not verify.
 * @throws DNSSECException Some other error occurred.
 */
public static void
verify(RRset rrset, RRSIGRecord rrsig, DNSKEYRecord key) throws DNSSECException
{
	if (!matches(rrsig, key))
		throw new KeyMismatchException(key, rrsig);

	Date now = new Date();
	if (now.compareTo(rrsig.getExpire()) > 0)
		throw new SignatureExpiredException(rrsig.getExpire(), now);
	if (now.compareTo(rrsig.getTimeSigned()) < 0)
		throw new SignatureNotYetValidException(rrsig.getTimeSigned(),
							now);

	verify(key.getPublicKey(), rrsig.getAlgorithm(),
	       digestRRset(rrsig, rrset), rrsig.getSignature());
}

private static byte []
sign(PrivateKey privkey, PublicKey pubkey, int alg, byte [] data,
     String provider) throws DNSSECException
{
	byte [] signature;
	try {
		Signature s;
		if (provider != null)
			s = Signature.getInstance(algString(alg), provider);
		else
			s = Signature.getInstance(algString(alg));
		s.initSign(privkey);
		s.update(data);
		signature = s.sign();
	}
	catch (GeneralSecurityException e) {
		throw new DNSSECException(e.toString());
	}

	if (pubkey instanceof DSAPublicKey) {
		try {
			DSAPublicKey dsa = (DSAPublicKey) pubkey;
			BigInteger P = dsa.getParams().getP();
			int t = (BigIntegerLength(P) - 64) / 8;
			signature = DSASignaturetoDNS(signature, t);
		}
		catch (IOException e) {
			throw new IllegalStateException();
		}
	} else if (pubkey instanceof ECPublicKey) {
		try {
			switch (alg) {
			case Algorithm.ECDSAP256SHA256:
				signature = ECDSASignaturetoDNS(signature,
								ECDSA_P256);
				break;
			case Algorithm.ECDSAP384SHA384:
				signature = ECDSASignaturetoDNS(signature,
								ECDSA_P384);
				break;
			default:
				throw new UnsupportedAlgorithmException(alg);
			}
		}
		catch (IOException e) {
			throw new IllegalStateException();
		}
	}

	return signature;
}
static void
checkAlgorithm(PrivateKey key, int alg) throws UnsupportedAlgorithmException
{
	switch (alg) {
	case Algorithm.RSAMD5:
	case Algorithm.RSASHA1:
	case Algorithm.RSA_NSEC3_SHA1:
	case Algorithm.RSASHA256:
	case Algorithm.RSASHA512:
		if (! (key instanceof RSAPrivateKey))
			throw new IncompatibleKeyException();
		break;
	case Algorithm.DSA:
	case Algorithm.DSA_NSEC3_SHA1:
		if (! (key instanceof DSAPrivateKey))
			throw new IncompatibleKeyException();
		break;
	case Algorithm.ECDSAP256SHA256:
	case Algorithm.ECDSAP384SHA384:
		if (! (key instanceof ECPrivateKey))
			throw new IncompatibleKeyException();
		break;
	default:
		throw new UnsupportedAlgorithmException(alg);
	}
}

/**
 * Generate a DNSSEC signature.  key and privateKey must refer to the
 * same underlying cryptographic key.
 * @param rrset The data to be signed
 * @param key The DNSKEY record to use as part of signing
 * @param privkey The PrivateKey to use when signing
 * @param inception The time at which the signatures should become valid
 * @param expiration The time at which the signatures should expire
 * @throws UnsupportedAlgorithmException The algorithm is unknown
 * @throws MalformedKeyException The key is malformed
 * @throws DNSSECException Some other error occurred.
 * @return The generated signature
 */
public static RRSIGRecord
sign(RRset rrset, DNSKEYRecord key, PrivateKey privkey,
     Date inception, Date expiration) throws DNSSECException
{
	return sign(rrset, key, privkey, inception, expiration, null);
}

/**
 * Generate a DNSSEC signature.  key and privateKey must refer to the
 * same underlying cryptographic key.
 * @param rrset The data to be signed
 * @param key The DNSKEY record to use as part of signing
 * @param privkey The PrivateKey to use when signing
 * @param inception The time at which the signatures should become valid
 * @param expiration The time at which the signatures should expire
 * @param provider The name of the JCA provider.  If non-null, it will be
 * passed to JCA getInstance() methods.
 * @throws UnsupportedAlgorithmException The algorithm is unknown
 * @throws MalformedKeyException The key is malformed
 * @throws DNSSECException Some other error occurred.
 * @return The generated signature
 */
public static RRSIGRecord
sign(RRset rrset, DNSKEYRecord key, PrivateKey privkey,
     Date inception, Date expiration, String provider) throws DNSSECException
{
	int alg = key.getAlgorithm();
	checkAlgorithm(privkey, alg);

	RRSIGRecord rrsig = new RRSIGRecord(rrset.getName(), rrset.getDClass(),
					    rrset.getTTL(), rrset.getType(),
					    alg, rrset.getTTL(),
					    expiration, inception,
					    key.getFootprint(),
					    key.getName(), null);

	rrsig.setSignature(sign(privkey, key.getPublicKey(), alg,
				digestRRset(rrsig, rrset), provider));
	return rrsig;
}

static SIGRecord
signMessage(Message message, SIGRecord previous, KEYRecord key,
	    PrivateKey privkey, Date inception, Date expiration)
	throws DNSSECException
{
	int alg = key.getAlgorithm();
	checkAlgorithm(privkey, alg);

	SIGRecord sig = new SIGRecord(Name.root, DClass.ANY, 0, 0,
					    alg, 0, expiration, inception,
					    key.getFootprint(),
					    key.getName(), null);
	DNSOutput out = new DNSOutput();
	digestSIG(out, sig);
	if (previous != null)
		out.writeByteArray(previous.getSignature());
	message.toWire(out);

	sig.setSignature(sign(privkey, key.getPublicKey(),
			      alg, out.toByteArray(), null));
	return sig;
}

static void
verifyMessage(Message message, byte [] bytes, SIGRecord sig, SIGRecord previous,
	      KEYRecord key) throws DNSSECException
{
	if (!matches(sig, key))
		throw new KeyMismatchException(key, sig);

	Date now = new Date();

	if (now.compareTo(sig.getExpire()) > 0)
		throw new SignatureExpiredException(sig.getExpire(), now);
	if (now.compareTo(sig.getTimeSigned()) < 0)
		throw new SignatureNotYetValidException(sig.getTimeSigned(),
							now);

	DNSOutput out = new DNSOutput();
	digestSIG(out, sig);
	if (previous != null)
		out.writeByteArray(previous.getSignature());

	Header header = (Header) message.getHeader().clone();
	header.decCount(Section.ADDITIONAL);
	out.writeByteArray(header.toWire());

	out.writeByteArray(bytes, Header.LENGTH,
			   message.sig0start - Header.LENGTH);

	verify(key.getPublicKey(), sig.getAlgorithm(),
	       out.toByteArray(), sig.getSignature());
}

/**
 * Generate the digest value for a DS key
 * @param key Which is covered by the DS record
 * @param digestid The type of digest
 * @return The digest value as an array of bytes
 */
static byte []
generateDSDigest(DNSKEYRecord key, int digestid)
{
	MessageDigest digest;
	try {
		switch (digestid) {
		case DSRecord.Digest.SHA1:
			digest = MessageDigest.getInstance("sha-1");
			break;
		case DSRecord.Digest.SHA256:
			digest = MessageDigest.getInstance("sha-256");
			break;
		case DSRecord.Digest.SHA384:
			digest = MessageDigest.getInstance("sha-384");
			break;
		default:
			throw new IllegalArgumentException(
					"unknown DS digest type " + digestid);
		}
	}
	catch (NoSuchAlgorithmException e) {
		throw new IllegalStateException("no message digest support");
	}
	digest.update(key.getName().toWire());
	digest.update(key.rdataToWireCanonical());
	return digest.digest();
}

}
