All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xbill.DNS.security.KEYConverter Maven / Gradle / Ivy

There is a newer version: 2.0-beta-7
Show newest version
// Copyright (c) 1999-2004 Brian Wellington ([email protected])

package org.xbill.DNS.security;

import org.xbill.DNS.*;

import javax.crypto.interfaces.DHPublicKey;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.PublicKey;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPublicKey;

/**
 * Routines to convert between a DNS KEY record and a Java PublicKey.
 *
 * @author Brian Wellington
 */

public class KEYConverter {

private static final BigInteger DHPRIME768 = new BigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", 16);
private static final BigInteger DHPRIME1024 = new BigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16);
private static final BigInteger TWO = new BigInteger("2", 16);

static int
BigIntegerLength(BigInteger i) {
	byte [] b = i.toByteArray();
	return (b[0] == 0 ? b.length - 1 : b.length);
}

static BigInteger
readBigInteger(DataInputStream in, int len) throws IOException {
	byte [] b = new byte[len];
	int n = in.read(b);
	if (n < len)
		throw new IOException("end of input");
	return new BigInteger(1, b);
}

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

static void
writeShort(ByteArrayOutputStream out, int i) {
	out.write((i >> 8) & 0xFF);
	out.write(i & 0xFF);
}

static RSAPublicKey
parseRSA(DataInputStream in) throws IOException {
	int exponentLength = in.readUnsignedByte();
	if (exponentLength == 0)
		exponentLength = in.readUnsignedShort();
	BigInteger exponent = readBigInteger(in, exponentLength);

	int modulusLength = in.available();
	BigInteger modulus = readBigInteger(in, modulusLength);

	RSAPublicKey rsa = new RSAPubKey(modulus, exponent);
	return rsa;
}

static DHPublicKey
parseDH(DataInputStream in) throws IOException {
	int special = 0;
	int pLength = in.readUnsignedShort();
	if (pLength < 16 && pLength != 1 && pLength != 2)
		return null;
	BigInteger p;
	if (pLength == 1 || pLength == 2) {
		if (pLength == 1)
			special = in.readUnsignedByte();
		else
			special = in.readUnsignedShort();
		if (special != 1 && special != 2)
			return null;
		if (special == 1)
			p = DHPRIME768;
		else
			p = DHPRIME1024;
	}
	else
		p = readBigInteger(in, pLength);

	int gLength = in.readUnsignedShort();
	BigInteger g;
	if (gLength == 0) {
		if (special != 0)
			g = TWO;
		else
			return null;
	}
	else
		g = readBigInteger(in, gLength);

	int yLength = in.readUnsignedShort();
	BigInteger y = readBigInteger(in, yLength);

	return new DHPubKey(p, g, y);
}

static DSAPublicKey
parseDSA(DataInputStream in) throws IOException {
	byte t = in.readByte();

	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);

	DSAPublicKey dsa = new DSAPubKey(p, q, g, y);
	return dsa;
}

/** Converts a KEY/DNSKEY record into a PublicKey */
static PublicKey
parseRecord(int alg, byte [] data) {
	ByteArrayInputStream bytes = new ByteArrayInputStream(data); 
	DataInputStream in = new DataInputStream(bytes);
	try {
		switch (alg) {
			case DNSSEC.RSAMD5:
			case DNSSEC.RSASHA1:
			case DNSSEC.RSA_NSEC3_SHA1:
				return parseRSA(in);
			case DNSSEC.DH:
				return parseDH(in);
			case DNSSEC.DSA:
			case DNSSEC.DSA_NSEC3_SHA1:
				return parseDSA(in);
			default:
				return null;
		}
	}
	catch (IOException e) {
		if (Options.check("verboseexceptions"))
			System.err.println(e);
		return null;
	}
}

/** Converts a DNSKEY record into a PublicKey */
public static PublicKey
parseRecord(DNSKEYRecord r) {
	int alg = r.getAlgorithm();
	byte [] data = r.getKey();
	return parseRecord(alg, data);
}

/** Converts a KEY record into a PublicKey */
public static PublicKey
parseRecord(KEYRecord r) {
	int alg = r.getAlgorithm();
	byte [] data = r.getKey();
	return parseRecord(alg, data);
}

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

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

	return out.toByteArray();
}

static byte []
buildDH(DHPublicKey key) {
	ByteArrayOutputStream out = new ByteArrayOutputStream();
	BigInteger p = key.getParams().getP();
	BigInteger g = key.getParams().getG();
	BigInteger y = key.getY();

	int pLength, gLength, yLength;
	if (g.equals(TWO) && (p.equals(DHPRIME768) || p.equals(DHPRIME1024))) {
		pLength = 1;
		gLength = 0;
	}
	else {
		pLength = BigIntegerLength(p);
		gLength = BigIntegerLength(g);
	}
	yLength = BigIntegerLength(y);

	writeShort(out, pLength);
	if (pLength == 1) {
		if (p.bitLength() == 768)
			out.write(1);
		else
			out.write(2);
	}
	else
		writeBigInteger(out, p);
	writeShort(out, gLength);
	if (gLength > 0)
		writeBigInteger(out, g);
	writeShort(out, yLength);
	writeBigInteger(out, y);

	return out.toByteArray();
}

static byte []
buildDSA(DSAPublicKey key) {
	ByteArrayOutputStream out = new ByteArrayOutputStream();
	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.write(t);
	writeBigInteger(out, q);
	writeBigInteger(out, p);
	writeBigInteger(out, g);
	writeBigInteger(out, y);

	return out.toByteArray();
}

/** Builds a KEY record from a PublicKey */
public static KEYRecord
buildRecord(Name name, int dclass, long ttl, int flags, int proto,
	    PublicKey key)
{
	byte alg;

	if (key instanceof RSAPublicKey) {
		alg = DNSSEC.RSAMD5;
	}
	else if (key instanceof DHPublicKey) {
		alg = DNSSEC.DH;
	}
	else if (key instanceof DSAPublicKey) {
		alg = DNSSEC.DSA;
	}
	else
		return null;

	return (KEYRecord) buildRecord(name, Type.KEY, dclass, ttl, flags,
				       proto, alg, key);
}

/** Builds a DNSKEY or KEY record from a PublicKey */
public static Record
buildRecord(Name name, int type, int dclass, long ttl, int flags, int proto,
	    int alg, PublicKey key)
{
	byte [] data;

	if (type != Type.KEY && type != Type.DNSKEY)
		throw new IllegalArgumentException("type must be KEY " +
						   "or DNSKEY");

	if (key instanceof RSAPublicKey) {
		data = buildRSA((RSAPublicKey) key);
	}
	else if (key instanceof DHPublicKey) {
		data = buildDH((DHPublicKey) key);
	}
	else if (key instanceof DSAPublicKey) {
		data = buildDSA((DSAPublicKey) key);
	}
	else
		return null;

	if (data == null)
		return null;

	if (type == Type.DNSKEY)
		return new DNSKEYRecord(name, dclass, ttl, flags, proto, alg,
					data);
	else
		return new KEYRecord(name, dclass, ttl, flags, proto, alg,
				     data);
}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy