org.xbill.DNS.security.KEYConverter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of browsermob-proxy Show documentation
Show all versions of browsermob-proxy Show documentation
A programmatic HTTP/S designed for performance and functional testing
// 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);
}
}