Add support for the SHA256 DS digest algorithm.

git-svn-id: https://svn.verisignlabs.com/jdnssec/tools/trunk@76 4cbd57fe-54e5-0310-bd9a-f30fe5ea5e6e
This commit is contained in:
David Blacka 2006-05-24 22:19:31 +00:00
parent 633ab040b3
commit dff0e250f6
6 changed files with 461 additions and 110 deletions

Binary file not shown.

View File

@ -56,12 +56,41 @@ public class DSTool
public boolean createDLV = false; public boolean createDLV = false;
public String outputfile = null; public String outputfile = null;
public String keyname = null; public String keyname = null;
public int digest_id = DSRecord.SHA1_DIGEST_ID;
public CLIState() public CLIState()
{ {
setupCLI(); setupCLI();
} }
/**
* Set up the command line options.
*
* @return a set of command line options.
*/
private void setupCLI()
{
opts = new Options();
// boolean options
opts.addOption("h", "help", false, "Print this message.");
opts.addOption(OptionBuilder.withLongOpt("dlv")
.withDescription("Generate a DLV record instead.").create());
// Argument options
opts.addOption(OptionBuilder.hasOptionalArg().withLongOpt("verbose")
.withArgName("level")
.withDescription("verbosity level -- 0 is silence, "
+ "5 is debug information, " + "6 is trace information.\n"
+ "default is level 5.").create('v'));
opts.addOption(OptionBuilder.hasArg().withLongOpt("digest")
.withArgName("id")
.withDescription("The Digest ID to use (numerically): "
+ "either 1 for SHA1 or 2 for SHA256").create('d'));
}
public void parseCommandLine(String[] args) public void parseCommandLine(String[] args)
throws org.apache.commons.cli.ParseException throws org.apache.commons.cli.ParseException
{ {
@ -91,7 +120,9 @@ public class DSTool
outputfile = cli.getOptionValue('f'); outputfile = cli.getOptionValue('f');
createDLV = cli.hasOption("dlv"); createDLV = cli.hasOption("dlv");
String optstr = cli.getOptionValue('d');
if (optstr != null) digest_id = parseInt(optstr, digest_id);
String[] cl_args = cli.getArgs(); String[] cl_args = cli.getArgs();
if (cl_args.length < 1) if (cl_args.length < 1)
@ -103,32 +134,6 @@ public class DSTool
keyname = cl_args[0]; keyname = cl_args[0];
} }
/**
* Set up the command line options.
*
* @return a set of command line options.
*/
private void setupCLI()
{
opts = new Options();
// boolean options
opts.addOption("h", "help", false, "Print this message.");
OptionBuilder.withLongOpt("dlv");
OptionBuilder.withDescription("Generate a DLV record instead.");
opts.addOption(OptionBuilder.create());
// Argument options
OptionBuilder.hasOptionalArg();
OptionBuilder.withLongOpt("verbose");
OptionBuilder.withArgName("level");
OptionBuilder.withDescription("verbosity level -- 0 is silence, "
+ "5 is debug information, " + "6 is trace information.\n"
+ "default is level 5.");
opts.addOption(OptionBuilder.create('v'));
}
/** Print out the usage and help statements, then quit. */ /** Print out the usage and help statements, then quit. */
private void usage() private void usage()
{ {
@ -176,15 +181,17 @@ public class DSTool
DnsKeyPair key = BINDKeyUtils.loadKey(state.keyname, null); DnsKeyPair key = BINDKeyUtils.loadKey(state.keyname, null);
DNSKEYRecord dnskey = key.getDNSKEYRecord(); DNSKEYRecord dnskey = key.getDNSKEYRecord();
if ((dnskey.getFlags() & DNSKEYRecord.Flags.SEP_KEY) == 0) if ((dnskey.getFlags() & DNSKEYRecord.Flags.SEP_KEY) == 0)
{ {
log.warning("DNSKEY is not an SEP-flagged key."); log.warning("DNSKEY is not an SEP-flagged key.");
} }
DSRecord ds = SignUtils.calculateDSRecord(dnskey, dnskey.getTTL()); DSRecord ds = SignUtils.calculateDSRecord(dnskey,
state.digest_id,
dnskey.getTTL());
Record res = ds; Record res = ds;
if (state.createDLV) if (state.createDLV)
{ {
log.fine("creating DLV."); log.fine("creating DLV.");

View File

@ -34,14 +34,9 @@ import java.util.logging.Logger;
import java.util.logging.Level; import java.util.logging.Level;
import org.apache.commons.cli.*; import org.apache.commons.cli.*;
import org.apache.commons.cli.Options;
import org.xbill.DNS.DNSKEYRecord; import org.xbill.DNS.*;
import org.xbill.DNS.DNSSEC;
import org.xbill.DNS.Name;
import org.xbill.DNS.RRset;
import org.xbill.DNS.Record;
import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;
import org.xbill.DNS.utils.base16; import org.xbill.DNS.utils.base16;
import com.verisignlabs.dnssec.security.*; import com.verisignlabs.dnssec.security.*;
@ -73,12 +68,13 @@ public class SignZone
public String outputfile = null; public String outputfile = null;
public boolean verifySigs = false; public boolean verifySigs = false;
public boolean selfSignKeys = true; public boolean selfSignKeys = true;
public boolean useOptIn = false; public boolean useOptOut = false;
public boolean fullySignKeyset = false; public boolean fullySignKeyset = false;
public List includeNames = null; public List includeNames = null;
public boolean useNsec3 = false; public boolean useNsec3 = false;
public byte[] salt = null; public byte[] salt = null;
public int iterations = 0; public int iterations = 0;
public int digest_id = DSRecord.SHA1_DIGEST_ID;
public CLIState() public CLIState()
{ {
@ -104,7 +100,7 @@ public class SignZone
// Argument options // Argument options
opts.addOption(OptionBuilder.hasOptionalArg().withLongOpt("verbose") opts.addOption(OptionBuilder.hasOptionalArg().withLongOpt("verbose")
.withArgName("level").withDescription("verbosity level") .withArgName("level").withDescription("verbosity level.")
.create('v')); .create('v'));
opts.addOption(OptionBuilder.hasArg().withArgName("dir") opts.addOption(OptionBuilder.hasArg().withArgName("dir")
.withLongOpt("keyset-directory") .withLongOpt("keyset-directory")
@ -127,21 +123,19 @@ public class SignZone
+ "(default is <origin>.signed).").create('f')); + "(default is <origin>.signed).").create('f'));
opts.addOption(OptionBuilder.hasArg().withArgName("KSK file") opts.addOption(OptionBuilder.hasArg().withArgName("KSK file")
.withLongOpt("ksk-file") .withLongOpt("ksk-file")
.withDescription("this key is the key signing key.").create('k')); .withDescription("this key is a key signing key (may repeat).")
.create('k'));
opts.addOption(OptionBuilder.hasArg().withArgName("file") opts.addOption(OptionBuilder.hasArg().withArgName("file")
.withLongOpt("include-file") .withLongOpt("include-file")
.withDescription("include names in this " .withDescription("include names in this "
+ "file in the NSEC/NSEC3 chain.").create('I')); + "file in the NSEC/NSEC3 chain.").create('I'));
opts.addOption(OptionBuilder.hasArg()
.withArgName("alias:original:mnemonic").withLongOpt("alg-alias")
.withDescription("Define an alias for an algorithm").create('A'));
// NSEC3 options // NSEC3 options
opts.addOption("3", "use-nsec3", false, "use NSEC3 instead of NSEC"); opts.addOption("3", "use-nsec3", false, "use NSEC3 instead of NSEC");
opts.addOption("O", opts.addOption("O",
"use-opt-in", "use-opt-out",
false, false,
"generate a fully Opt-In zone."); "generate a fully Opt-Out zone (only valid with NSEC3).");
opts.addOption(OptionBuilder.hasArg().withLongOpt("salt") opts.addOption(OptionBuilder.hasArg().withLongOpt("salt")
.withArgName("hex value").withDescription("supply a salt value.") .withArgName("hex value").withDescription("supply a salt value.")
@ -153,6 +147,15 @@ public class SignZone
.withArgName("value") .withArgName("value")
.withDescription("use this value for the iterations in NSEC3.") .withDescription("use this value for the iterations in NSEC3.")
.create()); .create());
opts.addOption(OptionBuilder.hasArg()
.withArgName("alias:original:mnemonic").withLongOpt("alg-alias")
.withDescription("Define an alias for an algorithm (may repeat).")
.create('A'));
opts.addOption(OptionBuilder.hasArg().withArgName("id")
.withLongOpt("ds-digest")
.withDescription("Digest algorithm to use for generated DSs")
.create());
} }
public void parseCommandLine(String[] args) public void parseCommandLine(String[] args)
@ -195,12 +198,12 @@ public class SignZone
if (cli.hasOption('a')) verifySigs = true; if (cli.hasOption('a')) verifySigs = true;
if (cli.hasOption('3')) useNsec3 = true; if (cli.hasOption('3')) useNsec3 = true;
if (cli.hasOption('O')) useOptIn = true; if (cli.hasOption('O')) useOptOut = true;
if (useOptIn && !useNsec3) if (useOptOut && !useNsec3)
{ {
System.err.println("OptIn not supported without NSEC3 -- ignored."); System.err.println("Opt-Out not supported without NSEC3 -- ignored.");
useOptIn = false; useOptOut = false;
} }
if ((optstrs = cli.getOptionValues('A')) != null) if ((optstrs = cli.getOptionValues('A')) != null)
@ -210,7 +213,7 @@ public class SignZone
addArgAlias(optstrs[i]); addArgAlias(optstrs[i]);
} }
} }
if (cli.hasOption('F')) fullySignKeyset = true; if (cli.hasOption('F')) fullySignKeyset = true;
if ((optstr = cli.getOptionValue('d')) != null) if ((optstr = cli.getOptionValue('d')) != null)
@ -294,6 +297,16 @@ public class SignZone
} }
} }
if ((optstr = cli.getOptionValue("ds-digest")) != null)
{
digest_id = parseInt(optstr, -1);
if (digest_id < 0)
{
System.err.println("error: DS digest ID is not a valid identifier");
usage();
}
}
String[] files = cli.getArgs(); String[] files = cli.getArgs();
if (files.length < 1) if (files.length < 1)
@ -328,7 +341,7 @@ public class SignZone
algs.addAlias(alias, mn, orig); algs.addAlias(alias, mn, orig);
} }
/** Print out the usage and help statements, then quit. */ /** Print out the usage and help statements, then quit. */
private void usage() private void usage()
{ {
@ -477,7 +490,6 @@ public class SignZone
{ {
if (inDirectory == null) if (inDirectory == null)
{ {
// FIXME: dunno how cross-platform this is
inDirectory = new File("."); inDirectory = new File(".");
} }
@ -663,33 +675,26 @@ public class SignZone
/** /**
* Given a zone, sign it. * Given a zone, sign it.
* *
* @param zonename the name of the zone. * @param signer A signer (utility) object to use to actually sign stuff.
* @param records the records comprising the zone. They do not have to be in * @param zonename The name of the zone.
* @param records The records comprising the zone. They do not have to be in
* any particular order, as this method will order them as * any particular order, as this method will order them as
* necessary. * necessary.
* @param keysigningkeypairs the key pairs that are designated as "key * @param keysigningkeypairs The key pairs that are designated as "key
* signing keys". * signing keys".
* @param zonekeypair this key pairs that are designated as "zone signing * @param zonekeypair This key pairs that are designated as "zone signing
* keys". * keys".
* @param start the RRSIG inception time. * @param start The RRSIG inception time.
* @param expire the RRSIG expiration time. * @param expire The RRSIG expiration time.
* @param useOptIn generate Opt-In style NXT records. It will consider any * @param fullySignKeyset Sign the zone apex keyset with all available keys.
* insecure delegation to be unsigned. To override this, include * @param digest_id The digest identifier to use when generating DS records.
* the name of the insecure delegation in the NXTIncludeNames list.
* @param useConservativeOptIn if true, Opt-In NXT records will only be
* generated if there are insecure, unsigned delegations in the
* span. Not effect if useOptIn is false.
* @param fullySignKeyset sign the zone apex keyset with all available keys.
* @param NXTIncludeNames names that are to be included in the NXT chain
* regardless. This may be null and is only used if useOptIn is
* true.
* *
* @return an ordered list of {@link org.xbill.DNS.Record} objects, * @return an ordered list of {@link org.xbill.DNS.Record} objects,
* representing the signed zone. * representing the signed zone.
*/ */
private static List signZone(JCEDnsSecSigner signer, Name zonename, private static List signZone(JCEDnsSecSigner signer, Name zonename,
List records, List keysigningkeypairs, List zonekeypairs, Date start, List records, List keysigningkeypairs, List zonekeypairs, Date start,
Date expire, boolean fullySignKeyset) Date expire, boolean fullySignKeyset, int digest_id)
throws IOException, GeneralSecurityException throws IOException, GeneralSecurityException
{ {
@ -703,7 +708,7 @@ public class SignZone
SignUtils.removeDuplicateRecords(records); SignUtils.removeDuplicateRecords(records);
// Generate DS records // Generate DS records
SignUtils.generateDSRecords(zonename, records); SignUtils.generateDSRecords(zonename, records, digest_id);
// Generate the NSEC records // Generate the NSEC records
SignUtils.generateNSECRecords(zonename, records); SignUtils.generateNSECRecords(zonename, records);
@ -768,10 +773,42 @@ public class SignZone
return signed_records; return signed_records;
} }
/**
* Given a zone sign it using NSEC3 records.
*
* @param signer A signer (utility) object used to actually sign stuff.
* @param zonename The name of the zone being signed.
* @param records The records comprising the zone. They do not have to be in
* any particular order, as this method will order them as
* necessary.
* @param keysigningkeypairs The key pairs that are designated as "key
* signing keys".
* @param zonekeypairs This key pairs that are designated as "zone signing
* keys".
* @param start The RRSIG inception time.
* @param expire The RRSIG expiration time.
* @param fullySignKeyset If true then the DNSKEY RRset will be signed by
* all available keys, if false, only the key signing keys.
* @param useOptOut If true, insecure delegations will be omitted from the
* NSEC3 chain, and all NSEC3 records will have the Opt-Out flag
* set.
* @param includedNames A list of names to include in the NSEC3 chain
* regardless.
* @param salt The salt to use for the NSEC3 hashing. null means no salt.
* @param iterations The number of iterations to use for the NSEC3 hashing.
* @param ds_digest_id The digest algorithm to use when generating DS
* records.
*
* @return an ordered list of {@link org.xbill.DNS.Record} objects,
* representing the signed zone.
*
* @throws IOException
* @throws GeneralSecurityException
*/
private static List signZoneNSEC3(JCEDnsSecSigner signer, Name zonename, private static List signZoneNSEC3(JCEDnsSecSigner signer, Name zonename,
List records, List keysigningkeypairs, List zonekeypairs, Date start, List records, List keysigningkeypairs, List zonekeypairs, Date start,
Date expire, boolean fullySignKeyset, boolean useOptIn, Date expire, boolean fullySignKeyset, boolean useOptOut,
List includedNames, byte[] salt, int iterations) List includedNames, byte[] salt, int iterations, int ds_digest_id)
throws IOException, GeneralSecurityException throws IOException, GeneralSecurityException
{ {
// Remove any existing DNSSEC records (NSEC, NSEC3, RRSIG) // Remove any existing DNSSEC records (NSEC, NSEC3, RRSIG)
@ -779,17 +816,17 @@ public class SignZone
// Sort the zone // Sort the zone
Collections.sort(records, new RecordComparator()); Collections.sort(records, new RecordComparator());
// Remove duplicate records // Remove duplicate records
SignUtils.removeDuplicateRecords(records); SignUtils.removeDuplicateRecords(records);
// Generate DS records // Generate DS records
SignUtils.generateDSRecords(zonename, records); SignUtils.generateDSRecords(zonename, records, ds_digest_id);
// Generate NSEC3 records // Generate NSEC3 records
if (useOptIn) if (useOptOut)
{ {
SignUtils.generateOptInNSEC3Records(zonename, SignUtils.generateOptOutNSEC3Records(zonename,
records, records,
includedNames, includedNames,
salt, salt,
@ -900,14 +937,14 @@ public class SignZone
{ {
keypairs = kskpairs; keypairs = kskpairs;
} }
// If there *still* aren't any ZSKs defined, bail. // If there *still* aren't any ZSKs defined, bail.
if (keypairs == null || keypairs.size() == 0) if (keypairs == null || keypairs.size() == 0)
{ {
System.err.println("No zone signing keys could be determined."); System.err.println("No zone signing keys could be determined.");
state.usage(); state.usage();
} }
// Read in the zone // Read in the zone
List records = ZoneUtils.readZoneFile(state.zonefile, null); List records = ZoneUtils.readZoneFile(state.zonefile, null);
if (records == null || records.size() == 0) if (records == null || records.size() == 0)
@ -941,6 +978,7 @@ public class SignZone
if (!keyPairsValidForZone(zonename, keypairs) if (!keyPairsValidForZone(zonename, keypairs)
|| !keyPairsValidForZone(zonename, kskpairs)) || !keyPairsValidForZone(zonename, kskpairs))
{ {
System.err.println("error: specified keypairs are not valid for the zone.");
state.usage(); state.usage();
} }
@ -961,7 +999,7 @@ public class SignZone
records.add(((DnsKeyPair) i.next()).getDNSKEYRecord()); records.add(((DnsKeyPair) i.next()).getDNSKEYRecord());
} }
} }
// read in the keysets, if any. // read in the keysets, if any.
List keysetrecs = getKeysets(state.keysetDirectory, zonename); List keysetrecs = getKeysets(state.keysetDirectory, zonename);
if (keysetrecs != null) if (keysetrecs != null)
@ -984,10 +1022,11 @@ public class SignZone
state.start, state.start,
state.expire, state.expire,
state.fullySignKeyset, state.fullySignKeyset,
state.useOptIn, state.useOptOut,
state.includeNames, state.includeNames,
state.salt, state.salt,
state.iterations); state.iterations,
state.digest_id);
} }
else else
{ {
@ -998,7 +1037,8 @@ public class SignZone
keypairs, keypairs,
state.start, state.start,
state.expire, state.expire,
state.fullySignKeyset); state.fullySignKeyset,
state.digest_id);
} }
// write out the signed zone // write out the signed zone

