add support for algorithm aliases, fix SignZone so you can specify more than one KSK
git-svn-id: https://svn.verisignlabs.com/jdnssec/tools/trunk@64 4cbd57fe-54e5-0310-bd9a-f30fe5ea5e6e
This commit is contained in:
parent
5ba24d35b1
commit
435acff6d0
@ -27,10 +27,10 @@ import java.util.logging.Logger;
|
||||
import org.apache.commons.cli.*;
|
||||
import org.xbill.DNS.DClass;
|
||||
import org.xbill.DNS.DNSKEYRecord;
|
||||
import org.xbill.DNS.DNSSEC;
|
||||
import org.xbill.DNS.Name;
|
||||
|
||||
import com.verisignlabs.dnssec.security.BINDKeyUtils;
|
||||
import com.verisignlabs.dnssec.security.DnsKeyAlgorithm;
|
||||
import com.verisignlabs.dnssec.security.DnsKeyPair;
|
||||
import com.verisignlabs.dnssec.security.JCEDnsSecSigner;
|
||||
|
||||
@ -66,6 +66,73 @@ public class KeyGen
|
||||
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("k",
|
||||
"kskflag",
|
||||
false,
|
||||
"Key is a key-signing-key (sets the SEP flag).");
|
||||
|
||||
// Argument options
|
||||
OptionBuilder.hasArg();
|
||||
OptionBuilder.withLongOpt("nametype");
|
||||
OptionBuilder.withArgName("type");
|
||||
OptionBuilder.withDescription("ZONE | OTHER (default ZONE)");
|
||||
opts.addOption(OptionBuilder.create('n'));
|
||||
|
||||
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'));
|
||||
|
||||
OptionBuilder.hasArg();
|
||||
OptionBuilder.withArgName("algorithm");
|
||||
OptionBuilder
|
||||
.withDescription("RSA | RSASHA1 | RSAMD5 | DH | DSA | alias, "
|
||||
+ "RSASHA1 is default.");
|
||||
opts.addOption(OptionBuilder.create('a'));
|
||||
|
||||
OptionBuilder.hasArg();
|
||||
OptionBuilder.withArgName("size");
|
||||
OptionBuilder.withDescription("key size, in bits. (default = 1024)\n"
|
||||
+ "RSA|RSASHA1|RSAMD5: [512..4096]\n"
|
||||
+ "DSA: [512..1024]\n"
|
||||
+ "DH: [128..4096]");
|
||||
opts.addOption(OptionBuilder.create('b'));
|
||||
|
||||
OptionBuilder.hasArg();
|
||||
OptionBuilder.withArgName("file");
|
||||
OptionBuilder.withLongOpt("output-file");
|
||||
OptionBuilder
|
||||
.withDescription("base filename for the public/private key files");
|
||||
opts.addOption(OptionBuilder.create('f'));
|
||||
|
||||
OptionBuilder.hasArg();
|
||||
OptionBuilder.withLongOpt("keydir");
|
||||
OptionBuilder.withArgName("dir");
|
||||
OptionBuilder.withDescription("place generated key files in this "
|
||||
+ "directory");
|
||||
opts.addOption(OptionBuilder.create('d'));
|
||||
|
||||
OptionBuilder.hasArg();
|
||||
OptionBuilder.withLongOpt("alg-alias");
|
||||
OptionBuilder.withArgName("alias:original:mnemonic");
|
||||
OptionBuilder.withDescription("define an alias for an algorithm");
|
||||
opts.addOption(OptionBuilder.create('A'));
|
||||
}
|
||||
|
||||
public void parseCommandLine(String[] args)
|
||||
throws org.apache.commons.cli.ParseException
|
||||
{
|
||||
@ -111,6 +178,16 @@ public class KeyGen
|
||||
zoneKey = false;
|
||||
}
|
||||
}
|
||||
|
||||
String[] optstrs;
|
||||
if ((optstrs = cli.getOptionValues('A')) != null)
|
||||
{
|
||||
for (int i = 0; i < optstrs.length; i++)
|
||||
{
|
||||
addArgAlias(optstrs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if ((optstr = cli.getOptionValue('a')) != null)
|
||||
{
|
||||
algorithm = parseAlg(optstr);
|
||||
@ -137,64 +214,25 @@ public class KeyGen
|
||||
owner = cl_args[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the command line options.
|
||||
*
|
||||
* @return a set of command line options.
|
||||
*/
|
||||
private void setupCLI()
|
||||
private void addArgAlias(String s)
|
||||
{
|
||||
opts = new Options();
|
||||
|
||||
// boolean options
|
||||
opts.addOption("h", "help", false, "Print this message.");
|
||||
opts.addOption("k",
|
||||
"kskflag",
|
||||
false,
|
||||
"Key is a key-signing-key (sets the SEP flag).");
|
||||
|
||||
// Argument options
|
||||
OptionBuilder.hasArg();
|
||||
OptionBuilder.withLongOpt("nametype");
|
||||
OptionBuilder.withArgName("type");
|
||||
OptionBuilder.withDescription("ZONE | OTHER (default ZONE)");
|
||||
opts.addOption(OptionBuilder.create('n'));
|
||||
|
||||
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'));
|
||||
|
||||
OptionBuilder.hasArg();
|
||||
OptionBuilder.withArgName("algorithm");
|
||||
OptionBuilder.withDescription("RSA | RSASHA1 | RSAMD5 | DH | DSA, "
|
||||
+ "RSASHA1 is default.");
|
||||
opts.addOption(OptionBuilder.create('a'));
|
||||
|
||||
OptionBuilder.hasArg();
|
||||
OptionBuilder.withArgName("size");
|
||||
OptionBuilder.withDescription("key size, in bits. (default = 1024)\n"
|
||||
+ "RSA|RSASHA1|RSAMD5: [512..4096]\n"
|
||||
+ "DSA: [512..1024]\n"
|
||||
+ "DH: [128..4096]");
|
||||
opts.addOption(OptionBuilder.create('b'));
|
||||
|
||||
OptionBuilder.hasArg();
|
||||
OptionBuilder.withArgName("file");
|
||||
OptionBuilder.withLongOpt("output-file");
|
||||
OptionBuilder.withDescription("base filename for the public/private key files");
|
||||
opts.addOption(OptionBuilder.create('f'));
|
||||
|
||||
OptionBuilder.hasArg();
|
||||
OptionBuilder.withLongOpt("keydir");
|
||||
OptionBuilder.withArgName("dir");
|
||||
OptionBuilder.withDescription("place generated key files in this directory");
|
||||
opts.addOption(OptionBuilder.create('d'));
|
||||
if (s == null) return;
|
||||
|
||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||
|
||||
String[] v = s.split(":");
|
||||
if (v.length < 2) return;
|
||||
|
||||
int alias = parseInt(v[0], -1);
|
||||
if (alias <= 0) return;
|
||||
int orig = parseInt(v[1], -1);
|
||||
if (orig <= 0) return;
|
||||
String mn = null;
|
||||
if (v.length > 2) mn = v[2];
|
||||
|
||||
algs.addAlias(alias, mn, orig);
|
||||
}
|
||||
|
||||
|
||||
/** Print out the usage and help statements, then quit. */
|
||||
private void usage()
|
||||
{
|
||||
@ -239,34 +277,12 @@ public class KeyGen
|
||||
|
||||
private static int parseAlg(String s)
|
||||
{
|
||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||
|
||||
int alg = parseInt(s, -1);
|
||||
if (alg > 0) return alg;
|
||||
|
||||
s = s.toUpperCase();
|
||||
|
||||
if (s.equals("RSA"))
|
||||
{
|
||||
return DNSSEC.RSASHA1;
|
||||
}
|
||||
else if (s.equals("RSAMD5"))
|
||||
{
|
||||
return DNSSEC.RSA;
|
||||
}
|
||||
else if (s.equals("DH"))
|
||||
{
|
||||
return DNSSEC.DH;
|
||||
}
|
||||
else if (s.equals("DSA"))
|
||||
{
|
||||
return DNSSEC.DSA;
|
||||
}
|
||||
else if (s.equals("RSASHA1"))
|
||||
{
|
||||
return DNSSEC.RSASHA1;
|
||||
}
|
||||
|
||||
// default
|
||||
return DNSSEC.RSASHA1;
|
||||
return algs.stringToAlgorithm(s);
|
||||
}
|
||||
|
||||
public static void execute(CLIState state) throws Exception
|
||||
|
@ -44,13 +44,7 @@ import org.xbill.DNS.TextParseException;
|
||||
import org.xbill.DNS.Type;
|
||||
import org.xbill.DNS.utils.base16;
|
||||
|
||||
import com.verisignlabs.dnssec.security.BINDKeyUtils;
|
||||
import com.verisignlabs.dnssec.security.DnsKeyPair;
|
||||
import com.verisignlabs.dnssec.security.DnsSecVerifier;
|
||||
import com.verisignlabs.dnssec.security.JCEDnsSecSigner;
|
||||
import com.verisignlabs.dnssec.security.RecordComparator;
|
||||
import com.verisignlabs.dnssec.security.SignUtils;
|
||||
import com.verisignlabs.dnssec.security.ZoneUtils;
|
||||
import com.verisignlabs.dnssec.security.*;
|
||||
|
||||
/**
|
||||
* This class forms the command line implementation of a DNSSEC zone signer.
|
||||
@ -91,6 +85,76 @@ public class SignZone
|
||||
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("a", "verify", false, "verify generated signatures>");
|
||||
opts.addOption("F",
|
||||
"fully-sign-keyset",
|
||||
false,
|
||||
"sign the zone apex keyset with all available keys.");
|
||||
|
||||
// Argument options
|
||||
opts.addOption(OptionBuilder.hasOptionalArg().withLongOpt("verbose")
|
||||
.withArgName("level").withDescription("verbosity level")
|
||||
.create('v'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("dir")
|
||||
.withLongOpt("keyset-directory")
|
||||
.withDescription("directory to find keyset files (default '.').")
|
||||
.create('d'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("dir")
|
||||
.withLongOpt("key-directory")
|
||||
.withDescription("directory to find key files (default '.').")
|
||||
.create('D'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("time/offset")
|
||||
.withLongOpt("start-time")
|
||||
.withDescription("signature starting time "
|
||||
+ "(default is now - 1 hour)").create('s'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("time/offset")
|
||||
.withLongOpt("expire-time")
|
||||
.withDescription("signature expiration time "
|
||||
+ "(default is start-time + 30 days).").create('e'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("outfile")
|
||||
.withDescription("file the signed zone is written to "
|
||||
+ "(default is <origin>.signed).").create('f'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("KSK file")
|
||||
.withLongOpt("ksk-file")
|
||||
.withDescription("this key is the key signing key.").create('k'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("file")
|
||||
.withLongOpt("include-file")
|
||||
.withDescription("include names in this "
|
||||
+ "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
|
||||
opts.addOption("3", "use-nsec3", false, "use NSEC3 instead of NSEC");
|
||||
opts.addOption("O",
|
||||
"use-opt-in",
|
||||
false,
|
||||
"generate a fully Opt-In zone.");
|
||||
|
||||
opts.addOption(OptionBuilder.hasArg().withLongOpt("salt")
|
||||
.withArgName("hex value").withDescription("supply a salt value.")
|
||||
.create('S'));
|
||||
opts.addOption(OptionBuilder.hasArg().withLongOpt("random-salt")
|
||||
.withArgName("length").withDescription("generate a random salt.")
|
||||
.create('R'));
|
||||
opts.addOption(OptionBuilder.hasArg().withLongOpt("iterations")
|
||||
.withArgName("value")
|
||||
.withDescription("use this value for the iterations in NSEC3.")
|
||||
.create());
|
||||
}
|
||||
|
||||
public void parseCommandLine(String[] args)
|
||||
throws org.apache.commons.cli.ParseException, ParseException,
|
||||
IOException
|
||||
@ -99,6 +163,7 @@ public class SignZone
|
||||
CommandLine cli = cli_parser.parse(opts, args);
|
||||
|
||||
String optstr = null;
|
||||
String[] optstrs = null;
|
||||
|
||||
if (cli.hasOption('h')) usage();
|
||||
|
||||
@ -138,6 +203,14 @@ public class SignZone
|
||||
useOptIn = false;
|
||||
}
|
||||
|
||||
if ((optstrs = cli.getOptionValues('A')) != null)
|
||||
{
|
||||
for (int i = 0; i < optstrs.length; i++)
|
||||
{
|
||||
addArgAlias(optstrs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (cli.hasOption('F')) fullySignKeyset = true;
|
||||
|
||||
if ((optstr = cli.getOptionValue('d')) != null)
|
||||
@ -182,15 +255,7 @@ public class SignZone
|
||||
|
||||
outputfile = cli.getOptionValue('f');
|
||||
|
||||
// FIXME: this is a bit awkward, because we really want -k to repeat,
|
||||
// but the CLI classes don't do it quite right. Instead we just convert
|
||||
// our single argument to an array.
|
||||
String kskFile = cli.getOptionValue('k');
|
||||
if (kskFile != null)
|
||||
{
|
||||
kskFiles = new String[1];
|
||||
kskFiles[0] = kskFile;
|
||||
}
|
||||
kskFiles = cli.getOptionValues('k');
|
||||
|
||||
if ((optstr = cli.getOptionValue('I')) != null)
|
||||
{
|
||||
@ -235,74 +300,25 @@ public class SignZone
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the command line options.
|
||||
*
|
||||
* @return a set of command line options.
|
||||
*/
|
||||
private void setupCLI()
|
||||
private void addArgAlias(String s)
|
||||
{
|
||||
opts = new Options();
|
||||
if (s == null) return;
|
||||
|
||||
// boolean options
|
||||
opts.addOption("h", "help", false, "Print this message.");
|
||||
opts.addOption("a", "verify", false, "verify generated signatures>");
|
||||
opts.addOption("F",
|
||||
"fully-sign-keyset",
|
||||
false,
|
||||
"sign the zone apex keyset with all available keys.");
|
||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||
|
||||
// Argument options
|
||||
opts.addOption(OptionBuilder.hasOptionalArg().withLongOpt("verbose")
|
||||
.withArgName("level").withDescription("verbosity level")
|
||||
.create('v'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("dir")
|
||||
.withLongOpt("keyset-directory")
|
||||
.withDescription("directory to find keyset files (default '.').")
|
||||
.create('d'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("dir")
|
||||
.withLongOpt("key-directory")
|
||||
.withDescription("directory to find key files (default '.').")
|
||||
.create('D'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("time/offset")
|
||||
.withLongOpt("start-time")
|
||||
.withDescription("signature starting time "
|
||||
+ "(default is now - 1 hour)").create('s'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("time/offset")
|
||||
.withLongOpt("expire-time")
|
||||
.withDescription("signature expiration time "
|
||||
+ "(default is start-time + 30 days).").create('e'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("outfile")
|
||||
.withDescription("file the signed zone is written to "
|
||||
+ "(default is <origin>.signed).").create('f'));
|
||||
opts.addOption(OptionBuilder.hasArg()
|
||||
.withArgName("KSK file").withLongOpt("ksk-file")
|
||||
.withDescription("this key is the key signing key.")
|
||||
.create('k'));
|
||||
opts.addOption(OptionBuilder.hasArg().withArgName("file")
|
||||
.withLongOpt("include-file")
|
||||
.withDescription("include names in this "
|
||||
+ "file in the NSEC/NSEC3 chain.").create('I'));
|
||||
String[] v = s.split(":");
|
||||
if (v.length < 2) return;
|
||||
|
||||
// NSEC3 options
|
||||
opts.addOption("3", "use-nsec3", false, "use NSEC3 instead of NSEC");
|
||||
opts.addOption("O",
|
||||
"use-opt-in",
|
||||
false,
|
||||
"generate a fully Opt-In zone.");
|
||||
int alias = parseInt(v[0], -1);
|
||||
if (alias <= 0) return;
|
||||
int orig = parseInt(v[1], -1);
|
||||
if (orig <= 0) return;
|
||||
String mn = null;
|
||||
if (v.length > 2) mn = v[2];
|
||||
|
||||
opts.addOption(OptionBuilder.hasArg().withLongOpt("salt")
|
||||
.withArgName("hex value").withDescription("supply a salt value.")
|
||||
.create('S'));
|
||||
opts.addOption(OptionBuilder.hasArg().withLongOpt("random-salt")
|
||||
.withArgName("length").withDescription("generate a random salt.")
|
||||
.create('R'));
|
||||
opts.addOption(OptionBuilder.hasArg().withLongOpt("iterations")
|
||||
.withArgName("value")
|
||||
.withDescription("use this value for the iterations in NSEC3.")
|
||||
.create());
|
||||
algs.addAlias(alias, mn, orig);
|
||||
}
|
||||
|
||||
|
||||
/** Print out the usage and help statements, then quit. */
|
||||
private void usage()
|
||||
{
|
||||
|
@ -33,12 +33,7 @@ import org.apache.commons.cli.*;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.xbill.DNS.*;
|
||||
|
||||
import com.verisignlabs.dnssec.security.BINDKeyUtils;
|
||||
import com.verisignlabs.dnssec.security.DnsKeyPair;
|
||||
import com.verisignlabs.dnssec.security.DnsSecVerifier;
|
||||
import com.verisignlabs.dnssec.security.RecordComparator;
|
||||
import com.verisignlabs.dnssec.security.SignUtils;
|
||||
import com.verisignlabs.dnssec.security.ZoneUtils;
|
||||
import com.verisignlabs.dnssec.security.*;
|
||||
|
||||
/**
|
||||
* This class forms the command line implementation of a DNSSEC zone
|
||||
@ -69,6 +64,40 @@ public class VerifyZone
|
||||
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("s",
|
||||
"strict",
|
||||
false,
|
||||
"Zone will only be considered valid if all "
|
||||
+ "signatures could be cryptographically verified");
|
||||
|
||||
// Argument options
|
||||
opts.addOption(OptionBuilder.hasArg().withLongOpt("keydir")
|
||||
.withArgName("dir").withDescription("directory to find "
|
||||
+ "trusted key files").create('d'));
|
||||
|
||||
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()
|
||||
.withArgName("alias:original:mnemonic").withLongOpt("alg-alias")
|
||||
.withDescription("Define an alias for an algorithm").create('A'));
|
||||
|
||||
}
|
||||
|
||||
public void parseCommandLine(String[] args)
|
||||
throws org.apache.commons.cli.ParseException
|
||||
{
|
||||
@ -105,6 +134,15 @@ public class VerifyZone
|
||||
keydir = new File(optstr);
|
||||
}
|
||||
|
||||
String[] optstrs = null;
|
||||
if ((optstrs = cli.getOptionValues('A')) != null)
|
||||
{
|
||||
for (int i = 0; i < optstrs.length; i++)
|
||||
{
|
||||
addArgAlias(optstrs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
String[] cl_args = cli.getArgs();
|
||||
|
||||
if (cl_args.length < 1)
|
||||
@ -122,40 +160,25 @@ public class VerifyZone
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the command line options.
|
||||
*
|
||||
* @return a set of command line options.
|
||||
*/
|
||||
private void setupCLI()
|
||||
private void addArgAlias(String s)
|
||||
{
|
||||
opts = new Options();
|
||||
|
||||
// boolean options
|
||||
opts.addOption("h", "help", false, "Print this message.");
|
||||
opts.addOption("s",
|
||||
"strict",
|
||||
false,
|
||||
"Zone will only be considered valid if all "
|
||||
+ "signatures could be cryptographically verified");
|
||||
|
||||
// Argument options
|
||||
OptionBuilder.hasArg();
|
||||
OptionBuilder.withLongOpt("keydir");
|
||||
OptionBuilder.withArgName("dir");
|
||||
OptionBuilder.withDescription("directory to find trusted key files");
|
||||
opts.addOption(OptionBuilder.create('d'));
|
||||
|
||||
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'));
|
||||
|
||||
if (s == null) return;
|
||||
|
||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||
|
||||
String[] v = s.split(":");
|
||||
if (v.length < 2) return;
|
||||
|
||||
int alias = parseInt(v[0], -1);
|
||||
if (alias <= 0) return;
|
||||
int orig = parseInt(v[1], -1);
|
||||
if (orig <= 0) return;
|
||||
String mn = null;
|
||||
if (v.length > 2) mn = v[2];
|
||||
|
||||
algs.addAlias(alias, mn, orig);
|
||||
}
|
||||
|
||||
|
||||
/** Print out the usage and help statements, then quit. */
|
||||
public void usage()
|
||||
{
|
||||
@ -209,7 +232,9 @@ public class VerifyZone
|
||||
|
||||
for (Iterator i = keypairs.iterator(); i.hasNext();)
|
||||
{
|
||||
verifier.addTrustedKey((DnsKeyPair) i.next());
|
||||
DnsKeyPair pair = (DnsKeyPair) i.next();
|
||||
if (pair.getPublic() == null) continue;
|
||||
verifier.addTrustedKey(pair);
|
||||
}
|
||||
|
||||
List rrsets = SignUtils.assembleIntoRRsets(records);
|
||||
@ -254,16 +279,17 @@ public class VerifyZone
|
||||
{
|
||||
zonename = r.getName();
|
||||
}
|
||||
|
||||
if (r.getName().equals(zonename) && r.getType() == Type.DNSKEY)
|
||||
|
||||
if (r.getName().equals(zonename) && r.getType() == Type.DNSKEY)
|
||||
{
|
||||
DnsKeyPair pair = new DnsKeyPair((DNSKEYRecord) r);
|
||||
res.add(pair);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static List getTrustedKeys(String[] keyfiles, File inDirectory)
|
||||
throws IOException
|
||||
{
|
||||
@ -283,7 +309,6 @@ public class VerifyZone
|
||||
public static void execute(CLIState state) throws Exception
|
||||
{
|
||||
|
||||
|
||||
List records = ZoneUtils.readZoneFile(state.zonefile, null);
|
||||
List keypairs = null;
|
||||
if (state.keyfiles != null)
|
||||
|
263
src/com/verisignlabs/dnssec/security/DnsKeyAlgorithm.java
Normal file
263
src/com/verisignlabs/dnssec/security/DnsKeyAlgorithm.java
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 2006 VeriSign. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer. 2. Redistributions in
|
||||
* binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution. 3. The name of the author may not
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.verisignlabs.dnssec.security;
|
||||
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Signature;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.xbill.DNS.DNSSEC;
|
||||
|
||||
/**
|
||||
* This class handles translated DNS signing algorithm identifiers into
|
||||
* various usable java implementations.
|
||||
*
|
||||
* Besides centralizing the logic surrounding matching a DNSKEY algorithm
|
||||
* identifier with various crypto implementations, it also handles algorithm
|
||||
* aliasing -- that is, defining a new algorithm identifier to be equivalent
|
||||
* to an existing identifier.
|
||||
*
|
||||
* @author David Blacka (orig)
|
||||
* @author $Author: davidb $ (latest)
|
||||
* @version $Revision: 2098 $
|
||||
*/
|
||||
public class DnsKeyAlgorithm
|
||||
{
|
||||
|
||||
public static final int UNKNOWN = -1;
|
||||
public static final int RSA = 1;
|
||||
public static final int DH = 2;
|
||||
public static final int DSA = 3;
|
||||
|
||||
private static class Entry
|
||||
{
|
||||
public String sigName;
|
||||
public int baseType;
|
||||
|
||||
public Entry(String sigName, int baseType)
|
||||
{
|
||||
this.sigName = sigName;
|
||||
this.baseType = baseType;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a mapping of algorithm identifier to Entry. The Entry contains
|
||||
* the data needed to map the algorithm to the various crypto
|
||||
* implementations.
|
||||
*/
|
||||
private HashMap mAlgorithmMap;
|
||||
/**
|
||||
* This is a mapping of algorithm mnemonics to algorithm identifiers.
|
||||
*/
|
||||
private HashMap mMnemonicToIdMap;
|
||||
/**
|
||||
* This is a mapping of identifiers to preferred mnemonic -- the preferred
|
||||
* one is the first defined one
|
||||
*/
|
||||
private HashMap mIdToMnemonicMap;
|
||||
|
||||
/** This is a cached key pair generator for RSA keys. */
|
||||
private KeyPairGenerator mRSAKeyGenerator;
|
||||
/** This is a cache key pair generator for DSA keys. */
|
||||
private KeyPairGenerator mDSAKeyGenerator;
|
||||
|
||||
private Logger log = Logger.getLogger(this.getClass()
|
||||
.toString());
|
||||
|
||||
/** This is the global instance for this class. */
|
||||
private static DnsKeyAlgorithm mInstance = null;
|
||||
|
||||
public DnsKeyAlgorithm()
|
||||
{
|
||||
mAlgorithmMap = new HashMap();
|
||||
mMnemonicToIdMap = new HashMap();
|
||||
mIdToMnemonicMap = new HashMap();
|
||||
|
||||
// Load the standard DNSSEC algorithms.
|
||||
addAlgorithm(DNSSEC.RSAMD5, new Entry("MD5withRSA", RSA));
|
||||
addMnemonic("RSAMD5", DNSSEC.RSAMD5);
|
||||
|
||||
addAlgorithm(DNSSEC.DH, new Entry("", DH));
|
||||
addMnemonic("DH", DNSSEC.DH);
|
||||
|
||||
addAlgorithm(DNSSEC.DSA, new Entry("SHA1withDSA", DSA));
|
||||
addMnemonic("DSA", DNSSEC.DSA);
|
||||
|
||||
addAlgorithm(DNSSEC.RSASHA1, new Entry("SHA1withRSA", RSA));
|
||||
addMnemonic("RSASHA1", DNSSEC.RSASHA1);
|
||||
addMnemonic("RSA", DNSSEC.RSASHA1);
|
||||
}
|
||||
|
||||
private void addAlgorithm(int algorithm, Entry entry)
|
||||
{
|
||||
Integer a = new Integer(algorithm);
|
||||
mAlgorithmMap.put(a, entry);
|
||||
}
|
||||
|
||||
private void addMnemonic(String m, int alg)
|
||||
{
|
||||
Integer a = new Integer(alg);
|
||||
mMnemonicToIdMap.put(m.toUpperCase(), a);
|
||||
if (! mIdToMnemonicMap.containsKey(a))
|
||||
{
|
||||
mIdToMnemonicMap.put(a, m);
|
||||
}
|
||||
}
|
||||
|
||||
public void addAlias(int alias, String mnemonic, int original_algorithm)
|
||||
{
|
||||
Integer a = new Integer(alias);
|
||||
Integer o = new Integer(original_algorithm);
|
||||
|
||||
if (mAlgorithmMap.containsKey(a))
|
||||
{
|
||||
log.warning("Unable to alias algorithm " + alias
|
||||
+ " because it already exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mAlgorithmMap.containsKey(o))
|
||||
{
|
||||
log.warning("Unable to alias algorith " + alias
|
||||
+ " to unknown algorithm identifier " + original_algorithm);
|
||||
return;
|
||||
}
|
||||
|
||||
mAlgorithmMap.put(a, mAlgorithmMap.get(o));
|
||||
|
||||
if (mnemonic != null)
|
||||
{
|
||||
addMnemonic(mnemonic, alias);
|
||||
}
|
||||
}
|
||||
|
||||
private Entry getEntry(int alg)
|
||||
{
|
||||
return (Entry) mAlgorithmMap.get(new Integer(alg));
|
||||
}
|
||||
|
||||
public Signature getSignature(int algorithm)
|
||||
{
|
||||
Entry entry = getEntry(algorithm);
|
||||
if (entry == null) return null;
|
||||
|
||||
Signature s = null;
|
||||
|
||||
try
|
||||
{
|
||||
s = Signature.getInstance(entry.sigName);
|
||||
}
|
||||
catch (NoSuchAlgorithmException e)
|
||||
{
|
||||
log.severe("Unable to get signature implementation for algorithm "
|
||||
+ algorithm + ": " + e);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public int stringToAlgorithm(String s)
|
||||
{
|
||||
Integer alg = (Integer) mMnemonicToIdMap.get(s.toUpperCase());
|
||||
if (alg != null) return alg.intValue();
|
||||
return -1;
|
||||
}
|
||||
|
||||
public String algToString(int algorithm)
|
||||
{
|
||||
return (String) mIdToMnemonicMap.get(new Integer(algorithm));
|
||||
}
|
||||
|
||||
public int baseType(int algorithm)
|
||||
{
|
||||
Entry entry = getEntry(algorithm);
|
||||
if (entry != null) return entry.baseType;
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public int standardAlgorithm(int algorithm)
|
||||
{
|
||||
switch (baseType(algorithm))
|
||||
{
|
||||
case RSA :
|
||||
return DNSSEC.RSASHA1;
|
||||
case DSA :
|
||||
return DNSSEC.DSA;
|
||||
case DH :
|
||||
return DNSSEC.DH;
|
||||
default :
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDSA(int algorithm)
|
||||
{
|
||||
return (baseType(algorithm) == DSA);
|
||||
}
|
||||
|
||||
public KeyPair generateKeyPair(int algorithm, int keysize)
|
||||
throws NoSuchAlgorithmException
|
||||
{
|
||||
KeyPair pair = null;
|
||||
switch (baseType(algorithm))
|
||||
{
|
||||
case RSA :
|
||||
if (mRSAKeyGenerator == null)
|
||||
{
|
||||
mRSAKeyGenerator = KeyPairGenerator.getInstance("RSA");
|
||||
}
|
||||
mRSAKeyGenerator.initialize(keysize);
|
||||
pair = mRSAKeyGenerator.generateKeyPair();
|
||||
break;
|
||||
case DSA :
|
||||
if (mDSAKeyGenerator == null)
|
||||
{
|
||||
mDSAKeyGenerator = KeyPairGenerator.getInstance("DSA");
|
||||
}
|
||||
mDSAKeyGenerator.initialize(keysize);
|
||||
pair = mDSAKeyGenerator.generateKeyPair();
|
||||
break;
|
||||
default :
|
||||
throw new NoSuchAlgorithmException("Alg " + algorithm);
|
||||
}
|
||||
|
||||
return pair;
|
||||
}
|
||||
|
||||
public static DnsKeyAlgorithm getInstance()
|
||||
{
|
||||
if (mInstance == null) mInstance = new DnsKeyAlgorithm();
|
||||
return mInstance;
|
||||
}
|
||||
}
|
@ -44,7 +44,6 @@ import javax.crypto.spec.DHParameterSpec;
|
||||
import javax.crypto.spec.DHPrivateKeySpec;
|
||||
|
||||
import org.xbill.DNS.DNSKEYRecord;
|
||||
import org.xbill.DNS.DNSSEC;
|
||||
import org.xbill.DNS.KEYRecord;
|
||||
import org.xbill.DNS.Name;
|
||||
import org.xbill.DNS.security.KEYConverter;
|
||||
@ -68,11 +67,35 @@ public class DnsKeyConverter
|
||||
{
|
||||
}
|
||||
|
||||
/** Given a DNS KEY record, return the JCA public key */
|
||||
/**
|
||||
* Given a DNS KEY record, return the JCA public key
|
||||
*
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
public PublicKey parseDNSKEYRecord(DNSKEYRecord pKeyRecord)
|
||||
throws NoSuchAlgorithmException
|
||||
{
|
||||
if (pKeyRecord.getKey() == null) return null;
|
||||
|
||||
// FIXME: this won't work at all with alg aliases.
|
||||
// For now, instead of re-implementing parseRecord (or adding this stuff
|
||||
// to DNSjava), we will just translate the algorithm back to a standard
|
||||
// algorithm. Note that this will unnecessarily convert RSAMD5 to RSASHA1.
|
||||
|
||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||
int standard_alg = algs.standardAlgorithm(pKeyRecord.getAlgorithm());
|
||||
|
||||
if (standard_alg <= 0)
|
||||
throw new NoSuchAlgorithmException("DNSKEY algorithm "
|
||||
+ pKeyRecord.getAlgorithm() + " is unrecognized");
|
||||
|
||||
if (pKeyRecord.getAlgorithm() != standard_alg)
|
||||
{
|
||||
pKeyRecord = new DNSKEYRecord(pKeyRecord.getName(), pKeyRecord
|
||||
.getDClass(), pKeyRecord.getTTL(), pKeyRecord.getFlags(),
|
||||
pKeyRecord.getProtocol(), standard_alg, pKeyRecord.getKey());
|
||||
}
|
||||
|
||||
return KEYConverter.parseRecord(pKeyRecord);
|
||||
}
|
||||
|
||||
@ -104,15 +127,15 @@ public class DnsKeyConverter
|
||||
public PrivateKey convertEncodedPrivateKey(byte[] key, int algorithm)
|
||||
{
|
||||
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(key);
|
||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||
|
||||
try
|
||||
{
|
||||
switch (algorithm)
|
||||
switch (algs.baseType(algorithm))
|
||||
{
|
||||
case DNSSEC.RSAMD5 :
|
||||
case DNSSEC.RSASHA1 :
|
||||
case DnsKeyAlgorithm.RSA :
|
||||
return mRSAKeyFactory.generatePrivate(spec);
|
||||
case DNSSEC.DSA :
|
||||
case DnsKeyAlgorithm.DSA :
|
||||
return mDSAKeyFactory.generatePrivate(spec);
|
||||
}
|
||||
}
|
||||
@ -122,11 +145,23 @@ public class DnsKeyConverter
|
||||
return null;
|
||||
}
|
||||
|
||||
private int parseInt(String s, int def)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Integer.parseInt(s);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a JCA private key, given a BIND9-style textual encoding
|
||||
*/
|
||||
public PrivateKey parsePrivateKeyString(String key) throws IOException,
|
||||
NoSuchAlgorithmException
|
||||
public PrivateKey parsePrivateKeyString(String key)
|
||||
throws IOException, NoSuchAlgorithmException
|
||||
{
|
||||
StringTokenizer lines = new StringTokenizer(key, "\n");
|
||||
|
||||
@ -149,11 +184,24 @@ public class DnsKeyConverter
|
||||
}
|
||||
else if (line.startsWith("Algorithm: "))
|
||||
{
|
||||
if (val.startsWith("1 ")) return parsePrivateRSA(lines);
|
||||
if (val.startsWith("5 ")) return parsePrivateRSA(lines);
|
||||
if (val.startsWith("2 ")) return parsePrivateDH(lines);
|
||||
if (val.startsWith("3 ")) return parsePrivateDSA(lines);
|
||||
throw new IOException("unsupported private key algorithm: " + val);
|
||||
// here we assume that the value looks like # (MNEM) or just the
|
||||
// number.
|
||||
String[] toks = val.split("\\s", 2);
|
||||
val = toks[0];
|
||||
int alg = parseInt(val, -1);
|
||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||
|
||||
switch (algs.baseType(alg))
|
||||
{
|
||||
case DnsKeyAlgorithm.RSA :
|
||||
return parsePrivateRSA(lines);
|
||||
case DnsKeyAlgorithm.DSA :
|
||||
return parsePrivateDSA(lines);
|
||||
case DnsKeyAlgorithm.DH :
|
||||
return parsePrivateDH(lines);
|
||||
default :
|
||||
throw new IOException("unsupported private key algorithm: " + val);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -390,11 +438,11 @@ public class DnsKeyConverter
|
||||
}
|
||||
else if (priv instanceof DSAPrivateKey && pub instanceof DSAPublicKey)
|
||||
{
|
||||
return generatePrivateDSA((DSAPrivateKey) priv, (DSAPublicKey) pub);
|
||||
return generatePrivateDSA((DSAPrivateKey) priv, (DSAPublicKey) pub, alg);
|
||||
}
|
||||
else if (priv instanceof DHPrivateKey && pub instanceof DHPublicKey)
|
||||
{
|
||||
return generatePrivateDH((DHPrivateKey) priv, (DHPublicKey) pub);
|
||||
return generatePrivateDH((DHPrivateKey) priv, (DHPublicKey) pub, alg);
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -426,16 +474,11 @@ public class DnsKeyConverter
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter out = new PrintWriter(sw);
|
||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||
|
||||
out.println("Private-key-format: v1.2");
|
||||
if (algorithm == DNSSEC.RSAMD5)
|
||||
{
|
||||
out.println("Algorithm: 1 (RSAMD5)");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.println("Algorithm: 5 (RSASHA1)");
|
||||
}
|
||||
out.println("Algorithm: " + algorithm + " ("
|
||||
+ algs.algToString(algorithm) + ")");
|
||||
out.print("Modulus: ");
|
||||
out.println(b64BigInt(key.getModulus()));
|
||||
out.print("PublicExponent: ");
|
||||
@ -457,15 +500,18 @@ public class DnsKeyConverter
|
||||
}
|
||||
|
||||
/** Given a DH key pair, return the BIND9-style text encoding */
|
||||
private String generatePrivateDH(DHPrivateKey key, DHPublicKey pub)
|
||||
private String generatePrivateDH(DHPrivateKey key, DHPublicKey pub,
|
||||
int algorithm)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter out = new PrintWriter(sw);
|
||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||
|
||||
DHParameterSpec p = key.getParams();
|
||||
|
||||
out.println("Private-key-format: v1.2");
|
||||
out.println("Algorithm: 2 (DH)");
|
||||
out.println("Algorithm: " + algorithm + " ("
|
||||
+ algs.algToString(algorithm) + ")");
|
||||
out.print("Prime(p): ");
|
||||
out.println(b64BigInt(p.getP()));
|
||||
out.print("Generator(g): ");
|
||||
@ -479,15 +525,18 @@ public class DnsKeyConverter
|
||||
}
|
||||
|
||||
/** Given a DSA key pair, return the BIND9-style text encoding */
|
||||
private String generatePrivateDSA(DSAPrivateKey key, DSAPublicKey pub)
|
||||
private String generatePrivateDSA(DSAPrivateKey key, DSAPublicKey pub,
|
||||
int algorithm)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter out = new PrintWriter(sw);
|
||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||
|
||||
DSAParams p = key.getParams();
|
||||
|
||||
out.println("Private-key-format: v1.2");
|
||||
out.println("Algorithm: 3 (DSA)");
|
||||
out.println("Algorithm: " + algorithm + " ("
|
||||
+ algs.algToString(algorithm) + ")");
|
||||
out.print("Prime(p): ");
|
||||
out.println(b64BigInt(p.getP()));
|
||||
out.print("Subprime(q): ");
|
||||
|
@ -106,7 +106,7 @@ public class DnsKeyPair
|
||||
setDNSKEYRecord(keyRecord);
|
||||
setPrivateKeyString(null);
|
||||
}
|
||||
|
||||
|
||||
public DnsKeyPair(Name keyName, int algorithm, PublicKey publicKey,
|
||||
PrivateKey privateKey)
|
||||
{
|
||||
@ -146,35 +146,8 @@ public class DnsKeyPair
|
||||
/** @return the appropriate Signature object for this keypair. */
|
||||
protected Signature getSignature()
|
||||
{
|
||||
Signature s = null;
|
||||
|
||||
// First try and deduce the algorithm from the KEYRecord (which
|
||||
// will be specific), then try and deduce it from the private key.
|
||||
// We should have one or the other.
|
||||
try
|
||||
{
|
||||
switch (getDNSKEYAlgorithm())
|
||||
{
|
||||
case DNSSEC.RSAMD5 :
|
||||
s = Signature.getInstance("MD5withRSA");
|
||||
break;
|
||||
case DNSSEC.DSA :
|
||||
s = Signature.getInstance("SHA1withDSA");
|
||||
break;
|
||||
case DNSSEC.RSASHA1 :
|
||||
s = Signature.getInstance("SHA1withRSA");
|
||||
break;
|
||||
case -1 :
|
||||
s = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (NoSuchAlgorithmException e)
|
||||
{
|
||||
log.severe("error getting Signature object: " + e);
|
||||
}
|
||||
|
||||
return s;
|
||||
DnsKeyAlgorithm algorithms = DnsKeyAlgorithm.getInstance();
|
||||
return algorithms.getSignature(getDNSKEYAlgorithm());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -184,8 +157,16 @@ public class DnsKeyPair
|
||||
{
|
||||
if (mPublicKey == null && getDNSKEYRecord() != null)
|
||||
{
|
||||
DnsKeyConverter conv = getKeyConverter();
|
||||
setPublic(conv.parseDNSKEYRecord(getDNSKEYRecord()));
|
||||
try
|
||||
{
|
||||
DnsKeyConverter conv = getKeyConverter();
|
||||
setPublic(conv.parseDNSKEYRecord(getDNSKEYRecord()));
|
||||
}
|
||||
catch (NoSuchAlgorithmException e)
|
||||
{
|
||||
log.severe(e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return mPublicKey;
|
||||
@ -220,6 +201,7 @@ public class DnsKeyPair
|
||||
|
||||
/**
|
||||
* @return the opaque private key string, null if one doesn't exist.
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
public String getPrivateKeyString()
|
||||
{
|
||||
@ -304,6 +286,7 @@ public class DnsKeyPair
|
||||
/**
|
||||
* @return a Signature object initialized for verifying, or null if this key
|
||||
* pair does not have a valid public key.
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
public Signature getVerifier()
|
||||
{
|
||||
|
@ -263,14 +263,18 @@ public class DnsSecVerifier implements Verifier
|
||||
{
|
||||
byte[] data = SignUtils.generateSigData(rrset, sigrec);
|
||||
|
||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||
|
||||
Signature signer = keypair.getVerifier();
|
||||
signer.update(data);
|
||||
|
||||
byte[] sig = sigrec.getSignature();
|
||||
if (sigrec.getAlgorithm() == DNSSEC.DSA)
|
||||
|
||||
if (algs.baseType(sigrec.getAlgorithm()) == DnsKeyAlgorithm.DSA)
|
||||
{
|
||||
sig = SignUtils.convertDSASignature(sig);
|
||||
}
|
||||
|
||||
if (!signer.verify(sig))
|
||||
{
|
||||
log.info("Signature failed to verify cryptographically");
|
||||
|
@ -22,7 +22,6 @@ package com.verisignlabs.dnssec.security;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Signature;
|
||||
import java.security.interfaces.DSAPublicKey;
|
||||
@ -34,7 +33,6 @@ import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.xbill.DNS.DNSKEYRecord;
|
||||
import org.xbill.DNS.DNSSEC;
|
||||
import org.xbill.DNS.Name;
|
||||
import org.xbill.DNS.RRSIGRecord;
|
||||
import org.xbill.DNS.RRset;
|
||||
@ -54,10 +52,7 @@ import org.xbill.DNS.Type;
|
||||
*/
|
||||
public class JCEDnsSecSigner
|
||||
{
|
||||
private DnsKeyConverter mKeyConverter;
|
||||
|
||||
private KeyPairGenerator mRSAKeyGenerator;
|
||||
private KeyPairGenerator mDSAKeyGenerator;
|
||||
private DnsKeyConverter mKeyConverter;
|
||||
|
||||
/**
|
||||
* Cryptographically generate a new DNSSEC key.
|
||||
@ -73,32 +68,11 @@ public class JCEDnsSecSigner
|
||||
public DnsKeyPair generateKey(Name owner, long ttl, int dclass,
|
||||
int algorithm, int flags, int keysize) throws NoSuchAlgorithmException
|
||||
{
|
||||
KeyPair pair;
|
||||
DnsKeyAlgorithm algorithms = DnsKeyAlgorithm.getInstance();
|
||||
|
||||
if (ttl < 0) ttl = 86400; // set to a reasonable default.
|
||||
|
||||
switch (algorithm)
|
||||
{
|
||||
case DNSSEC.RSAMD5 :
|
||||
case DNSSEC.RSASHA1 :
|
||||
if (mRSAKeyGenerator == null)
|
||||
{
|
||||
mRSAKeyGenerator = KeyPairGenerator.getInstance("RSA");
|
||||
}
|
||||
mRSAKeyGenerator.initialize(keysize);
|
||||
pair = mRSAKeyGenerator.generateKeyPair();
|
||||
break;
|
||||
case DNSSEC.DSA :
|
||||
if (mDSAKeyGenerator == null)
|
||||
{
|
||||
mDSAKeyGenerator = KeyPairGenerator.getInstance("DSA");
|
||||
}
|
||||
mDSAKeyGenerator.initialize(keysize);
|
||||
pair = mDSAKeyGenerator.generateKeyPair();
|
||||
break;
|
||||
default :
|
||||
throw new NoSuchAlgorithmException("Alg " + algorithm);
|
||||
}
|
||||
KeyPair pair = algorithms.generateKeyPair(algorithm, keysize);
|
||||
|
||||
if (mKeyConverter == null)
|
||||
{
|
||||
@ -111,6 +85,7 @@ public class JCEDnsSecSigner
|
||||
flags,
|
||||
algorithm,
|
||||
pair.getPublic());
|
||||
|
||||
DnsKeyPair dnspair = new DnsKeyPair();
|
||||
dnspair.setDNSKEYRecord(keyrec);
|
||||
dnspair.setPublic(pair.getPublic()); // keep from conv. the keyrec back.
|
||||
@ -173,11 +148,12 @@ public class JCEDnsSecSigner
|
||||
signer.update(sign_data);
|
||||
byte[] sig = signer.sign();
|
||||
|
||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||
// Convert to RFC 2536 format, if necessary.
|
||||
if (pair.getDNSKEYAlgorithm() == DNSSEC.DSA)
|
||||
if (algs.baseType(pair.getDNSKEYAlgorithm()) == DnsKeyAlgorithm.DSA)
|
||||
{
|
||||
sig = SignUtils.convertDSASignature(((DSAPublicKey) pair.getPublic()).getParams(),
|
||||
sig);
|
||||
sig = SignUtils.convertDSASignature(((DSAPublicKey) pair.getPublic())
|
||||
.getParams(), sig);
|
||||
}
|
||||
RRSIGRecord sigrec = SignUtils.generateRRSIG(sig, presig);
|
||||
sigs.add(sigrec);
|
||||
@ -234,8 +210,8 @@ public class JCEDnsSecSigner
|
||||
*/
|
||||
private Name addRRset(List toList, Name zonename, RRset rrset,
|
||||
List keysigningkeypairs, List zonekeypairs, Date start, Date expire,
|
||||
boolean fullySignKeyset, Name last_cut) throws IOException,
|
||||
GeneralSecurityException
|
||||
boolean fullySignKeyset, Name last_cut)
|
||||
throws IOException, GeneralSecurityException
|
||||
{
|
||||
// add the records themselves
|
||||
for (Iterator i = rrset.rrs(); i.hasNext();)
|
||||
@ -243,10 +219,8 @@ public class JCEDnsSecSigner
|
||||
toList.add(i.next());
|
||||
}
|
||||
|
||||
int type = SignUtils.recordSecType(zonename,
|
||||
rrset.getName(),
|
||||
rrset.getType(),
|
||||
last_cut);
|
||||
int type = SignUtils.recordSecType(zonename, rrset.getName(), rrset
|
||||
.getType(), last_cut);
|
||||
|
||||
// we don't sign non-normal sets (delegations, glue, invalid).
|
||||
// we also don't sign the zone key set unless we've been asked.
|
||||
|
@ -157,13 +157,6 @@ public class SignUtils
|
||||
// Caculate the offset where the RDATA begins (we have to skip
|
||||
// past the length byte)
|
||||
|
||||
// FIXME: currently, draft-ietf-dnsext-dnssec-records-06 has us
|
||||
// sorting by length first, then bytes. This can be accomplished
|
||||
// by not skipping past the RDLENGTH field, I think.
|
||||
// FIXME update: I pointed this out as an error, and subsequent
|
||||
// versions should correct this, setting the standard back to
|
||||
// bytes, then length.
|
||||
|
||||
int offset = rrset.getName().toWireCanonical().length + 10;
|
||||
ByteArrayComparator bac = new ByteArrayComparator(offset, false);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user