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:
parent
633ab040b3
commit
dff0e250f6
Binary file not shown.
@ -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,6 +120,8 @@ 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();
|
||||||
|
|
||||||
@ -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()
|
||||||
{
|
{
|
||||||
@ -182,7 +187,9 @@ public class DSTool
|
|||||||
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)
|
||||||
|
@ -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)
|
||||||
@ -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)
|
||||||
@ -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)
|
||||||
@ -784,12 +821,12 @@ public class SignZone
|
|||||||
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,
|
||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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
|
||||||
|
@ -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)
|
||||||
|
285
src/com/verisignlabs/dnssec/security/SHA256.java
Normal file
285
src/com/verisignlabs/dnssec/security/SHA256.java
Normal 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]) + " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -721,7 +721,7 @@ public class SignUtils
|
|||||||
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user