View File

@ -264,8 +264,6 @@ public class JCEDnsSecSigner
* necessary. * necessary.
* @param keysigningkeypairs the key pairs that are designated as "key * @param keysigningkeypairs the key pairs that are designated as "key
* signing keys". * signing keys".
* @param zonekeypair this key pairs that are designated as "zone signing
* keys".
* @param start the RRSIG inception time. * @param start the RRSIG inception time.
* @param expire the RRSIG expiration time. * @param expire the RRSIG expiration time.
* @param useOptIn generate Opt-In style NXT records. It will consider any * @param useOptIn generate Opt-In style NXT records. It will consider any
@ -275,17 +273,20 @@ public class JCEDnsSecSigner
* generated if there are insecure, unsigned delegations in the * generated if there are insecure, unsigned delegations in the
* span. Not effect if useOptIn is false. * span. Not effect if useOptIn is false.
* @param fullySignKeyset sign the zone apex keyset with all available keys. * @param fullySignKeyset sign the zone apex keyset with all available keys.
* @param ds_digest_id TODO
* @param zonekeypair this key pairs that are designated as "zone signing
* keys".
* @param NXTIncludeNames names that are to be included in the NXT chain * @param NXTIncludeNames names that are to be included in the NXT chain
* regardless. This may be null and is only used if useOptIn is * regardless. This may be null and is only used if useOptIn is
* true. * true.
*
* @return an ordered list of {@link org.xbill.DNS.Record} objects, * @return an ordered list of {@link org.xbill.DNS.Record} objects,
* representing the signed zone. * representing the signed zone.
*/ */
public List signZone(Name zonename, List records, List keysigningkeypairs, public List signZone(Name zonename, List records, List keysigningkeypairs,
List zonekeypairs, Date start, Date expire, boolean useOptIn, List zonekeypairs, Date start, Date expire, boolean useOptIn,
boolean useConservativeOptIn, boolean fullySignKeyset, boolean useConservativeOptIn, boolean fullySignKeyset,
List NSECIncludeNames) throws IOException, GeneralSecurityException List NSECIncludeNames, int ds_digest_id)
throws IOException, GeneralSecurityException
{ {
// Remove any existing DNSSEC records (NSEC, RRSIG) // Remove any existing DNSSEC records (NSEC, RRSIG)
@ -297,7 +298,7 @@ public class JCEDnsSecSigner
SignUtils.removeDuplicateRecords(records); SignUtils.removeDuplicateRecords(records);
// Generate DS records // Generate DS records
SignUtils.generateDSRecords(zonename, records); SignUtils.generateDSRecords(zonename, records, ds_digest_id);
// Generate NXT records // Generate NXT records
if (useOptIn) if (useOptIn)

View File

@ -0,0 +1,285 @@
/*************************************************************************
* SHA256
*
* a homebrew of the SHA256 algorithm for dnsjava. Some of the concepts
* are taken from the Cryptix crypto provider: http://www.cryptix.org
*
* Scott Rose
* NIST
* 04/16/04
*************************************************************************/
package com.verisignlabs.dnssec.security;
import java.io.ByteArrayOutputStream;
public class SHA256
{
private int Ch(int a, int b, int c)
{
return (a & b) ^ (~a & c);
}
private int Maj(int a, int b, int c)
{
return (a & b) ^ (a & c) ^ (b & c);
}
private int SHR(int x, int n)
{
return (x >>> n);
}
private int ROTR(int x, int n)
{
return ((x >>> n) | (x << (32 - n)));
}
private int SIG0(int x)
{
return (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22));
}
private int SIG1(int x)
{
return (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25));
}
private int sig0(int x)
{
return (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3));
}
private int sig1(int x)
{
return (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10));
}
// Constants "K"
private static final int K[] = {0x428a2f98, 0x71374491, 0xb5c0fbcf,
0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98,
0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f,
0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8,
0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85,
0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e,
0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c,
0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee,
0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
0xc67178f2 };
private int digest[] = new int[8];
private byte data[];
public SHA256()
{
}
public void init()
{
digest[0] = 0x6a09e667;
digest[1] = 0xbb67ae85;
digest[2] = 0x3c6ef372;
digest[3] = 0xa54ff53a;
digest[4] = 0x510e527f;
digest[5] = 0x9b05688c;
digest[6] = 0x1f83d9ab;
digest[7] = 0x5be0cd19;
}
public void setData(byte input[])
{
// clone the array
data = doDataPad(input);
}
private byte[] doDataPad(byte input[])
{
int n, fill;
n = input.length + 9;
if (input.length < 55)
{
fill = 64 - n;
}
else
{
fill = 64 - (n % 64);
}
if ((input.length % 64) != 0)
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(input, 0, input.length);
out.write(0x80);
for (int i = 0; i < fill; i++)
out.write(0x00);
long l = input.length * 8; // length is measured in bits
out.write((int) (l >>> 56) & 0xFF);
out.write((int) (l >>> 48) & 0xFF);
out.write((int) (l >>> 40) & 0xFF);
out.write((int) (l >>> 32) & 0xFF);
out.write((int) (l >>> 24) & 0xFF);
out.write((int) (l >>> 16) & 0xFF);
out.write((int) (l >>> 8) & 0xFF);
out.write((int) l & 0xFF);
// we are replacing data here with a new padded version
return out.toByteArray();
}
return input;
}
/*
* utility method to convert a byte input array to an int[] for easier
* processing. Also does the padding as necessary
*/
private int[] convertToInt(byte block[])
{
int output[] = new int[16];
int w = -1;
for (int i = 0; i < 16; i++)
{
output[i] = (block[++w] << 24) | ((block[++w] & 0xFF) << 16)
| ((block[++w] & 0xFF) << 8) | (block[++w] & 0xFF);
}
return output;
}
/*
* method called to get the SHA1 digest of the input
*/
public byte[] getDigest()
{
byte output[] = new byte[32];
int aBlock[];
byte byteBlock[];
// for (int n = 0; n < data.length; n++)
// {
// System.out.print(Integer.toHexString(data[n]) + " ");
// }
// System.out.println("\n\n");
if (data.length > 64)
{
int n = data.length / 64;
int place = 0;
for (int i = 0; i < n; i++)
{
byteBlock = new byte[64];
for (int x = 0; x < 64; x++)
{
byteBlock[x] = data[place++];
}
aBlock = convertToInt(byteBlock);
transform(aBlock);
}
}
else
{
aBlock = convertToInt(data);
transform(aBlock);
}
// convert the int array back to byte and return
int out = -1;
for (int i = 0; i < 8; i++)
{
output[++out] = (byte) ((digest[i] >>> 24) & 0xFF);
output[++out] = (byte) ((digest[i] >>> 16) & 0xFF);
output[++out] = (byte) ((digest[i] >>> 8) & 0xFF);
output[++out] = (byte) (digest[i] & 0xFF);
}
return output;
}
/*
* this is the method that actually performs the digest and returns the
* result
*/
private void transform(int block[])
{
// first, break into blocks and process one by one
int A = digest[0];
int B = digest[1];
int C = digest[2];
int D = digest[3];
int E = digest[4];
int F = digest[5];
int G = digest[6];
int H = digest[7];
// doing the message schedule
int W[] = new int[64];
for (int i = 0; i < 16; i++)
{
W[i] = block[i];
// System.out.println("W: " + Integer.toHexString(W[i]) + "\n");
}
for (int i = 16; i < 64; i++)
{
W[i] = sig1(W[i - 2]) + W[i - 7] + sig0(W[i - 15]) + W[i - 16];
}
for (int t = 0; t < 64; t++)
{
int T1 = H + SIG1(E) + Ch(E, F, G) + K[t] + W[t];
int T2 = SIG0(A) + Maj(A, B, C);
H = G;
G = F;
F = E;
E = D + T1;
D = C;
C = B;
B = A;
A = T1 + T2;
// System.out.println("A: " + Integer.toHexString(A));
// System.out.println("B: " + Integer.toHexString(B));
// System.out.println("C: " + Integer.toHexString(C));
// System.out.println("D: " + Integer.toHexString(D));
// System.out.println("E: " + Integer.toHexString(E));
// System.out.println("F: " + Integer.toHexString(F));
// System.out.println("G: " + Integer.toHexString(G));
// System.out.println("H: " + Integer.toHexString(H) + "\n");
}
digest[0] += A;
digest[1] += B;
digest[2] += C;
digest[3] += D;
digest[4] += E;
digest[6] += F;
digest[7] += G;
}
public static void main(String argv[])
{
String data1 = "abc";
SHA256 sha = new SHA256();
byte output[];
sha.init();
System.out.println("ready to set the data");
sha.setData(data1.getBytes());
System.out.println("ready to get the digest");
output = sha.getDigest();
for (int i = 0; i < output.length; i++)
{
// Integer b = new Integer((int)output[i]);
System.out.print(Integer.toHexString(output[i]) + " ");
}
}
}

View File

@ -42,15 +42,15 @@ import org.xbill.DNS.utils.base64;
public class SignUtils public class SignUtils
{ {
private static final int ASN1_INT = 0x02; private static final int ASN1_INT = 0x02;
private static final int ASN1_SEQ = 0x30; private static final int ASN1_SEQ = 0x30;
public static final int RR_NORMAL = 0; public static final int RR_NORMAL = 0;
public static final int RR_DELEGATION = 1; public static final int RR_DELEGATION = 1;
public static final int RR_GLUE = 2; public static final int RR_GLUE = 2;
public static final int RR_INVALID = 3; public static final int RR_INVALID = 3;
private static Logger log; private static Logger log;
static static
{ {
@ -712,16 +712,16 @@ public class SignUtils
List nsec3s = finishNSEC3s(proto_nsec3s); List nsec3s = finishNSEC3s(proto_nsec3s);
// DEBUG // DEBUG
// for (Iterator i = nsec3s.iterator(); i.hasNext();) // for (Iterator i = nsec3s.iterator(); i.hasNext();)
// { // {
// NSEC3Record nsec3 = (NSEC3Record) i.next(); // NSEC3Record nsec3 = (NSEC3Record) i.next();
// log.fine("NSEC3: " + nsec3 + "\nRDATA: " // log.fine("NSEC3: " + nsec3 + "\nRDATA: "
// + base16.toString(nsec3.rdataToWireCanonical())); // + base16.toString(nsec3.rdataToWireCanonical()));
// } // }
records.addAll(nsec3s); records.addAll(nsec3s);
} }
public static void generateOptInNSEC3Records(Name zonename, List records, public static void generateOptOutNSEC3Records(Name zonename, List records,
List includedNames, byte[] salt, int iterations) List includedNames, byte[] salt, int iterations)
throws NoSuchAlgorithmException throws NoSuchAlgorithmException
{ {
@ -1081,8 +1081,9 @@ public class SignUtils
* @param zonename the name of the zone, used to reliably distinguish the * @param zonename the name of the zone, used to reliably distinguish the
* zone apex from other records. * zone apex from other records.
* @param records a list of {@link org.xbill.DNS.Record} objects. * @param records a list of {@link org.xbill.DNS.Record} objects.
* @param digest_id The digest algorithm to use.
*/ */
public static void generateDSRecords(Name zonename, List records) public static void generateDSRecords(Name zonename, List records, int digest_id)
{ {
for (ListIterator i = records.listIterator(); i.hasNext();) for (ListIterator i = records.listIterator(); i.hasNext();)
@ -1096,7 +1097,9 @@ public class SignUtils
// Convert non-zone level KEY records into DS records. // Convert non-zone level KEY records into DS records.
if (r.getType() == Type.DNSKEY && !r_name.equals(zonename)) if (r.getType() == Type.DNSKEY && !r_name.equals(zonename))
{ {
DSRecord ds = calculateDSRecord((DNSKEYRecord) r, r.getTTL()); DSRecord ds = calculateDSRecord((DNSKEYRecord) r,
DSRecord.SHA1_DIGEST_ID,
r.getTTL());
i.set(ds); i.set(ds);
} }
@ -1155,11 +1158,13 @@ public class SignUtils
* Given a DNSKEY record, generate the DS record from it. * Given a DNSKEY record, generate the DS record from it.
* *
* @param keyrec the KEY record in question. * @param keyrec the KEY record in question.
* @param digest_id The digest ID.
* @param ttl the desired TTL for the generated DS record. If zero, or * @param ttl the desired TTL for the generated DS record. If zero, or
* negative, the original KEY RR's TTL will be used. * negative, the original KEY RR's TTL will be used.
* @return the corresponding {@link org.xbill.DNS.DSRecord} * @return the corresponding {@link org.xbill.DNS.DSRecord}
*/ */
public static DSRecord calculateDSRecord(DNSKEYRecord keyrec, long ttl) public static DSRecord calculateDSRecord(DNSKEYRecord keyrec,
int digest_id, long ttl)
{ {
if (keyrec == null) return null; if (keyrec == null) return null;
@ -1172,12 +1177,25 @@ public class SignUtils
try try
{ {
MessageDigest md = MessageDigest.getInstance("SHA"); byte[] digest;
byte[] digest = md.digest(os.toByteArray()); switch (digest_id)
{
case DSRecord.SHA1_DIGEST_ID :
MessageDigest md = MessageDigest.getInstance("SHA");
digest = md.digest(os.toByteArray());
break;
case DSRecord.SHA256_DIGEST_ID :
SHA256 sha = new SHA256();
sha.setData(os.toByteArray());
digest = sha.getDigest();
break;
default :
throw new IllegalArgumentException("Unknown digest id: " + digest_id);
}
return new DSRecord(keyrec.getName(), keyrec.getDClass(), ttl, keyrec return new DSRecord(keyrec.getName(), keyrec.getDClass(), ttl, keyrec
.getFootprint(), keyrec.getAlgorithm(), DSRecord.SHA1_DIGEST_ID, .getFootprint(), keyrec.getAlgorithm(), digest_id,
digest); digest);
} }