Compare commits

..

No commits in common. "33b4630f4bef0c44616b062e7013f1da0d4cfc9c" and "6118ae718ea974821bef43142d9b2afdfb67c9e3" have entirely different histories.

31 changed files with 1575 additions and 1008 deletions

6
.gitattributes vendored Normal file
View File

@ -0,0 +1,6 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf

25
build.gradle Normal file
View File

@ -0,0 +1,25 @@
/**
Declares dependencies for Jdnssec-tools
**/
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
jar {
baseName = 'jdnssec-tools'
version = '0.17.1'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile fileTree(dir: 'lib', include: '*.jar')
}

View File

@ -1,2 +1,3 @@
#build.compiler=jikes
#build.compiler=modern
build.deprecation=true build.deprecation=true
build.debug=true

View File

@ -44,11 +44,11 @@
<javac srcdir="${build.src}" <javac srcdir="${build.src}"
destdir="${build.dest}" destdir="${build.dest}"
classpathref="project.classpath" classpathref="project.classpath"
deprecation="${build.deprecation}" deprecation="true"
includeantruntime="false" includeantruntime="false"
includes="com/verisignlabs/dnssec/" includes="com/verisignlabs/dnssec/"
debug="${build.debug}" source="17"
release="17" /> target="17" />
</target> </target>
<target name="sectools-jar" depends="usage,sectools"> <target name="sectools-jar" depends="usage,sectools">
@ -154,11 +154,13 @@
<target name="dist" depends="sectools-dist"> <target name="dist" depends="sectools-dist">
<echo message="do not forget to tag the release:" />
<echo message=" svn-tag ${version}" />
</target> </target>
<target name="usage"> <target name="usage">
<echo message=" " /> <echo message=" " />
<echo message="jdnssec-tools v. ${version} Build System" /> <echo message="SECTOOLS v. ${version} Build System" />
<echo message="--------------------------------" /> <echo message="--------------------------------" />
<echo message="Available Targets:" /> <echo message="Available Targets:" />
<echo message=" compile (default) - compiles the source code, creates jar" /> <echo message=" compile (default) - compiles the source code, creates jar" />

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

185
gradlew vendored Executable file
View File

@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
gradlew.bat vendored Normal file
View File

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

BIN
lib/commons-cli-1.5.0.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/eddsa-0.3.0.jar Normal file

Binary file not shown.

View File

@ -56,7 +56,7 @@ public class DSTool extends CLBase {
public dsType createType = dsType.DS; public dsType createType = dsType.DS;
public String outputfile = null; public String outputfile = null;
public String keyname = null; public String keyname = null;
public int digestId = DNSSEC.Digest.SHA256; public int digestId = DNSSEC.Digest.SHA1;
public CLIState() { public CLIState() {
super("jdnssec-dstool [..options..] keyfile"); super("jdnssec-dstool [..options..] keyfile");
@ -71,8 +71,7 @@ public class DSTool extends CLBase {
protected void setupOptions(Options opts) { protected void setupOptions(Options opts) {
opts.addOption(Option.builder("D").longOpt("dlv").desc("Generate a DLV record instead.").build()); opts.addOption(Option.builder("D").longOpt("dlv").desc("Generate a DLV record instead.").build());
opts.addOption(Option.builder("C").longOpt("cds").desc("Generate a CDS record instead").build()); opts.addOption(Option.builder("C").longOpt("cds").desc("Generate a CDS record instead").build());
opts.addOption( opts.addOption(Option.builder("d").hasArg().argName("id").longOpt("digest").desc("The digest algorithm to use").build());
Option.builder("d").hasArg().argName("id").longOpt("digest").desc("The digest algorithm to use").build());
opts.addOption(Option.builder("f").hasArg().argName("file").longOpt("output").desc("output to file").build()); opts.addOption(Option.builder("f").hasArg().argName("file").longOpt("output").desc("output to file").build());
} }
@ -121,9 +120,9 @@ public class DSTool extends CLBase {
log.fine("creating CDS."); log.fine("creating CDS.");
CDSRecord cds = new CDSRecord(ds.getName(), ds.getDClass(), ds.getTTL(), ds.getFootprint(), ds.getAlgorithm(), CDSRecord cds = new CDSRecord(ds.getName(), ds.getDClass(), ds.getTTL(), ds.getFootprint(), ds.getAlgorithm(),
ds.getDClass(), ds.getDigest()); ds.getDClass(), ds.getDigest());
res = cds; res = cds;
} }
if (state.outputfile != null && !state.outputfile.equals("-")) { if (state.outputfile != null && !state.outputfile.equals("-")) {
try (PrintWriter out = new PrintWriter(new FileWriter(state.outputfile))) { try (PrintWriter out = new PrintWriter(new FileWriter(state.outputfile))) {
out.println(res); out.println(res);

View File

@ -44,8 +44,8 @@ public class KeyGen extends CLBase {
* state. * state.
*/ */
protected static class CLIState extends CLIStateBase { protected static class CLIState extends CLIStateBase {
public int algorithm = 13; public int algorithm = 8;
public int keylength = 2048; public int keylength = 1024;
public boolean useLargeE = true; public boolean useLargeE = true;
public String outputfile = null; public String outputfile = null;
public File keydir = null; public File keydir = null;
@ -77,10 +77,10 @@ public class KeyGen extends CLBase {
String[] algStrings = DnsKeyAlgorithm.getInstance().supportedAlgMnemonics(); String[] algStrings = DnsKeyAlgorithm.getInstance().supportedAlgMnemonics();
String algStringSet = String.join(" | ", algStrings); String algStringSet = String.join(" | ", algStrings);
opts.addOption(Option.builder("a").hasArg().argName("algorithm") opts.addOption(Option.builder("a").hasArg().argName("algorithm")
.desc(algStringSet + " | alias, ECDSAP256SHA256 is default.").build()); .desc(algStringSet + " | alias, RSASHA256 is default.").build());
opts.addOption(Option.builder("b").hasArg().argName("size").desc( opts.addOption(Option.builder("b").hasArg().argName("size").desc(
"key size, in bits (default 2048). RSA: [512..4096], DSA: [512..1024], DH: [128..4096], ECDSA: ignored, EdDSA: ignored") "key size, in bits (default 1024). RSA: [512..4096], DSA: [512..1024], DH: [128..4096], ECDSA: ignored, EdDSA: ignored")
.build()); .build());
opts.addOption(Option.builder("f").hasArg().argName("file").longOpt("output-file") opts.addOption(Option.builder("f").hasArg().argName("file").longOpt("output-file")
.desc("base filename from the public/private key files").build()); .desc("base filename from the public/private key files").build());

View File

@ -84,13 +84,13 @@ public class KeyInfoTool extends CLBase {
+ " (" + dnskey.getAlgorithm() + ")"); + " (" + dnskey.getAlgorithm() + ")");
System.out.println("ID: " + dnskey.getFootprint()); System.out.println("ID: " + dnskey.getFootprint());
System.out.println("KeyFileBase: " + BINDKeyUtils.keyFileBase(key)); System.out.println("KeyFileBase: " + BINDKeyUtils.keyFileBase(key));
DnsKeyAlgorithm.BaseAlgorithm basetype = dnskeyalg.baseType(dnskey.getAlgorithm()); int basetype = dnskeyalg.baseType(dnskey.getAlgorithm());
if (basetype == DnsKeyAlgorithm.BaseAlgorithm.RSA) { if (basetype == DnsKeyAlgorithm.RSA) {
RSAPublicKey pub = (RSAPublicKey) key.getPublic(); RSAPublicKey pub = (RSAPublicKey) key.getPublic();
System.out.println("RSA Public Exponent: " + pub.getPublicExponent()); System.out.println("RSA Public Exponent: " + pub.getPublicExponent());
System.out.println("RSA Modulus: " + pub.getModulus()); System.out.println("RSA Modulus: " + pub.getModulus());
} else if (basetype == DnsKeyAlgorithm.BaseAlgorithm.DSA) { } else if (basetype == DnsKeyAlgorithm.DSA) {
DSAPublicKey pub = (DSAPublicKey) key.getPublic(); DSAPublicKey pub = (DSAPublicKey) key.getPublic();
System.out.println("DSA base (G): " + pub.getParams().getG()); System.out.println("DSA base (G): " + pub.getParams().getG());
System.out.println("DSA prime (P): " + pub.getParams().getP()); System.out.println("DSA prime (P): " + pub.getParams().getP());

View File

@ -75,14 +75,10 @@ public class SignKeyset extends CLBase {
opts.addOption("a", "verify", false, "verify generated signatures>"); opts.addOption("a", "verify", false, "verify generated signatures>");
// Argument options // Argument options
opts.addOption(Option.builder("D").hasArg().argName("dir").longOpt("key-directory") opts.addOption(Option.builder("D").hasArg().argName("dir").longOpt("key-directory").desc("directory where key files are found (default '.').").build());
.desc("directory where key files are found (default '.').").build()); opts.addOption(Option.builder("s").hasArg().argName("time/offset").longOpt("start-time").desc("signature starting time (default is now - 1 hour)").build());
opts.addOption(Option.builder("s").hasArg().argName("time/offset").longOpt("start-time") opts.addOption(Option.builder("e").hasArg().argName("time/offset").longOpt("expire-time").desc("signature expiration time (default is start-time + 30 days)").build());
.desc("signature starting time (default is now - 1 hour)").build()); opts.addOption(Option.builder("f").hasArg().argName("outfile").desc("file the signed keyset is written to").build());
opts.addOption(Option.builder("e").hasArg().argName("time/offset").longOpt("expire-time")
.desc("signature expiration time (default is start-time + 30 days)").build());
opts.addOption(
Option.builder("f").hasArg().argName("outfile").desc("file the signed keyset is written to").build());
} }
@Override @Override
@ -133,9 +129,11 @@ public class SignKeyset extends CLBase {
/** /**
* Verify the generated signatures. * Verify the generated signatures.
* *
* @param records a list of {@link org.xbill.DNS.Record}s. * @param records
* @param keypairs a list of keypairs used the sign the zone. * a list of {@link org.xbill.DNS.Record}s.
* @param keypairs
* a list of keypairs used the sign the zone.
* @return true if all of the signatures validated. * @return true if all of the signatures validated.
*/ */
private static boolean verifySigs(List<Record> records, private static boolean verifySigs(List<Record> records,
@ -170,13 +168,16 @@ public class SignKeyset extends CLBase {
/** /**
* Load the key pairs from the key files. * Load the key pairs from the key files.
* *
* @param keyfiles a string array containing the base names or paths of the * @param keyfiles
* keys to be loaded. * a string array containing the base names or paths of the
* @param startIndex the starting index of keyfiles string array to use. This * keys
* allows us to use the straight command line argument * to be loaded.
* array. * @param startIndex
* @param inDirectory the directory to look in (may be null). * the starting index of keyfiles string array to use. This
* allows us to use the straight command line argument array.
* @param inDirectory
* the directory to look in (may be null).
* @return a list of keypair objects. * @return a list of keypair objects.
*/ */
private static List<DnsKeyPair> getKeys(String[] keyfiles, int startIndex, private static List<DnsKeyPair> getKeys(String[] keyfiles, int startIndex,
@ -243,8 +244,8 @@ public class SignKeyset extends CLBase {
} }
// Make sure that all records are DNSKEYs with the same name. // Make sure that all records are DNSKEYs with the same name.
Name keysetName = null; Name keysetName = null;
RRset keyset = new RRset(); RRset keyset = new RRset();
for (Record r : records) { for (Record r : records) {
if (r.getType() != Type.DNSKEY) { if (r.getType() != Type.DNSKEY) {

View File

@ -55,14 +55,14 @@ public class SignRRset extends CLBase {
* This is an inner class used to hold all of the command line option state. * This is an inner class used to hold all of the command line option state.
*/ */
protected static class CLIState extends CLIStateBase { protected static class CLIState extends CLIStateBase {
private File keyDirectory = null; private File keyDirectory = null;
public String[] keyFiles = null; public String[] keyFiles = null;
public Instant start = null; public Instant start = null;
public Instant expire = null; public Instant expire = null;
public String inputfile = null; public String inputfile = null;
public String outputfile = null; public String outputfile = null;
public boolean verifySigs = false; public boolean verifySigs = false;
public boolean verboseSigning = false; public boolean verboseSigning = false;
public CLIState() { public CLIState() {
super("jdnssec-signrrset [..options..] rrset_file key_file [key_file ...]"); super("jdnssec-signrrset [..options..] rrset_file key_file [key_file ...]");
@ -137,8 +137,10 @@ public class SignRRset extends CLBase {
/** /**
* Verify the generated signatures. * Verify the generated signatures.
* *
* @param records a list of {@link org.xbill.DNS.Record}s. * @param records
* @param keypairs a list of keypairs used the sign the zone. * a list of {@link org.xbill.DNS.Record}s.
* @param keypairs
* a list of keypairs used the sign the zone.
* @return true if all of the signatures validated. * @return true if all of the signatures validated.
*/ */
private static boolean verifySigs(List<Record> records, List<DnsKeyPair> keypairs) { private static boolean verifySigs(List<Record> records, List<DnsKeyPair> keypairs) {
@ -174,12 +176,15 @@ public class SignRRset extends CLBase {
/** /**
* Load the key pairs from the key files. * Load the key pairs from the key files.
* *
* @param keyfiles a string array containing the base names or paths of the * @param keyfiles
* keys to be loaded. * a string array containing the base names or paths of the
* @param startIndex the starting index of keyfiles string array to use. This * keys
* allows us to use the straight command line argument * to be loaded.
* array. * @param startIndex
* @param inDirectory the directory to look in (may be null). * the starting index of keyfiles string array to use. This
* allows us to use the straight command line argument array.
* @param inDirectory
* the directory to look in (may be null).
* @return a list of keypair objects. * @return a list of keypair objects.
*/ */
private static List<DnsKeyPair> getKeys(String[] keyfiles, int startIndex, private static List<DnsKeyPair> getKeys(String[] keyfiles, int startIndex,

View File

@ -79,8 +79,6 @@ public class SignZone extends CLBase {
public long nsec3paramttl = -1; public long nsec3paramttl = -1;
public boolean verboseSigning = false; public boolean verboseSigning = false;
private static final Random rand = new Random();
public CLIState() { public CLIState() {
super("jdnssec-signzone [..options..] zone_file [key_file ...]"); super("jdnssec-signzone [..options..] zone_file [key_file ...]");
} }
@ -200,8 +198,9 @@ public class SignZone extends CLBase {
if ((optstr = cli.getOptionValue('R')) != null) { if ((optstr = cli.getOptionValue('R')) != null) {
int length = parseInt(optstr, 0); int length = parseInt(optstr, 0);
if (length > 0 && length <= 255) { if (length > 0 && length <= 255) {
Random random = new Random();
salt = new byte[length]; salt = new byte[length];
rand.nextBytes(salt); random.nextBytes(salt);
} }
} }
@ -242,8 +241,8 @@ public class SignZone extends CLBase {
/** /**
* Load a list of DNS names from a file. * Load a list of DNS names from a file.
* *
* @param nameListFile the path of a file containing a bare list of DNS * @param nameListFile
* names. * the path of a file containing a bare list of DNS names.
* @return a list of {@link org.xbill.DNS.Name} objects. * @return a list of {@link org.xbill.DNS.Name} objects.
*/ */
private static List<Name> getNameList(File nameListFile) throws IOException { private static List<Name> getNameList(File nameListFile) throws IOException {
@ -255,6 +254,9 @@ public class SignZone extends CLBase {
try { try {
Name n = Name.fromString(line); Name n = Name.fromString(line);
// force the name to be absolute. // force the name to be absolute.
// FIXME: we should probably get some fancy logic here to
// detect if the name needs the origin appended, or just the
// root.
if (!n.isAbsolute()) if (!n.isAbsolute())
n = Name.concatenate(n, Name.root); n = Name.concatenate(n, Name.root);
@ -272,12 +274,14 @@ public class SignZone extends CLBase {
/** /**
* Verify the generated signatures. * Verify the generated signatures.
* *
* @param records a list of {@link org.xbill.DNS.Record}s. * @param records
* @param keypairs a list of keypairs used the sign the zone. * a list of {@link org.xbill.DNS.Record}s.
* @param keypairs
* a list of keypairs used the sign the zone.
* @return true if all of the signatures validated. * @return true if all of the signatures validated.
*/ */
private static boolean verifyZoneSigs(List<Record> records, private static boolean verifyZoneSigs(List<Record> records,
List<DnsKeyPair> keypairs, List<DnsKeyPair> kskpairs) { List<DnsKeyPair> keypairs) {
boolean secure = true; boolean secure = true;
DnsSecVerifier verifier = new DnsSecVerifier(); DnsSecVerifier verifier = new DnsSecVerifier();
@ -285,9 +289,7 @@ public class SignZone extends CLBase {
for (DnsKeyPair pair : keypairs) { for (DnsKeyPair pair : keypairs) {
verifier.addTrustedKey(pair); verifier.addTrustedKey(pair);
} }
for (DnsKeyPair pair : kskpairs) {
verifier.addTrustedKey(pair);
}
verifier.setVerifyAllSigs(true); verifier.setVerifyAllSigs(true);
List<RRset> rrsets = SignUtils.assembleIntoRRsets(records); List<RRset> rrsets = SignUtils.assembleIntoRRsets(records);
@ -301,7 +303,6 @@ public class SignZone extends CLBase {
boolean result = verifier.verify(rrset); boolean result = verifier.verify(rrset);
if (!result) { if (!result) {
System.err.println("Signatures did not verify for RRset: " + rrset);
staticLog.fine("Signatures did not verify for RRset: " + rrset); staticLog.fine("Signatures did not verify for RRset: " + rrset);
secure = false; secure = false;
} }
@ -313,12 +314,17 @@ public class SignZone extends CLBase {
/** /**
* Load the key pairs from the key files. * Load the key pairs from the key files.
* *
* @param keyfiles a string array containing the base names or paths of the * @param keyfiles
* keys to be loaded. * a string array containing the base names or paths of the
* @param startIndex the starting index of keyfiles string array to use. This * keys to
* allows us to use the straight command line argument * be loaded.
* array. * @param startIndex
* @param inDirectory the directory to look in (may be null). * the starting index of keyfiles string array to use. This
* allows
* us
* to use the straight command line argument array.
* @param inDirectory
* the directory to look in (may be null).
* @return a list of keypair objects. * @return a list of keypair objects.
*/ */
private static List<DnsKeyPair> getKeys(String[] keyfiles, int startIndex, private static List<DnsKeyPair> getKeys(String[] keyfiles, int startIndex,
@ -412,12 +418,19 @@ public class SignZone extends CLBase {
/** /**
* Load keysets (which contain delegation point security info). * Load keysets (which contain delegation point security info).
* *
* @param inDirectory the directory to look for the keyset files (may be null, * @param inDirectory
* in which case it defaults to looking in the current * the directory to look for the keyset files (may be null,
* working directory). * in
* @param zonename the name of the zone we are signing, so we can ignore * which
* keysets that do not belong in the zone. * case it defaults to looking in the current working
* @return a list of {@link org.xbill.DNS.Record}s found in the keyset files. * directory).
* @param zonename
* the name of the zone we are signing, so we can ignore
* keysets
* that
* do not belong in the zone.
* @return a list of {@link org.xbill.DNS.Record}s found in the keyset
* files.
*/ */
private static List<Record> getKeysets(File inDirectory, Name zonename) private static List<Record> getKeysets(File inDirectory, Name zonename)
throws IOException { throws IOException {
@ -450,9 +463,13 @@ public class SignZone extends CLBase {
/** /**
* Determine if the given keypairs can be used to sign the zone. * Determine if the given keypairs can be used to sign the zone.
* *
* @param zonename the zone origin. * @param zonename
* @param keypairs a list of {@link DnsKeyPair} objects that will be used to * the zone origin.
* sign the zone. * @param keypairs
* a list of {@link DnsKeyPair} objects that will be used to
* sign
* the
* zone.
* @return true if the keypairs valid. * @return true if the keypairs valid.
*/ */
private static boolean keyPairsValidForZone(Name zonename, List<DnsKeyPair> keypairs) { private static boolean keyPairsValidForZone(Name zonename, List<DnsKeyPair> keypairs) {
@ -486,70 +503,55 @@ public class SignZone extends CLBase {
return; return;
} }
// Load the key pairs. Note that getKeys() always returns array. // Load the key pairs.
List<DnsKeyPair> keypairs = getKeys(state.keyFiles, 0, state.keyDirectory); List<DnsKeyPair> keypairs = getKeys(state.keyFiles, 0, state.keyDirectory);
List<DnsKeyPair> kskpairs = getKeys(state.kskFiles, 0, state.keyDirectory); List<DnsKeyPair> kskpairs = getKeys(state.kskFiles, 0, state.keyDirectory);
// If we didn't get any keys on the command line, look at the zone apex for // If we didn't get any keys on the command line, look at the zone apex for
// any public keys. // any public keys.
if (keypairs.isEmpty()) { if (keypairs == null && kskpairs == null) {
List<Record> dnskeys = ZoneUtils.findRRs(records, zonename, Type.DNSKEY); List<Record> dnskeys = ZoneUtils.findRRs(records, zonename, Type.DNSKEY);
keypairs = getKeys(dnskeys, state.keyDirectory); keypairs = getKeys(dnskeys, state.keyDirectory);
} }
// If we *still* don't have any key pairs, look for keys the key directory // If we *still* don't have any key pairs, look for keys the key directory
// that match // that match
if (keypairs.isEmpty()) { if (keypairs == null && kskpairs == null) {
keypairs = findZoneKeys(state.keyDirectory, zonename); keypairs = findZoneKeys(state.keyDirectory, zonename);
} }
// If we don't have any KSKs, but we do have more than one zone // If we don't have any KSKs, but we do have more than one zone
// signing key (presumably), presume that the zone signing keys // signing key (presumably), presume that the zone signing keys
// are just not differentiated and try to figure out which keys // are just not differentiated and try to figure out which keys
// are actually KSKs by looking at the SEP flag. // are actually ksks by looking at the SEP flag.
if (kskpairs.isEmpty() && !keypairs.isEmpty()) { if ((kskpairs == null || kskpairs.isEmpty()) && keypairs != null
&& keypairs.size() > 1) {
for (Iterator<DnsKeyPair> i = keypairs.iterator(); i.hasNext();) { for (Iterator<DnsKeyPair> i = keypairs.iterator(); i.hasNext();) {
DnsKeyPair pair = i.next(); DnsKeyPair pair = i.next();
DNSKEYRecord kr = pair.getDNSKEYRecord(); DNSKEYRecord kr = pair.getDNSKEYRecord();
if ((kr.getFlags() & DNSKEYRecord.Flags.SEP_KEY) != 0) { if ((kr.getFlags() & DNSKEYRecord.Flags.SEP_KEY) != 0) {
if (kskpairs == null)
kskpairs = new ArrayList<>();
kskpairs.add(pair); kskpairs.add(pair);
i.remove(); i.remove();
} }
} }
} }
// If we have zero keypairs at all, we are stuck. // If there are no ZSKs defined at this point (yet there are KSKs
if (keypairs.isEmpty() && kskpairs.isEmpty()) { // provided), all KSKs will be treated as ZSKs, as well.
if (keypairs == null || keypairs.isEmpty()) {
keypairs = kskpairs;
}
// If there *still* aren't any ZSKs defined, bail.
if (keypairs == null || keypairs.isEmpty()) {
System.err.println("No zone signing keys could be determined."); System.err.println("No zone signing keys could be determined.");
state.usage(); state.usage();
return; return;
} }
// If we only have one type of key (all ZSKs or all KSKs), then these are
// "CSKs" -- Combined signing keys, so assign one set to the other.
if (keypairs.isEmpty()) {
keypairs = kskpairs;
} else if (kskpairs.isEmpty()) {
kskpairs = keypairs;
}
// Output what keys we are using for what
if (keypairs == kskpairs) {
System.out.println("CSKs: ");
for (DnsKeyPair kp : keypairs) {
System.out.println(" - " + kp);
}
} else {
System.out.println("KSKs: ");
for (DnsKeyPair kp : kskpairs) {
System.out.println(" - " + kp);
}
System.out.println("ZSKs: ");
for (DnsKeyPair kp : keypairs) {
System.out.println(" - " + kp);
}
}
// default the output file, if not set. // default the output file, if not set.
if (state.outputfile == null && !state.zonefile.equals("-")) { if (state.outputfile == null && !state.zonefile.equals("-")) {
if (zonename.isAbsolute()) { if (zonename.isAbsolute()) {
@ -569,12 +571,12 @@ public class SignZone extends CLBase {
// We force the signing keys to be in the zone by just appending // We force the signing keys to be in the zone by just appending
// them to the zone here. Currently JCEDnsSecSigner.signZone // them to the zone here. Currently JCEDnsSecSigner.signZone
// removes duplicate records. // removes duplicate records.
if (!kskpairs.isEmpty()) { if (kskpairs != null) {
for (DnsKeyPair pair : kskpairs) { for (DnsKeyPair pair : kskpairs) {
records.add(pair.getDNSKEYRecord()); records.add(pair.getDNSKEYRecord());
} }
} }
if (!keypairs.isEmpty()) { if (keypairs != null) {
for (DnsKeyPair pair : keypairs) { for (DnsKeyPair pair : keypairs) {
records.add(pair.getDNSKEYRecord()); records.add(pair.getDNSKEYRecord());
} }
@ -606,11 +608,15 @@ public class SignZone extends CLBase {
// write out the signed zone // write out the signed zone
ZoneUtils.writeZoneFile(signedRecords, state.outputfile); ZoneUtils.writeZoneFile(signedRecords, state.outputfile);
System.out.println("zone signing complete");
if (state.verifySigs) { if (state.verifySigs) {
// FIXME: ugh.
if (kskpairs != null) {
keypairs.addAll(kskpairs);
}
log.fine("verifying generated signatures"); log.fine("verifying generated signatures");
boolean res = verifyZoneSigs(signedRecords, keypairs, kskpairs); boolean res = verifyZoneSigs(signedRecords, keypairs);
if (res) { if (res) {
System.out.println("Generated signatures verified"); System.out.println("Generated signatures verified");
@ -618,6 +624,7 @@ public class SignZone extends CLBase {
System.out.println("Generated signatures did not verify."); System.out.println("Generated signatures did not verify.");
} }
} }
} }
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -100,6 +100,7 @@ public class ZoneFormat extends CLBase {
private static void formatZone(List<Record> zone) { private static void formatZone(List<Record> zone) {
for (Record r : zone) { for (Record r : zone) {
System.out.println(r.toString()); System.out.println(r.toString());
} }

View File

@ -46,8 +46,7 @@ import org.xbill.DNS.utils.base64;
*/ */
public class BINDKeyUtils { public class BINDKeyUtils {
private BINDKeyUtils() { private BINDKeyUtils() { }
}
/** /**
* Calculate the BIND9 key file base name (i.e., without the ".key" or * Calculate the BIND9 key file base name (i.e., without the ".key" or
@ -61,18 +60,18 @@ public class BINDKeyUtils {
/** Reads in the DNSKEYRecord from the public key file */ /** Reads in the DNSKEYRecord from the public key file */
private static DNSKEYRecord loadPublicKeyFile(File publicKeyFile) private static DNSKEYRecord loadPublicKeyFile(File publicKeyFile)
throws IOException { throws IOException {
try (Master m = new Master(publicKeyFile.getAbsolutePath(), null, 600)) { Master m = new Master(publicKeyFile.getAbsolutePath(), null, 600);
Record r;
DNSKEYRecord result = null;
while ((r = m.nextRecord()) != null) { Record r;
if (r.getType() == Type.DNSKEY) { DNSKEYRecord result = null;
result = (DNSKEYRecord) r;
} while ((r = m.nextRecord()) != null) {
if (r.getType() == Type.DNSKEY) {
result = (DNSKEYRecord) r;
} }
return result;
} }
return result;
} }
/** Reads in the private key verbatim from the private key file */ /** Reads in the private key verbatim from the private key file */
@ -107,12 +106,17 @@ public class BINDKeyUtils {
* Given the information necessary to construct the path to a BIND9 generated * Given the information necessary to construct the path to a BIND9 generated
* key pair, load the key pair. * key pair, load the key pair.
* *
* @param signer the DNS name of the key. * @param signer
* @param algorithm the DNSSEC algorithm of the key. * the DNS name of the key.
* @param keyid the DNSSEC key footprint. * @param algorithm
* @param inDirectory the directory to look for the files (may be null). * the DNSSEC algorithm of the key.
* @param keyid
* the DNSSEC key footprint.
* @param inDirectory
* the directory to look for the files (may be null).
* @return the loaded key pair. * @return the loaded key pair.
* @throws IOException if there was a problem reading the BIND9 files. * @throws IOException
* if there was a problem reading the BIND9 files.
*/ */
public static DnsKeyPair loadKeyPair(Name signer, int algorithm, int keyid, public static DnsKeyPair loadKeyPair(Name signer, int algorithm, int keyid,
File inDirectory) throws IOException { File inDirectory) throws IOException {
@ -124,12 +128,16 @@ public class BINDKeyUtils {
/** /**
* Given a base path to a BIND9 key pair, load the key pair. * Given a base path to a BIND9 key pair, load the key pair.
* *
* @param keyFileBasePath the base filename (or real filename for either the * @param keyFileBasePath
* public or private key) of the key. * the base filename (or real filename for either the
* @param inDirectory the directory to look in, if the keyFileBasePath is * public or
* private key) of the key.
* @param inDirectory
* the directory to look in, if the keyFileBasePath is
* relative. * relative.
* @return the loaded key pair. * @return the loaded key pair.
* @throws IOException if there was a problem reading the files * @throws IOException
* if there was a problem reading the files
*/ */
public static DnsKeyPair loadKeyPair(String keyFileBasePath, File inDirectory) public static DnsKeyPair loadKeyPair(String keyFileBasePath, File inDirectory)
throws IOException { throws IOException {
@ -154,12 +162,15 @@ public class BINDKeyUtils {
* Given a base path to a BIND9 key pair, load the public part (only) of the * Given a base path to a BIND9 key pair, load the public part (only) of the
* key pair * key pair
* *
* @param keyFileBasePath the base or real path to the public part of a key * @param keyFileBasePath
* the base or real path to the public part of a key
* pair. * pair.
* @param inDirectory the directory to look in if the path is relative * @param inDirectory
* (may be null). * the directory to look in if the path is relative (may
* be null).
* @return a {@link DnsKeyPair} containing just the public key information. * @return a {@link DnsKeyPair} containing just the public key information.
* @throws IOException if there was a problem reading the public key file. * @throws IOException
* if there was a problem reading the public key file.
*/ */
public static DnsKeyPair loadKey(String keyFileBasePath, File inDirectory) public static DnsKeyPair loadKey(String keyFileBasePath, File inDirectory)
throws IOException { throws IOException {
@ -179,11 +190,15 @@ public class BINDKeyUtils {
* "keyset-[signer]." where [signer] is the DNS owner name of the key. The * "keyset-[signer]." where [signer] is the DNS owner name of the key. The
* keyset may be signed, but doesn't have to be. * keyset may be signed, but doesn't have to be.
* *
* @param keysetFileName the name of the keyset file. * @param keysetFileName
* @param inDirectory the directory to look in if the path is relative (may * the name of the keyset file.
* be null, defaults to the current working directory). * @param inDirectory
* the directory to look in if the path is relative (may
* be null,
* defaults to the current working directory).
* @return a RRset contain the KEY records and any associated SIG records. * @return a RRset contain the KEY records and any associated SIG records.
* @throws IOException if there was a problem reading the keyset file. * @throws IOException
* if there was a problem reading the keyset file.
*/ */
public static RRset loadKeySet(String keysetFileName, File inDirectory) public static RRset loadKeySet(String keysetFileName, File inDirectory)
throws IOException { throws IOException {
@ -203,8 +218,8 @@ public class BINDKeyUtils {
/** /**
* Calculate the key file base for this key pair. * Calculate the key file base for this key pair.
* *
* @param pair the {@link DnsKeyPair} to work from. It only needs a public * @param pair
* key. * the {@link DnsKeyPair} to work from. It only needs a public key.
* @return the base name of the key files. * @return the base name of the key files.
*/ */
public static String keyFileBase(DnsKeyPair pair) { public static String keyFileBase(DnsKeyPair pair) {
@ -244,7 +259,8 @@ public class BINDKeyUtils {
* Given a the contents of a BIND9 private key file, convert it into a native * Given a the contents of a BIND9 private key file, convert it into a native
* {@link java.security.PrivateKey} object. * {@link java.security.PrivateKey} object.
* *
* @param privateKeyString the contents of a BIND9 key file in string form. * @param privateKeyString
* the contents of a BIND9 key file in string form.
* @return a {@link java.security.PrivateKey} * @return a {@link java.security.PrivateKey}
*/ */
public static PrivateKey convertPrivateKeyString(String privateKeyString) { public static PrivateKey convertPrivateKeyString(String privateKeyString) {
@ -256,7 +272,7 @@ public class BINDKeyUtils {
try { try {
DnsKeyConverter conv = new DnsKeyConverter(); DnsKeyConverter conv = new DnsKeyConverter();
return conv.parsePrivateKeyString(privateKeyString); return conv.parsePrivateKeyString(privateKeyString);
} catch (IOException | NoSuchAlgorithmException e) { } catch (IOException|NoSuchAlgorithmException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -267,8 +283,10 @@ public class BINDKeyUtils {
* Given a native private key, convert it into a BIND9 private key file * Given a native private key, convert it into a BIND9 private key file
* format. * format.
* *
* @param priv the private key to convert. * @param priv
* @param pub the private key's corresponding public key. Some algorithms * the private key to convert.
* @param pub
* the private key's corresponding public key. Some algorithms
* require information from both. * require information from both.
* @return a string containing the contents of a BIND9 private key file. * @return a string containing the contents of a BIND9 private key file.
*/ */
@ -309,11 +327,16 @@ public class BINDKeyUtils {
/** /**
* This routine will write out the BIND9 dnssec-* tool compatible files. * This routine will write out the BIND9 dnssec-* tool compatible files.
* *
* @param baseFileName use this base file name. If null, the standard BIND9 * @param baseFileName
* base file name will be computed. * use this base file name. If null, the standard BIND9 base
* @param pair the keypair in question. * file
* @param inDirectory the directory to write to (may be null). * name will be computed.
* @throws IOException if there is a problem writing the files. * @param pair
* the keypair in question.
* @param inDirectory
* the directory to write to (may be null).
* @throws IOException
* if there is a problem writing the files.
*/ */
public static void writeKeyFiles(String baseFileName, DnsKeyPair pair, public static void writeKeyFiles(String baseFileName, DnsKeyPair pair,
File inDirectory) throws IOException { File inDirectory) throws IOException {
@ -346,8 +369,10 @@ public class BINDKeyUtils {
* This routine will write out the BIND9 dnssec-* tool compatible files to the * This routine will write out the BIND9 dnssec-* tool compatible files to the
* standard file names. * standard file names.
* *
* @param pair the key pair in question. * @param pair
* @param inDirectory the directory to write to (may be null). * the key pair in question.
* @param inDirectory
* the directory to write to (may be null).
*/ */
public static void writeKeyFiles(DnsKeyPair pair, File inDirectory) public static void writeKeyFiles(DnsKeyPair pair, File inDirectory)
throws IOException { throws IOException {

View File

@ -27,7 +27,7 @@ import java.util.logging.Logger;
* @author David Blacka * @author David Blacka
*/ */
public class ByteArrayComparator implements Comparator<byte[]> { public class ByteArrayComparator implements Comparator<byte[]> {
private int mOffset = 0; private int mOffset = 0;
private boolean mDebug = false; private boolean mDebug = false;
private Logger log; private Logger log;

View File

@ -34,6 +34,7 @@ import java.security.KeyPair;
import java.security.KeyPairGenerator; import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.Provider; import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security; import java.security.Security;
import java.security.Signature; import java.security.Signature;
import java.security.spec.ECFieldFp; import java.security.spec.ECFieldFp;
@ -42,7 +43,6 @@ import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint; import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve; import java.security.spec.EllipticCurve;
import java.security.spec.InvalidParameterSpecException; import java.security.spec.InvalidParameterSpecException;
import java.security.spec.NamedParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.RSAKeyGenParameterSpec;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -51,6 +51,12 @@ import java.util.logging.Logger;
import org.xbill.DNS.DNSSEC; import org.xbill.DNS.DNSSEC;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
// for now, we need to import the EdDSA parameter spec classes
// because they have no generic form in java.security.spec.*
// sadly, this will currently fail if you don't have the lib.
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
/** /**
* This class handles translating DNS signing algorithm identifiers into various * This class handles translating DNS signing algorithm identifiers into various
* usable java implementations. * usable java implementations.
@ -66,24 +72,21 @@ public class DnsKeyAlgorithm {
// Our base algorithm numbers. This is a normalization of the DNSSEC // Our base algorithm numbers. This is a normalization of the DNSSEC
// algorithms (which are really signature algorithms). Thus RSASHA1, // algorithms (which are really signature algorithms). Thus RSASHA1,
// RSASHA256, etc. all boil down to 'RSA' here. Similary, ECDSAP256SHA256 and // RSASHA256, etc. all boil down to 'RSA' here.
// ECDSAP384SHA384 both become 'ECDSA'. public static final int UNKNOWN = -1;
public enum BaseAlgorithm { public static final int RSA = 1;
UNKNOWN, public static final int DH = 2;
RSA, public static final int DSA = 3;
DH, public static final int ECC_GOST = 4;
DSA, public static final int ECDSA = 5;
ECC_GOST, public static final int EDDSA = 6;
ECDSA,
EDDSA;
}
private static class AlgEntry { private static class AlgEntry {
public int dnssecAlgorithm; public int dnssecAlgorithm;
public String sigName; public String sigName;
public BaseAlgorithm baseType; public int baseType;
public AlgEntry(int algorithm, String sigName, BaseAlgorithm baseType) { public AlgEntry(int algorithm, String sigName, int baseType) {
this.dnssecAlgorithm = algorithm; this.dnssecAlgorithm = algorithm;
this.sigName = sigName; this.sigName = sigName;
this.baseType = baseType; this.baseType = baseType;
@ -93,20 +96,18 @@ public class DnsKeyAlgorithm {
private static class ECAlgEntry extends AlgEntry { private static class ECAlgEntry extends AlgEntry {
public ECParameterSpec ecSpec; public ECParameterSpec ecSpec;
public ECAlgEntry(int algorithm, String sigName, BaseAlgorithm baseType, ECParameterSpec spec) { public ECAlgEntry(int algorithm, String sigName, int baseType, ECParameterSpec spec) {
super(algorithm, sigName, baseType); super(algorithm, sigName, baseType);
this.ecSpec = spec; this.ecSpec = spec;
} }
} }
private static class EdAlgEntry extends AlgEntry { private static class EdAlgEntry extends AlgEntry {
public String curveName; public EdDSAParameterSpec edSpec;
public NamedParameterSpec paramSpec;
public EdAlgEntry(int algorithm, String sigName, BaseAlgorithm baseType, String curveName) { public EdAlgEntry(int algorithm, String sigName, int baseType, EdDSAParameterSpec spec) {
super(algorithm, sigName, baseType); super(algorithm, sigName, baseType);
this.curveName = curveName; this.edSpec = spec;
this.paramSpec = new NamedParameterSpec(curveName);
} }
} }
@ -142,15 +143,24 @@ public class DnsKeyAlgorithm {
private static DnsKeyAlgorithm mInstance = null; private static DnsKeyAlgorithm mInstance = null;
public DnsKeyAlgorithm() { public DnsKeyAlgorithm() {
// Attempt to add the bouncycastle provider. This is so we can use this // Attempt to add the bouncycastle provider.
// provider if it is available, but not require the user to add it as one of // This is so we can use this provider if it is available, but not require
// the java.security providers. // the user to add it as one of the java.security providers.
try { try {
Class<?> bcProviderClass = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider"); Class<?> bcProviderClass = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
Provider bcProvider = (Provider) bcProviderClass.getDeclaredConstructor().newInstance(); Provider bcProvider = (Provider) bcProviderClass.getDeclaredConstructor().newInstance();
Security.addProvider(bcProvider); Security.addProvider(bcProvider);
} catch (ReflectiveOperationException e) { } catch (ReflectiveOperationException e) {
log.fine("Unable to load BC provider"); log.info("Unable to load BC provider");
}
// Attempt to add the EdDSA-Java provider.
try {
Class<?> eddsaProviderClass = Class.forName("net.i2p.crypto.eddsa.EdDSASecurityProvider");
Provider eddsaProvider = (Provider) eddsaProviderClass.getDeclaredConstructor().newInstance();
Security.addProvider(eddsaProvider);
} catch (ReflectiveOperationException e) {
log.warning("Unable to load EdDSA provider");
} }
initialize(); initialize();
@ -162,16 +172,16 @@ public class DnsKeyAlgorithm {
mIdToMnemonicMap = new HashMap<>(); mIdToMnemonicMap = new HashMap<>();
// Load the standard DNSSEC algorithms. // Load the standard DNSSEC algorithms.
addAlgorithm(DNSSEC.Algorithm.RSAMD5, "MD5withRSA", BaseAlgorithm.RSA); addAlgorithm(DNSSEC.Algorithm.RSAMD5, "MD5withRSA", RSA);
addMnemonic("RSAMD5", DNSSEC.Algorithm.RSAMD5); addMnemonic("RSAMD5", DNSSEC.Algorithm.RSAMD5);
addAlgorithm(DNSSEC.Algorithm.DH, "", BaseAlgorithm.DH); addAlgorithm(DNSSEC.Algorithm.DH, "", DH);
addMnemonic("DH", DNSSEC.Algorithm.DH); addMnemonic("DH", DNSSEC.Algorithm.DH);
addAlgorithm(DNSSEC.Algorithm.DSA, "SHA1withDSA", BaseAlgorithm.DSA); addAlgorithm(DNSSEC.Algorithm.DSA, "SHA1withDSA", DSA);
addMnemonic("DSA", DNSSEC.Algorithm.DSA); addMnemonic("DSA", DNSSEC.Algorithm.DSA);
addAlgorithm(DNSSEC.Algorithm.RSASHA1, "SHA1withRSA", BaseAlgorithm.RSA); addAlgorithm(DNSSEC.Algorithm.RSASHA1, "SHA1withRSA", RSA);
addMnemonic("RSASHA1", DNSSEC.Algorithm.RSASHA1); addMnemonic("RSASHA1", DNSSEC.Algorithm.RSASHA1);
addMnemonic("RSA", DNSSEC.Algorithm.RSASHA1); addMnemonic("RSA", DNSSEC.Algorithm.RSASHA1);
@ -183,114 +193,79 @@ public class DnsKeyAlgorithm {
addMnemonic("NSEC3RSASHA1", DNSSEC.Algorithm.RSA_NSEC3_SHA1); addMnemonic("NSEC3RSASHA1", DNSSEC.Algorithm.RSA_NSEC3_SHA1);
// Algorithms added by RFC 5702. // Algorithms added by RFC 5702.
addAlgorithm(DNSSEC.Algorithm.RSASHA256, "SHA256withRSA", BaseAlgorithm.RSA); addAlgorithm(DNSSEC.Algorithm.RSASHA256, "SHA256withRSA", RSA);
addMnemonic("RSASHA256", DNSSEC.Algorithm.RSASHA256); addMnemonic("RSASHA256", DNSSEC.Algorithm.RSASHA256);
addAlgorithm(DNSSEC.Algorithm.RSASHA512, "SHA512withRSA", BaseAlgorithm.RSA); addAlgorithm(DNSSEC.Algorithm.RSASHA512, "SHA512withRSA", RSA);
addMnemonic("RSASHA512", DNSSEC.Algorithm.RSASHA512); addMnemonic("RSASHA512", DNSSEC.Algorithm.RSASHA512);
// ECC-GOST is not supported by Java 1.8's Sun crypto provider. The // ECC-GOST is not supported by Java 1.8's Sun crypto provider. The
// bouncycastle.org provider, however, does support it. // bouncycastle.org provider, however, does support it.
// GostR3410-2001-CryptoPro-A is the named curve in the BC provider, but we // GostR3410-2001-CryptoPro-A is the named curve in the BC provider, but we
// will get the parameters directly. // will get the parameters directly.
addAlgorithm(DNSSEC.Algorithm.ECC_GOST, "GOST3411withECGOST3410", BaseAlgorithm.ECC_GOST, null); addAlgorithm(DNSSEC.Algorithm.ECC_GOST, "GOST3411withECGOST3410", ECC_GOST, null);
addMnemonic("ECCGOST", DNSSEC.Algorithm.ECC_GOST); addMnemonic("ECCGOST", DNSSEC.Algorithm.ECC_GOST);
addMnemonic("ECC-GOST", DNSSEC.Algorithm.ECC_GOST); addMnemonic("ECC-GOST", DNSSEC.Algorithm.ECC_GOST);
addAlgorithm(DNSSEC.Algorithm.ECDSAP256SHA256, "SHA256withECDSA", BaseAlgorithm.ECDSA, "secp256r1"); addAlgorithm(DNSSEC.Algorithm.ECDSAP256SHA256, "SHA256withECDSA", ECDSA, "secp256r1");
addMnemonic("ECDSAP256SHA256", DNSSEC.Algorithm.ECDSAP256SHA256); addMnemonic("ECDSAP256SHA256", DNSSEC.Algorithm.ECDSAP256SHA256);
addMnemonic("ECDSA-P256", DNSSEC.Algorithm.ECDSAP256SHA256); addMnemonic("ECDSA-P256", DNSSEC.Algorithm.ECDSAP256SHA256);
addAlgorithm(DNSSEC.Algorithm.ECDSAP384SHA384, "SHA384withECDSA", BaseAlgorithm.ECDSA, "secp384r1"); addAlgorithm(DNSSEC.Algorithm.ECDSAP384SHA384, "SHA384withECDSA", ECDSA, "secp384r1");
addMnemonic("ECDSAP384SHA384", DNSSEC.Algorithm.ECDSAP384SHA384); addMnemonic("ECDSAP384SHA384", DNSSEC.Algorithm.ECDSAP384SHA384);
addMnemonic("ECDSA-P384", DNSSEC.Algorithm.ECDSAP384SHA384); addMnemonic("ECDSA-P384", DNSSEC.Algorithm.ECDSAP384SHA384);
// For the Edwards Curve implementations, we just initialize Signature and // EdDSA is not supported by either the Java 1.8 Sun crypto
// KeyPairGenerator with the curve name. // provider or bouncycastle. It is added by the Ed25519-Java
addAlgorithm(15, "Ed25519", BaseAlgorithm.EDDSA, "Ed25519"); // library. We don't have a corresponding constant in
// org.xbill.DNS.DNSSEC yet, though.
addAlgorithm(15, "NONEwithEdDSA", EDDSA, "Ed25519");
addMnemonic("ED25519", 15); addMnemonic("ED25519", 15);
addAlgorithm(16, "Ed448", BaseAlgorithm.EDDSA, "Ed448");
addMnemonic(("ED448"), 16);
} }
private void addAlgorithm(int algorithm, String sigName, BaseAlgorithm baseType) { private void addAlgorithm(int algorithm, String sigName, int baseType) {
mAlgorithmMap.put(algorithm, new AlgEntry(algorithm, sigName, baseType)); mAlgorithmMap.put(algorithm, new AlgEntry(algorithm, sigName, baseType));
} }
/** private void addAlgorithm(int algorithm, String sigName, int baseType, String curveName) {
* Add a ECDSA (algorithms 13/14) to the set, looking up the curve names. if (baseType == ECDSA) {
* ECParameterSpec ecSpec = ECSpecFromAlgorithm(algorithm);
* @param algorithm the DNSSEC algorithm number. if (ecSpec == null)
* @param sigName the name of the signature scheme. ecSpec = ECSpecFromName(curveName);
* @param curveName the official name of the elliptic curve in our crypto if (ecSpec == null)
* library (SunEC). return;
*/
private void addECDSAAlgorithm(int algorithm, String sigName, String curveName) {
ECParameterSpec ecSpec = ECSpecFromAlgorithm(algorithm);
if (ecSpec == null)
ecSpec = ECSpecFromName(curveName);
if (ecSpec == null)
return;
// Check to see if we can get a Signature object for this algorithm. // Check to see if we can get a Signature object for this algorithm.
try { try {
Signature.getInstance(sigName); Signature.getInstance(sigName);
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
// for now, let's find out // for now, let's find out
log.severe("could not get signature for " + sigName + ": " + e.getMessage()); log.severe("could not get signature for " + sigName + ": " + e.getMessage());
// If not, do not add the algorithm. // If not, do not add the algorithm.
return; return;
}
ECAlgEntry entry = new ECAlgEntry(algorithm, sigName, baseType, ecSpec);
mAlgorithmMap.put(algorithm, entry);
} else if (baseType == EDDSA) {
EdDSAParameterSpec edSpec = EdDSASpecFromName(curveName);
if (edSpec == null)
return;
// Check to see if we can get a Signature object for this algorithm.
try {
Signature.getInstance(sigName);
} catch (NoSuchAlgorithmException e) {
// for now, let's find out
log.severe("could not get signature for " + sigName + ": " + e.getMessage());
// If not, do not add the algorithm.
return;
}
EdAlgEntry entry = new EdAlgEntry(algorithm, sigName, baseType, edSpec);
mAlgorithmMap.put(algorithm, entry);
} }
ECAlgEntry entry = new ECAlgEntry(algorithm, sigName, BaseAlgorithm.ECDSA, ecSpec);
mAlgorithmMap.put(algorithm, entry);
} }
/**
* Add an EdDSA (Edwards curve algorithms, DNSSEC algorithms 15/16), looking up
* the curve.
*
* @param algorithm the DNSSEC algorithm numer.
* @param sigName the name of the signing scheme. For EdDSA, this is the same
* as the curve.
* @param curveName the name of the curve.
*/
private void addEdDSAAlgorithm(int algorithm, String sigName, String curveName) {
// Check to see if we can get a Signature object for this algorithm.
try {
Signature.getInstance(sigName);
} catch (NoSuchAlgorithmException e) {
// for now, let's find out
log.severe("could not get signature for EdDSA curve" + curveName + ": " + e.getMessage());
// If not, do not add the algorithm.
return;
}
EdAlgEntry entry = new EdAlgEntry(algorithm, sigName, BaseAlgorithm.EDDSA, curveName);
mAlgorithmMap.put(algorithm, entry);
}
/**
* Add an Elliptic Curve algorithm given a signing scheme and curve name.
*
* @param algorithm the DNSSEC algorithm number
* @param sigName the signature scheme (e.g., which crypto hash function are
* we using?)
* @param baseType the base type (either ECDSA or EDDSA).
* @param curveName the name of the curve.
*/
private void addAlgorithm(int algorithm, String sigName, BaseAlgorithm baseType, String curveName) {
if (baseType == BaseAlgorithm.ECDSA) {
addECDSAAlgorithm(algorithm, sigName, curveName);
} else if (baseType == BaseAlgorithm.EDDSA) {
addEdDSAAlgorithm(algorithm, sigName, curveName);
}
}
/**
* Add an alternate mnemonic for an algorithm.
*
* @param m the new mnemonic.
* @param alg the DNSSEC algorithm number.
*/
private void addMnemonic(String m, int alg) { private void addMnemonic(String m, int alg) {
// Do not add mnemonics for algorithms that ended up not actually being // Do not add mnemonics for algorithms that ended up not actually being
// supported. // supported.
@ -301,19 +276,19 @@ public class DnsKeyAlgorithm {
mIdToMnemonicMap.computeIfAbsent(alg, k -> m); mIdToMnemonicMap.computeIfAbsent(alg, k -> m);
} }
public void addAlias(int alias, String mnemonic, int origAlgorithm) { public void addAlias(int alias, String mnemonic, int original_algorithm) {
if (mAlgorithmMap.containsKey(alias)) { if (mAlgorithmMap.containsKey(alias)) {
log.warning("Unable to alias algorithm " + alias + " because it already exists."); log.warning("Unable to alias algorithm " + alias + " because it already exists.");
return; return;
} }
if (!mAlgorithmMap.containsKey(origAlgorithm)) { if (!mAlgorithmMap.containsKey(original_algorithm)) {
log.warning("Unable to alias algorithm " + alias log.warning("Unable to alias algorithm " + alias
+ " to unknown algorithm identifier " + origAlgorithm); + " to unknown algorithm identifier " + original_algorithm);
return; return;
} }
mAlgorithmMap.put(alias, mAlgorithmMap.get(origAlgorithm)); mAlgorithmMap.put(alias, mAlgorithmMap.get(original_algorithm));
if (mnemonic != null) { if (mnemonic != null) {
addMnemonic(mnemonic, alias); addMnemonic(mnemonic, alias);
@ -329,16 +304,16 @@ public class DnsKeyAlgorithm {
// the ECC-GOST curve. // the ECC-GOST curve.
private ECParameterSpec ECSpecFromAlgorithm(int algorithm) { private ECParameterSpec ECSpecFromAlgorithm(int algorithm) {
if (algorithm == DNSSEC.Algorithm.ECC_GOST) { if (algorithm == DNSSEC.Algorithm.ECC_GOST) {
// From RFC 4357 Section 11.4 // From RFC 4357 Section 11.4
BigInteger p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97", 16); BigInteger p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97", 16);
BigInteger a = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94", 16); BigInteger a = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94", 16);
BigInteger b = new BigInteger("A6", 16); BigInteger b = new BigInteger("A6", 16);
BigInteger gx = new BigInteger("1", 16); BigInteger gx = new BigInteger("1", 16);
BigInteger gy = new BigInteger("8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14", 16); BigInteger gy = new BigInteger("8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14", 16);
BigInteger n = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893", 16); BigInteger n = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893", 16);
EllipticCurve curve = new EllipticCurve(new ECFieldFp(p), a, b); EllipticCurve curve = new EllipticCurve(new ECFieldFp(p), a, b);
return new ECParameterSpec(curve, new ECPoint(gx, gy), n, 1); return new ECParameterSpec(curve, new ECPoint(gx, gy), n, 1);
} }
return null; return null;
} }
@ -347,8 +322,8 @@ public class DnsKeyAlgorithm {
private ECParameterSpec ECSpecFromName(String stdName) { private ECParameterSpec ECSpecFromName(String stdName) {
try { try {
AlgorithmParameters ap = AlgorithmParameters.getInstance("EC"); AlgorithmParameters ap = AlgorithmParameters.getInstance("EC");
ECGenParameterSpec ecgSpec = new ECGenParameterSpec(stdName); ECGenParameterSpec ecg_spec = new ECGenParameterSpec(stdName);
ap.init(ecgSpec); ap.init(ecg_spec);
return ap.getParameterSpec(ECParameterSpec.class); return ap.getParameterSpec(ECParameterSpec.class);
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
log.info("Elliptic Curve not supported by any crypto provider: " + e.getMessage()); log.info("Elliptic Curve not supported by any crypto provider: " + e.getMessage());
@ -358,6 +333,24 @@ public class DnsKeyAlgorithm {
return null; return null;
} }
// Fetch the curve parameters from a named EdDSA curve.
private EdDSAParameterSpec EdDSASpecFromName(String stdName) {
try {
EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(stdName);
if (spec != null)
return spec;
throw new InvalidParameterSpecException("Edwards Curve " + stdName + " not found.");
}
// catch (NoSuchAlgorithmException e) {
// log.info("Edwards Curve not supported by any crypto provider: " +
// e.getMessage());
// }
catch (InvalidParameterSpecException e) {
log.info("Edwards Curve " + stdName + " not supported");
}
return null;
}
public String[] supportedAlgMnemonics() { public String[] supportedAlgMnemonics() {
Set<Integer> keyset = mAlgorithmMap.keySet(); Set<Integer> keyset = mAlgorithmMap.keySet();
Integer[] algs = keyset.toArray(new Integer[keyset.size()]); Integer[] algs = keyset.toArray(new Integer[keyset.size()]);
@ -395,10 +388,11 @@ public class DnsKeyAlgorithm {
} }
/** /**
* Given one of the ECDSA algorithms (ECDSAP256SHA256, etc.) return the * Given one of the ECDSA algorithms (ECDSAP256SHA256, etc.) return
* elliptic curve parameters. * the elliptic curve parameters.
* *
* @param algorithm The DNSSEC algorithm number. * @param algorithm
* The DNSSEC algorithm number.
* @return The calculated JCA ECParameterSpec for that DNSSEC algorithm, or * @return The calculated JCA ECParameterSpec for that DNSSEC algorithm, or
* null if not a recognized/supported EC algorithm. * null if not a recognized/supported EC algorithm.
*/ */
@ -408,35 +402,37 @@ public class DnsKeyAlgorithm {
return null; return null;
if (!(entry instanceof ECAlgEntry)) if (!(entry instanceof ECAlgEntry))
return null; return null;
ECAlgEntry ecEntry = (ECAlgEntry) entry; ECAlgEntry ec_entry = (ECAlgEntry) entry;
return ecEntry.ecSpec; return ec_entry.ecSpec;
} }
/** /**
* Given one of the EdDSA algorithms (ED25519 or ED448), return the named * Given one of the EdDSA algorithms (Ed25519, Ed448) return the
* parameter spec. * elliptic curve parameters.
* *
* @param algorithm The DNSSEC algorithm number. * @param algorithm
* @return The NamedParameterSpec for that DNSSEC algorithm, nor null if the * The DNSSEC algorithm number.
* algorithm wasn't a supported EdDSA algorithm. * @return The stored EdDSAParameterSpec for that algorithm, or
* null if not a recognized/supported EdDSA algorithm.
*/ */
public NamedParameterSpec getEdwardsCurveSpec(int algorithm) { public EdDSAParameterSpec getEdwardsCurveParams(int algorithm) {
AlgEntry entry = getEntry(algorithm); AlgEntry entry = getEntry(algorithm);
if (entry == null) if (entry == null)
return null; return null;
if (!(entry instanceof EdAlgEntry)) if (!(entry instanceof EdAlgEntry))
return null; return null;
EdAlgEntry edEntry = (EdAlgEntry) entry; EdAlgEntry ed_entry = (EdAlgEntry) entry;
return edEntry.paramSpec; return ed_entry.edSpec;
} }
/** /**
* Translate a possible algorithm alias back to the original DNSSEC algorithm * Translate a possible algorithm alias back to the original DNSSEC algorithm
* number * number
* *
* @param algorithm a DNSSEC algorithm that may be an alias. * @param algorithm
* a DNSSEC algorithm that may be an alias.
* @return -1 if the algorithm isn't recognised, the orignal algorithm number * @return -1 if the algorithm isn't recognised, the orignal algorithm number
* if it is. * if it is.
*/ */
@ -462,7 +458,8 @@ public class DnsKeyAlgorithm {
* Given an algorithm mnemonic, convert the mnemonic to a DNSSEC algorithm * Given an algorithm mnemonic, convert the mnemonic to a DNSSEC algorithm
* number. * number.
* *
* @param s The mnemonic string. This is case-insensitive. * @param s
* The mnemonic string. This is case-insensitive.
* @return -1 if the mnemonic isn't recognized or supported, the algorithm * @return -1 if the mnemonic isn't recognized or supported, the algorithm
* number if it is. * number if it is.
*/ */
@ -476,7 +473,8 @@ public class DnsKeyAlgorithm {
/** /**
* Given a DNSSEC algorithm number, return the "preferred" mnemonic. * Given a DNSSEC algorithm number, return the "preferred" mnemonic.
* *
* @param algorithm A DNSSEC algorithm number. * @param algorithm
* A DNSSEC algorithm number.
* @return The preferred mnemonic string, or null if not supported or * @return The preferred mnemonic string, or null if not supported or
* recognized. * recognized.
*/ */
@ -484,15 +482,15 @@ public class DnsKeyAlgorithm {
return mIdToMnemonicMap.get(algorithm); return mIdToMnemonicMap.get(algorithm);
} }
public BaseAlgorithm baseType(int algorithm) { public int baseType(int algorithm) {
AlgEntry entry = getEntry(algorithm); AlgEntry entry = getEntry(algorithm);
if (entry != null) if (entry != null)
return entry.baseType; return entry.baseType;
return BaseAlgorithm.UNKNOWN; return UNKNOWN;
} }
public boolean isDSA(int algorithm) { public boolean isDSA(int algorithm) {
return (baseType(algorithm) == BaseAlgorithm.DSA); return (baseType(algorithm) == DSA);
} }
public KeyPair generateKeyPair(int algorithm, int keysize, boolean useLargeExp) public KeyPair generateKeyPair(int algorithm, int keysize, boolean useLargeExp)
@ -504,14 +502,14 @@ public class DnsKeyAlgorithm {
mRSAKeyGenerator = KeyPairGenerator.getInstance("RSA"); mRSAKeyGenerator = KeyPairGenerator.getInstance("RSA");
} }
RSAKeyGenParameterSpec rsaSpec; RSAKeyGenParameterSpec rsa_spec;
if (useLargeExp) { if (useLargeExp) {
rsaSpec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F4); rsa_spec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F4);
} else { } else {
rsaSpec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F0); rsa_spec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F0);
} }
try { try {
mRSAKeyGenerator.initialize(rsaSpec); mRSAKeyGenerator.initialize(rsa_spec);
} catch (InvalidAlgorithmParameterException e) { } catch (InvalidAlgorithmParameterException e) {
// Fold the InvalidAlgorithmParameterException into our existing // Fold the InvalidAlgorithmParameterException into our existing
// thrown exception. Ugly, but requires less code change. // thrown exception. Ugly, but requires less code change.
@ -562,9 +560,18 @@ public class DnsKeyAlgorithm {
break; break;
} }
case EDDSA: { case EDDSA: {
EdAlgEntry entry = (EdAlgEntry) getEntry(algorithm); if (mEdKeyGenerator == null) {
mEdKeyGenerator = KeyPairGenerator.getInstance(entry.curveName); mEdKeyGenerator = KeyPairGenerator.getInstance("EdDSA");
}
EdDSAParameterSpec edSpec = getEdwardsCurveParams(algorithm);
try {
mEdKeyGenerator.initialize(edSpec, new SecureRandom());
} catch (InvalidAlgorithmParameterException e) {
// Fold the InvalidAlgorithmParameterException into our existing
// thrown exception. Ugly, but requires less code change.
throw new NoSuchAlgorithmException("invalid key parameter spec");
}
pair = mEdKeyGenerator.generateKeyPair(); pair = mEdKeyGenerator.generateKeyPair();
break; break;
} }

View File

@ -30,16 +30,12 @@ import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey; import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey; import java.security.interfaces.ECPublicKey;
import java.security.interfaces.EdECPrivateKey;
import java.security.interfaces.EdECPublicKey;
import java.security.interfaces.RSAPrivateCrtKey; import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.DSAPrivateKeySpec; import java.security.spec.DSAPrivateKeySpec;
import java.security.spec.ECParameterSpec; import java.security.spec.ECParameterSpec;
import java.security.spec.ECPrivateKeySpec; import java.security.spec.ECPrivateKeySpec;
import java.security.spec.EdECPrivateKeySpec;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec; import java.security.spec.KeySpec;
import java.security.spec.NamedParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateCrtKeySpec; import java.security.spec.RSAPrivateCrtKeySpec;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -54,6 +50,13 @@ import org.xbill.DNS.DNSSEC.DNSSECException;
import org.xbill.DNS.Name; import org.xbill.DNS.Name;
import org.xbill.DNS.utils.base64; import org.xbill.DNS.utils.base64;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
// For now, just import the native EdDSA classes
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
/** /**
* This class handles conversions between JCA key formats and DNSSEC and BIND9 * This class handles conversions between JCA key formats and DNSSEC and BIND9
* key formats. * key formats.
@ -84,6 +87,7 @@ public class DnsKeyConverter {
// Because we have arbitrarily aliased algorithms, we need to possibly // Because we have arbitrarily aliased algorithms, we need to possibly
// translate the aliased algorithm back to the actual algorithm. // translate the aliased algorithm back to the actual algorithm.
int originalAlgorithm = mAlgorithms.originalAlgorithm(pKeyRecord.getAlgorithm()); int originalAlgorithm = mAlgorithms.originalAlgorithm(pKeyRecord.getAlgorithm());
if (originalAlgorithm <= 0) if (originalAlgorithm <= 0)
@ -97,6 +101,16 @@ public class DnsKeyConverter {
pKeyRecord.getKey()); pKeyRecord.getKey());
} }
// do not rely on DNSJava's method for EdDSA for now.
if (mAlgorithms.baseType(originalAlgorithm) == DnsKeyAlgorithm.EDDSA) {
try {
return parseEdDSADNSKEYRecord(pKeyRecord);
} catch (InvalidKeySpecException e) {
// just to be expedient, recast this as a NoSuchAlgorithmException.
throw new NoSuchAlgorithmException(e.getMessage());
}
}
try { try {
// This uses DNSJava's DNSSEC.toPublicKey() method. // This uses DNSJava's DNSSEC.toPublicKey() method.
return pKeyRecord.getPublicKey(); return pKeyRecord.getPublicKey();
@ -105,12 +119,30 @@ public class DnsKeyConverter {
} }
} }
/**
* Since we don't (yet) have support in DNSJava for parsing the
* newer EdDSA algorithms, here is a local version.
*/
private PublicKey parseEdDSADNSKEYRecord(DNSKEYRecord pKeyRecord)
throws IllegalArgumentException, NoSuchAlgorithmException, InvalidKeySpecException {
byte[] seed = pKeyRecord.getKey();
EdDSAPublicKeySpec spec = new EdDSAPublicKeySpec(seed,
mAlgorithms.getEdwardsCurveParams(pKeyRecord.getAlgorithm()));
KeyFactory factory = KeyFactory.getInstance("EdDSA");
return factory.generatePublic(spec);
}
/** /**
* Given a JCA public key and the ancillary data, generate a DNSKEY record. * Given a JCA public key and the ancillary data, generate a DNSKEY record.
*/ */
public DNSKEYRecord generateDNSKEYRecord(Name name, int dclass, long ttl, public DNSKEYRecord generateDNSKEYRecord(Name name, int dclass, long ttl,
int flags, int alg, PublicKey key) { int flags, int alg, PublicKey key) {
try { try {
if (mAlgorithms.baseType(alg) == DnsKeyAlgorithm.EDDSA) {
return generateEdDSADNSKEYRecord(name, dclass, ttl, flags, alg, key);
}
return new DNSKEYRecord(name, dclass, ttl, flags, DNSKEYRecord.Protocol.DNSSEC, alg, return new DNSKEYRecord(name, dclass, ttl, flags, DNSKEYRecord.Protocol.DNSSEC, alg,
key); key);
} catch (DNSSECException e) { } catch (DNSSECException e) {
@ -120,6 +152,13 @@ public class DnsKeyConverter {
} }
} }
private DNSKEYRecord generateEdDSADNSKEYRecord(Name name, int dclass, long ttl,
int flags, int alg, PublicKey key) {
EdDSAPublicKey ed_key = (EdDSAPublicKey) key;
byte[] key_data = ed_key.getAbyte();
return new DNSKEYRecord(name, dclass, ttl, flags, DNSKEYRecord.Protocol.DNSSEC, alg,
key_data);
}
// Private Key Specific Parsing routines // Private Key Specific Parsing routines
/** /**
@ -129,9 +168,9 @@ public class DnsKeyConverter {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(key); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(key);
try { try {
switch (mAlgorithms.baseType(algorithm)) { switch (mAlgorithms.baseType(algorithm)) {
case RSA: case DnsKeyAlgorithm.RSA:
return mRSAKeyFactory.generatePrivate(spec); return mRSAKeyFactory.generatePrivate(spec);
case DSA: case DnsKeyAlgorithm.DSA:
return mDSAKeyFactory.generatePrivate(spec); return mDSAKeyFactory.generatePrivate(spec);
default: default:
return null; return null;
@ -186,17 +225,17 @@ public class DnsKeyConverter {
int alg = parseInt(val, -1); int alg = parseInt(val, -1);
switch (mAlgorithms.baseType(alg)) { switch (mAlgorithms.baseType(alg)) {
case RSA: case DnsKeyAlgorithm.RSA:
return parsePrivateRSA(lines); return parsePrivateRSA(lines);
case DSA: case DnsKeyAlgorithm.DSA:
return parsePrivateDSA(lines); return parsePrivateDSA(lines);
case DH: case DnsKeyAlgorithm.DH:
return parsePrivateDH(lines); return parsePrivateDH(lines);
case ECC_GOST: case DnsKeyAlgorithm.ECC_GOST:
return parsePrivateECDSA(lines, alg); return parsePrivateECDSA(lines, alg);
case ECDSA: case DnsKeyAlgorithm.ECDSA:
return parsePrivateECDSA(lines, alg); return parsePrivateECDSA(lines, alg);
case EDDSA: case DnsKeyAlgorithm.EDDSA:
return parsePrivateEdDSA(lines, alg); return parsePrivateEdDSA(lines, alg);
default: default:
throw new IOException("unsupported private key algorithm: " + val); throw new IOException("unsupported private key algorithm: " + val);
@ -233,12 +272,12 @@ public class DnsKeyConverter {
private PrivateKey parsePrivateRSA(StringTokenizer lines) private PrivateKey parsePrivateRSA(StringTokenizer lines)
throws NoSuchAlgorithmException { throws NoSuchAlgorithmException {
BigInteger modulus = null; BigInteger modulus = null;
BigInteger publicExponent = null; BigInteger public_exponent = null;
BigInteger privateExponent = null; BigInteger private_exponent = null;
BigInteger primeP = null; BigInteger prime_p = null;
BigInteger primeQ = null; BigInteger prime_q = null;
BigInteger primePExponent = null; BigInteger prime_p_exponent = null;
BigInteger primeQExponent = null; BigInteger prime_q_exponent = null;
BigInteger coefficient = null; BigInteger coefficient = null;
while (lines.hasMoreTokens()) { while (lines.hasMoreTokens()) {
@ -257,28 +296,33 @@ public class DnsKeyConverter {
if (line.startsWith("Modulus: ")) { if (line.startsWith("Modulus: ")) {
modulus = new BigInteger(1, data); modulus = new BigInteger(1, data);
// printBigIntCompare(data, modulus);
} else if (line.startsWith("PublicExponent: ")) { } else if (line.startsWith("PublicExponent: ")) {
publicExponent = new BigInteger(1, data); public_exponent = new BigInteger(1, data);
// printBigIntCompare(data, public_exponent);
} else if (line.startsWith("PrivateExponent: ")) { } else if (line.startsWith("PrivateExponent: ")) {
privateExponent = new BigInteger(1, data); private_exponent = new BigInteger(1, data);
// printBigIntCompare(data, private_exponent);
} else if (line.startsWith("Prime1: ")) { } else if (line.startsWith("Prime1: ")) {
primeP = new BigInteger(1, data); prime_p = new BigInteger(1, data);
// printBigIntCompare(data, prime_p);
} else if (line.startsWith("Prime2: ")) { } else if (line.startsWith("Prime2: ")) {
primeQ = new BigInteger(1, data); prime_q = new BigInteger(1, data);
// printBigIntCompare(data, prime_q);
} else if (line.startsWith("Exponent1: ")) { } else if (line.startsWith("Exponent1: ")) {
primePExponent = new BigInteger(1, data); prime_p_exponent = new BigInteger(1, data);
} else if (line.startsWith("Exponent2: ")) { } else if (line.startsWith("Exponent2: ")) {
primeQExponent = new BigInteger(1, data); prime_q_exponent = new BigInteger(1, data);
} else if (line.startsWith("Coefficient: ")) { } else if (line.startsWith("Coefficient: ")) {
coefficient = new BigInteger(1, data); coefficient = new BigInteger(1, data);
} }
} }
try { try {
KeySpec spec = new RSAPrivateCrtKeySpec(modulus, publicExponent, KeySpec spec = new RSAPrivateCrtKeySpec(modulus, public_exponent,
privateExponent, primeP, private_exponent, prime_p,
primeQ, primePExponent, prime_q, prime_p_exponent,
primeQExponent, coefficient); prime_q_exponent, coefficient);
if (mRSAKeyFactory == null) { if (mRSAKeyFactory == null) {
mRSAKeyFactory = KeyFactory.getInstance("RSA"); mRSAKeyFactory = KeyFactory.getInstance("RSA");
} }
@ -422,13 +466,13 @@ public class DnsKeyConverter {
if (mECKeyFactory == null) { if (mECKeyFactory == null) {
mECKeyFactory = KeyFactory.getInstance("EC"); mECKeyFactory = KeyFactory.getInstance("EC");
} }
ECParameterSpec ecSpec = mAlgorithms.getEllipticCurveParams(algorithm); ECParameterSpec ec_spec = mAlgorithms.getEllipticCurveParams(algorithm);
if (ecSpec == null) { if (ec_spec == null) {
throw new NoSuchAlgorithmException("DNSSEC algorithm " + algorithm + throw new NoSuchAlgorithmException("DNSSEC algorithm " + algorithm +
" is not a recognized Elliptic Curve algorithm"); " is not a recognized Elliptic Curve algorithm");
} }
KeySpec spec = new ECPrivateKeySpec(s, ecSpec); KeySpec spec = new ECPrivateKeySpec(s, ec_spec);
try { try {
return mECKeyFactory.generatePrivate(spec); return mECKeyFactory.generatePrivate(spec);
@ -472,13 +516,13 @@ public class DnsKeyConverter {
if (mEdKeyFactory == null) { if (mEdKeyFactory == null) {
mEdKeyFactory = KeyFactory.getInstance("EdDSA"); mEdKeyFactory = KeyFactory.getInstance("EdDSA");
} }
NamedParameterSpec namedSpec = mAlgorithms.getEdwardsCurveSpec(algorithm); EdDSAParameterSpec ed_spec = mAlgorithms.getEdwardsCurveParams(algorithm);
if (namedSpec == null) { if (ed_spec == null) {
throw new NoSuchAlgorithmException("DNSSEC algorithm " + algorithm + throw new NoSuchAlgorithmException("DNSSEC algorithm " + algorithm +
" is not a recognized Edwards Curve algorithm"); " is not a recognized Edwards Curve algorithm");
} }
EdECPrivateKeySpec spec = new EdECPrivateKeySpec(namedSpec, seed); KeySpec spec = new EdDSAPrivateKeySpec(seed, ed_spec);
try { try {
return mEdKeyFactory.generatePrivate(spec); return mEdKeyFactory.generatePrivate(spec);
@ -501,8 +545,8 @@ public class DnsKeyConverter {
return generatePrivateDH((DHPrivateKey) priv, (DHPublicKey) pub, alg); return generatePrivateDH((DHPrivateKey) priv, (DHPublicKey) pub, alg);
} else if (priv instanceof ECPrivateKey && pub instanceof ECPublicKey) { } else if (priv instanceof ECPrivateKey && pub instanceof ECPublicKey) {
return generatePrivateEC((ECPrivateKey) priv, (ECPublicKey) pub, alg); return generatePrivateEC((ECPrivateKey) priv, (ECPublicKey) pub, alg);
} else if (priv instanceof EdECPrivateKey && pub instanceof EdECPublicKey) { } else if (priv instanceof EdDSAPrivateKey && pub instanceof EdDSAPublicKey) {
return generatePrivateED((EdECPrivateKey) priv, (EdECPublicKey) pub, alg); return generatePrivateED((EdDSAPrivateKey) priv, (EdDSAPublicKey) pub, alg);
} }
return null; return null;
@ -512,16 +556,16 @@ public class DnsKeyConverter {
* Convert from 'unsigned' big integer to original 'signed format' in Base64 * Convert from 'unsigned' big integer to original 'signed format' in Base64
*/ */
private static String b64BigInt(BigInteger i) { private static String b64BigInt(BigInteger i) {
byte[] origBytes = i.toByteArray(); byte[] orig_bytes = i.toByteArray();
if (origBytes[0] != 0 || origBytes.length == 1) { if (orig_bytes[0] != 0 || orig_bytes.length == 1) {
return base64.toString(origBytes); return base64.toString(orig_bytes);
} }
byte[] signedBytes = new byte[origBytes.length - 1]; byte[] signed_bytes = new byte[orig_bytes.length - 1];
System.arraycopy(origBytes, 1, signedBytes, 0, signedBytes.length); System.arraycopy(orig_bytes, 1, signed_bytes, 0, signed_bytes.length);
return base64.toString(signedBytes); return base64.toString(signed_bytes);
} }
/** /**
@ -624,7 +668,7 @@ public class DnsKeyConverter {
* Given an edwards curve key pair, and the actual algorithm (which will * Given an edwards curve key pair, and the actual algorithm (which will
* describe the curve used), return the BIND9-style text encoding. * describe the curve used), return the BIND9-style text encoding.
*/ */
private String generatePrivateED(EdECPrivateKey priv, EdECPublicKey pub, int alg) { private String generatePrivateED(EdDSAPrivateKey priv, EdDSAPublicKey pub, int alg) {
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
PrintWriter out = new PrintWriter(sw); PrintWriter out = new PrintWriter(sw);
@ -632,8 +676,7 @@ public class DnsKeyConverter {
out.println("Algorithm: " + alg + " (" + mAlgorithms.algToString(alg) out.println("Algorithm: " + alg + " (" + mAlgorithms.algToString(alg)
+ ")"); + ")");
out.print("PrivateKey: "); out.print("PrivateKey: ");
byte[] keyBytes = priv.getBytes().orElse("null".getBytes()); out.println(base64.toString(priv.getSeed()));
out.println(base64.toString(keyBytes));
return sw.toString(); return sw.toString();
} }

View File

@ -264,22 +264,18 @@ public class DnsKeyPair {
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
*/ */
public Signature getVerifier() { public Signature getVerifier() {
if (mVerifier != null) if (mVerifier == null) {
return mVerifier; mVerifier = getSignature();
PublicKey pk = getPublic();
mVerifier = getSignature(); if (mVerifier != null && pk != null) {
PublicKey pk = getPublic(); try {
mVerifier.initVerify(pk);
if (mVerifier == null || pk == null) { } catch (InvalidKeyException e) {
log.warning("Could not get a Signature object for this key pair" + this); }
return null; } else {
} // do not return an uninitialized verifier
return null;
try { }
mVerifier.initVerify(pk);
} catch (InvalidKeyException e) {
log.warning("Key pair cannot initialize with public key: " + this);
return null;
} }
return mVerifier; return mVerifier;
@ -331,16 +327,15 @@ public class DnsKeyPair {
return -1; return -1;
} }
// This is from a StackOverflow answer. There are number of bytes-to-hex // This is from a StackOverflow answer. There are number of bytes-to-hex
// converters in the ecosystem, but this avoid extra dependencies // converters in the ecosystem, but this avoid extra dependencies
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII); private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
public static String toHex(byte[] bytes) { public static String toHex(byte[] bytes) {
byte[] hexChars = new byte[bytes.length * 2]; byte[] hexChars = new byte[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) { for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF; int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4]; hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
} }
return new String(hexChars, StandardCharsets.UTF_8); return new String(hexChars, StandardCharsets.UTF_8);
} }

View File

@ -238,13 +238,13 @@ public class DnsSecVerifier {
for (DnsKeyPair keypair : keypairs) { for (DnsKeyPair keypair : keypairs) {
Signature signer = keypair.getVerifier(); Signature signer = keypair.getVerifier();
signer.update(data); signer.update(data);
byte[] sig = sigrec.getSignature(); byte[] sig = sigrec.getSignature();
if (algs.baseType(sigrec.getAlgorithm()) == DnsKeyAlgorithm.BaseAlgorithm.DSA) { if (algs.baseType(sigrec.getAlgorithm()) == DnsKeyAlgorithm.DSA) {
sig = SignUtils.convertDSASignature(sig); sig = SignUtils.convertDSASignature(sig);
} }
if (sigrec.getAlgorithm() == DNSSEC.Algorithm.ECDSAP256SHA256 || if (sigrec.getAlgorithm() == DNSSEC.Algorithm.ECDSAP256SHA256 ||
sigrec.getAlgorithm() == DNSSEC.Algorithm.ECDSAP384SHA384) { sigrec.getAlgorithm() == DNSSEC.Algorithm.ECDSAP384SHA384) {
sig = SignUtils.convertECDSASignature(sig); sig = SignUtils.convertECDSASignature(sig);

View File

@ -68,15 +68,21 @@ public class JCEDnsSecSigner {
/** /**
* Cryptographically generate a new DNSSEC key. * Cryptographically generate a new DNSSEC key.
* *
* @param owner the KEY RR's owner name. * @param owner
* @param ttl the KEY RR's TTL. * the KEY RR's owner name.
* @param dclass the KEY RR's DNS class. * @param ttl
* @param algorithm the DNSSEC algorithm (RSASHA258, RSASHA512, * the KEY RR's TTL.
* ECDSAP256, * @param dclass
* etc.) * the KEY RR's DNS class.
* @param flags any flags for the KEY RR. * @param algorithm
* @param keysize the size of the key to generate. * the DNSSEC algorithm (RSASHA258, RSASHA512,
* @param useLargeExponent if generating an RSA key, use the large exponent. * ECDSAP256, etc.)
* @param flags
* any flags for the KEY RR.
* @param keysize
* the size of the key to generate.
* @param useLargeExponent
* if generating an RSA key, use the large exponent.
* @return a DnsKeyPair with the public and private keys populated. * @return a DnsKeyPair with the public and private keys populated.
*/ */
public DnsKeyPair generateKey(Name owner, long ttl, int dclass, int algorithm, public DnsKeyPair generateKey(Name owner, long ttl, int dclass, int algorithm,
@ -107,25 +113,29 @@ public class JCEDnsSecSigner {
/** /**
* Sign an RRset. * Sign an RRset.
* *
* @param rrset the RRset to sign -- any existing signatures are ignored. * @param rrset
* @param keypars a list of DnsKeyPair objects containing private keys. * the RRset to sign -- any existing signatures are ignored.
* @param start the inception time for the resulting RRSIG records. * @param keypars
* @param expire the expiration time for the resulting RRSIG records. * a list of DnsKeyPair objects containing private keys.
* @param start
* the inception time for the resulting RRSIG records.
* @param expire
* the expiration time for the resulting RRSIG records.
* @return a list of RRSIGRecord objects. * @return a list of RRSIGRecord objects.
*/ */
public List<RRSIGRecord> signRRset(RRset rrset, List<DnsKeyPair> keypairs, Instant start, public List<RRSIGRecord> signRRset(RRset rrset, List<DnsKeyPair> keypairs, Instant start,
Instant expire) throws IOException, Instant expire) throws IOException,
GeneralSecurityException { GeneralSecurityException {
if (rrset == null || keypairs == null) if (rrset == null || keypairs == null)
return new ArrayList<>(); return null;
// default start to now, expire to start + 1 second. // default start to now, expire to start + 1 second.
if (start == null) if (start == null)
start = Instant.now(); start = Instant.now();
if (expire == null) if (expire == null)
expire = start.plusSeconds(1); expire = start.plusSeconds(1);
if (keypairs.isEmpty()) if (keypairs.size() == 0)
return new ArrayList<>(); return null;
if (mVerboseSigning) { if (mVerboseSigning) {
log.info("Signing RRset:"); log.info("Signing RRset:");
@ -133,9 +143,9 @@ public class JCEDnsSecSigner {
} }
// first, pre-calculate the RRset bytes. // first, pre-calculate the RRset bytes.
byte[] rrsetData = SignUtils.generateCanonicalRRsetData(rrset, 0, 0); byte[] rrset_data = SignUtils.generateCanonicalRRsetData(rrset, 0, 0);
ArrayList<RRSIGRecord> sigs = new ArrayList<>(keypairs.size()); ArrayList<RRSIGRecord> sigs = new ArrayList<RRSIGRecord>(keypairs.size());
// for each keypair, sign the RRset. // for each keypair, sign the RRset.
for (DnsKeyPair pair : keypairs) { for (DnsKeyPair pair : keypairs) {
@ -145,13 +155,13 @@ public class JCEDnsSecSigner {
RRSIGRecord presig = SignUtils.generatePreRRSIG(rrset, keyrec, start, expire, RRSIGRecord presig = SignUtils.generatePreRRSIG(rrset, keyrec, start, expire,
rrset.getTTL()); rrset.getTTL());
byte[] signData = SignUtils.generateSigData(rrsetData, presig); byte[] sign_data = SignUtils.generateSigData(rrset_data, presig);
if (mVerboseSigning) { if (mVerboseSigning) {
log.info("Canonical pre-signature data to sign with key " log.info("Canonical pre-signature data to sign with key "
+ keyrec.getName().toString() + "/" + keyrec.getAlgorithm() + "/" + keyrec.getName().toString() + "/" + keyrec.getAlgorithm() + "/"
+ keyrec.getFootprint() + ":"); + keyrec.getFootprint() + ":");
log.info(hexdump.dump(null, signData)); log.info(hexdump.dump(null, sign_data));
} }
Signature signer = pair.getSigner(); Signature signer = pair.getSigner();
@ -164,7 +174,7 @@ public class JCEDnsSecSigner {
} }
// sign the data. // sign the data.
signer.update(signData); signer.update(sign_data);
byte[] sig = signer.sign(); byte[] sig = signer.sign();
if (mVerboseSigning) { if (mVerboseSigning) {
@ -174,7 +184,7 @@ public class JCEDnsSecSigner {
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance(); DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
// Convert to RFC 2536 format, if necessary. // Convert to RFC 2536 format, if necessary.
if (algs.baseType(pair.getDNSKEYAlgorithm()) == DnsKeyAlgorithm.BaseAlgorithm.DSA) { if (algs.baseType(pair.getDNSKEYAlgorithm()) == DnsKeyAlgorithm.DSA) {
DSAPublicKey pk = (DSAPublicKey) pair.getPublic(); DSAPublicKey pk = (DSAPublicKey) pair.getPublic();
sig = SignUtils.convertDSASignature(pk.getParams(), sig); sig = SignUtils.convertDSASignature(pk.getParams(), sig);
} }
@ -196,9 +206,12 @@ public class JCEDnsSecSigner {
/** /**
* Create a completely self-signed DNSKEY RRset. * Create a completely self-signed DNSKEY RRset.
* *
* @param keypairs the public & private keypairs to use in the keyset. * @param keypairs
* @param start the RRSIG inception time. * the public & private keypairs to use in the keyset.
* @param expire the RRSIG expiration time. * @param start
* the RRSIG inception time.
* @param expire
* the RRSIG expiration time.
* @return a signed RRset. * @return a signed RRset.
*/ */
public RRset makeKeySet(List<DnsKeyPair> keypairs, Instant start, Instant expire) public RRset makeKeySet(List<DnsKeyPair> keypairs, Instant start, Instant expire)
@ -223,55 +236,67 @@ public class JCEDnsSecSigner {
/** /**
* Conditionally sign an RRset and add it to the toList. * Conditionally sign an RRset and add it to the toList.
* *
* @param toList the list to which we are adding the processed RRsets. * @param toList
* @param zonename the zone apex name. * the list to which we are adding the processed RRsets.
* @param rrset the RRset under consideration. * @param zonename
* @param kskpairs the List of KSKs.. * the zone apex name.
* @param zskpairs the List of zone keys. * @param rrset
* @param start the RRSIG inception time. * the RRset under consideration.
* @param expire the RRSIG expiration time. * @param kskpairs
* @param fullySignKeyset if true, sign the zone apex keyset with both KSKs * the List of KSKs..
* and ZSKs. * @param zskpairs
* @param lastCut the name of the last delegation point encountered. * the List of zone keys.
* @param start
* the RRSIG inception time.
* @param expire
* the RRSIG expiration time.
* @param fullySignKeyset
* if true, sign the zone apex keyset with both KSKs and
* ZSKs.
* @param last_cut
* the name of the last delegation point encountered.
* *
* @return the name of the new last_cut. * @return the name of the new last_cut.
*/ */
private Name addRRset(List<Record> toList, Name zonename, RRset rrset, private Name addRRset(List<Record> toList, Name zonename, RRset rrset,
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs, Instant start, List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs, Instant start,
Instant expire, boolean fullySignKeyset, Name lastCut, Instant expire, boolean fullySignKeyset, Name last_cut,
Name lastDname) throws IOException, GeneralSecurityException { Name last_dname) throws IOException, GeneralSecurityException {
// add the records themselves // add the records themselves
rrset.rrs().forEach(toList::add); rrset.rrs().forEach(record -> {
toList.add(record);
});
int type = SignUtils.recordSecType(zonename, rrset.getName(), rrset.getType(), int type = SignUtils.recordSecType(zonename, rrset.getName(), rrset.getType(),
lastCut, lastDname); last_cut, last_dname);
// we don't sign non-normal sets (delegations, glue, invalid). // we don't sign non-normal sets (delegations, glue, invalid).
if (type == SignUtils.RR_DELEGATION) { if (type == SignUtils.RR_DELEGATION) {
return rrset.getName(); return rrset.getName();
} }
if (type == SignUtils.RR_GLUE || type == SignUtils.RR_INVALID) { if (type == SignUtils.RR_GLUE || type == SignUtils.RR_INVALID) {
return lastCut; return last_cut;
} }
// check for the zone apex keyset. // check for the zone apex keyset.
if (rrset.getName().equals(zonename) && rrset.getType() == Type.DNSKEY && kskpairs != null && !kskpairs.isEmpty()) { if (rrset.getName().equals(zonename) && rrset.getType() == Type.DNSKEY) {
// if we have ksks, sign the keyset with them, otherwise we will just sign // if we have ksks, sign the keyset with them, otherwise we will just sign
// them with the zsks. // them with the zsks.
List<RRSIGRecord> sigs = signRRset(rrset, kskpairs, start, expire); if (kskpairs != null && kskpairs.size() > 0) {
toList.addAll(sigs); List<RRSIGRecord> sigs = signRRset(rrset, kskpairs, start, expire);
toList.addAll(sigs);
// If we aren't going to sign with all the keys, bail out now.
if (!fullySignKeyset)
return lastCut;
// If we aren't going to sign with all the keys, bail out now.
if (!fullySignKeyset)
return last_cut;
}
} }
// otherwise, we are OK to sign this set. // otherwise, we are OK to sign this set.
List<RRSIGRecord> sigs = signRRset(rrset, zskpairs, start, expire); List<RRSIGRecord> sigs = signRRset(rrset, zskpairs, start, expire);
toList.addAll(sigs); toList.addAll(sigs);
return lastCut; return last_cut;
} }
// Various NSEC/NSEC3 generation modes // Various NSEC/NSEC3 generation modes
@ -286,31 +311,49 @@ public class JCEDnsSecSigner {
* Opt-Out, etc.) External users of this class are expected to use the * Opt-Out, etc.) External users of this class are expected to use the
* appropriate public signZone* methods instead of this. * appropriate public signZone* methods instead of this.
* *
* @param zonename The name of the zone * @param zonename
* @param records The records comprising the zone. They do not have to * The name of the zone
* be in any particular order, as this method will * @param records
* order them as necessary. * The records comprising the zone. They do not have to
* @param kskpairs The key pairs designated as "key signing keys" * be in any
* @param zskpairs The key pairs designated as "zone signing keys" * particular order, as this method will order them as
* @param start The RRSIG inception time * necessary.
* @param expire The RRSIG expiration time * @param kskpairs
* @param fullySignKeyset If true, all keys (ksk or zsk) will sign the DNSKEY * The key pairs designated as "key signing keys"
* RRset. If false, only the ksks will sign it. * @param zskpairs
* @param dsDigestAlg The hash algorithm to use for generating DS records * The key pairs designated as "zone signing keys"
* @param start
* The RRSIG inception time
* @param expire
* The RRSIG expiration time
* @param fullySignKeyset
* If true, all keys (ksk or zsk) will sign the DNSKEY
* RRset. If
* false, only the ksks will sign it.
* @param ds_digest_alg
* The hash algorithm to use for generating DS records
* (DSRecord.SHA1_DIGEST_ID, e.g.) * (DSRecord.SHA1_DIGEST_ID, e.g.)
* @param mode The NSEC/NSEC3 generation mode: NSEC_MODE, * @param mode
* NSEC3_MODE, NSEC3_OPTOUT_MODE, etc. * The NSEC/NSEC3 generation mode: NSEC_MODE, NSEC3_MODE,
* @param includedNames When using an Opt-In/Opt-Out mode, the names listed * NSEC3_OPTOUT_MODE, etc.
* here will be included in the NSEC/NSEC3 chain * @param includedNames
* regardless * When using an Opt-In/Opt-Out mode, the names listed
* @param salt When using an NSEC3 mode, use this salt. * here will be
* @param iterations When using an NSEC3 mode, use this number of * included in the NSEC/NSEC3 chain regardless
* @param salt
* When using an NSEC3 mode, use this salt.
* @param iterations
* When using an NSEC3 mode, use this number of
* iterations * iterations
* @param beConservative If true, then only turn on the Opt-In flag when * @param beConservative
* there are insecure delegations in the span. * If true, then only turn on the Opt-In flag when there
* Currently this only works for NSEC_EXP_OPT_IN mode. * are insecure
* @param nsec3paramttl The TTL to use for the generated NSEC3PARAM record. * delegations in the span. Currently this only works for
* Negative values will use the SOA TTL. * NSEC_EXP_OPT_IN mode.
* @param nsec3paramttl
* The TTL to use for the generated NSEC3PARAM record.
* Negative
* values will use the SOA TTL.
* @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.
* *
@ -320,7 +363,7 @@ public class JCEDnsSecSigner {
private List<Record> signZone(Name zonename, List<Record> records, private List<Record> signZone(Name zonename, List<Record> records,
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs, List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs,
Instant start, Instant expire, boolean fullySignKeyset, Instant start, Instant expire, boolean fullySignKeyset,
int dsDigestAlg, int mode, List<Name> includedNames, int ds_digest_alg, int mode, List<Name> includedNames,
byte[] salt, int iterations, long nsec3paramttl, byte[] salt, int iterations, long nsec3paramttl,
boolean beConservative) throws IOException, boolean beConservative) throws IOException,
GeneralSecurityException { GeneralSecurityException {
@ -337,7 +380,7 @@ public class JCEDnsSecSigner {
// Generate DS records. This replaces any non-zone-apex DNSKEY RRs with DS // Generate DS records. This replaces any non-zone-apex DNSKEY RRs with DS
// RRs. // RRs.
SignUtils.generateDSRecords(zonename, records, dsDigestAlg); SignUtils.generateDSRecords(zonename, records, ds_digest_alg);
// Generate the NSEC or NSEC3 records based on 'mode' // Generate the NSEC or NSEC3 records based on 'mode'
switch (mode) { switch (mode) {
@ -355,8 +398,6 @@ public class JCEDnsSecSigner {
SignUtils.generateOptInNSECRecords(zonename, records, includedNames, SignUtils.generateOptInNSECRecords(zonename, records, includedNames,
beConservative); beConservative);
break; break;
default:
throw new NoSuchAlgorithmException("Unknown NSEC/NSEC3 mode: " + mode);
} }
// Re-sort so we can assemble into rrsets. // Re-sort so we can assemble into rrsets.
@ -364,9 +405,9 @@ public class JCEDnsSecSigner {
// Assemble into RRsets and sign. // Assemble into RRsets and sign.
RRset rrset = new RRset(); RRset rrset = new RRset();
ArrayList<Record> signedRecords = new ArrayList<>(); ArrayList<Record> signed_records = new ArrayList<Record>();
Name lastCut = null; Name last_cut = null;
Name lastDname = null; Name last_dname = null;
for (ListIterator<Record> i = records.listIterator(); i.hasNext();) { for (ListIterator<Record> i = records.listIterator(); i.hasNext();) {
Record r = i.next(); Record r = i.next();
@ -389,38 +430,48 @@ public class JCEDnsSecSigner {
// add the RRset to the list of signed_records, regardless of // add the RRset to the list of signed_records, regardless of
// whether or not we actually end up signing the set. // whether or not we actually end up signing the set.
lastCut = addRRset(signedRecords, zonename, rrset, kskpairs, zskpairs, start, last_cut = addRRset(signed_records, zonename, rrset, kskpairs, zskpairs, start,
expire, fullySignKeyset, lastCut, lastDname); expire, fullySignKeyset, last_cut, last_dname);
if (rrset.getType() == Type.DNAME) if (rrset.getType() == Type.DNAME)
lastDname = rrset.getName(); last_dname = rrset.getName();
rrset.clear(); rrset.clear();
rrset.addRR(r); rrset.addRR(r);
} }
// add the last RR set // add the last RR set
addRRset(signedRecords, zonename, rrset, kskpairs, zskpairs, start, expire, addRRset(signed_records, zonename, rrset, kskpairs, zskpairs, start, expire,
fullySignKeyset, lastCut, lastDname); fullySignKeyset, last_cut, last_dname);
return signedRecords; return signed_records;
} }
/** /**
* Given a zone, sign it using standard NSEC records. * Given a zone, sign it using standard NSEC records.
* *
* @param zonename The name of the zone. * @param zonename
* @param records The records comprising the zone. They do not have to * The name of the zone.
* be in any particular order, as this method will * @param records
* order them as necessary. * The records comprising the zone. They do not have to
* @param kskpairs The key pairs that are designated as "key signing * be in any
* particular order, as this method will order them as
* necessary.
* @param kskpairs
* The key pairs that are designated as "key signing
* keys". * keys".
* @param zskpairs This key pairs that are designated as "zone signing * @param zskpairs
* This key pairs that are designated as "zone signing
* keys". * keys".
* @param start The RRSIG inception time. * @param start
* @param expire The RRSIG expiration time. * The RRSIG inception time.
* @param fullySignKeyset Sign the zone apex keyset with all available keys * @param expire
* (instead of just the key signing keys). * The RRSIG expiration time.
* @param dsDigestAlg The digest algorithm to use when generating DS * @param fullySignKeyset
* Sign the zone apex keyset with all available keys
* (instead of just
* the key signing keys).
* @param ds_digest_alg
* The digest algorithm to use when generating DS
* records. * records.
* *
* @return an ordered list of {@link org.xbill.DNS.Record} objects, * @return an ordered list of {@link org.xbill.DNS.Record} objects,
@ -429,42 +480,58 @@ public class JCEDnsSecSigner {
public List<Record> signZone(Name zonename, List<Record> records, public List<Record> signZone(Name zonename, List<Record> records,
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs, List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs,
Instant start, Instant expire, boolean fullySignKeyset, Instant start, Instant expire, boolean fullySignKeyset,
int dsDigestAlg) throws IOException, int ds_digest_alg) throws IOException,
GeneralSecurityException { GeneralSecurityException {
return signZone(zonename, records, kskpairs, zskpairs, start, expire, return signZone(zonename, records, kskpairs, zskpairs, start, expire,
fullySignKeyset, dsDigestAlg, NSEC_MODE, null, null, 0, 0, false); fullySignKeyset, ds_digest_alg, NSEC_MODE, null, null, 0, 0, false);
} }
/** /**
* Given a zone, sign it using NSEC3 records. * Given a zone, sign it using NSEC3 records.
* *
* @param signer A signer (utility) object used to actually sign * @param signer
* stuff. * A signer (utility) object used to actually sign stuff.
* @param zonename The name of the zone being signed. * @param zonename
* @param records The records comprising the zone. They do not have to * The name of the zone being signed.
* be in any particular order, as this method will * @param records
* order them as necessary. * The records comprising the zone. They do not have to
* @param kskpairs The key pairs that are designated as "key signing * be in any
* particular order, as this method will order them as
* necessary.
* @param kskpairs
* The key pairs that are designated as "key signing
* keys". * keys".
* @param zskpairs This key pairs that are designated as "zone signing * @param zskpairs
* This key pairs that are designated as "zone signing
* keys". * keys".
* @param start The RRSIG inception time. * @param start
* @param expire The RRSIG expiration time. * The RRSIG inception time.
* @param fullySignKeyset If true then the DNSKEY RRset will be signed by all * @param expire
* available keys, if false, only the key signing keys. * The RRSIG expiration time.
* @param useOptOut If true, insecure delegations will be omitted from * @param fullySignKeyset
* the NSEC3 chain, and all NSEC3 records will have the * If true then the DNSKEY RRset will be signed by all
* Opt-Out flag set. * available
* @param includedNames A list of names to include in the NSEC3 chain * 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. * regardless.
* @param salt The salt to use for the NSEC3 hashing. null means no * @param salt
* The salt to use for the NSEC3 hashing. null means no
* salt. * salt.
* @param iterations The number of iterations to use for the NSEC3 * @param iterations
* hashing. * The number of iterations to use for the NSEC3 hashing.
* @param dsDigestAlg The digest algorithm to use when generating DS * @param ds_digest_alg
* The digest algorithm to use when generating DS
* records. * records.
* @param nsec3paramttl The TTL to use for the generated NSEC3PARAM record. * @param nsec3paramttl
* Negative values will use the SOA TTL. * The TTL to use for the generated NSEC3PARAM record.
* Negative
* values will use the SOA TTL.
* @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.
* *
@ -475,16 +542,16 @@ public class JCEDnsSecSigner {
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs, List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs,
Instant start, Instant expire, boolean fullySignKeyset, Instant start, Instant expire, boolean fullySignKeyset,
boolean useOptOut, List<Name> includedNames, boolean useOptOut, List<Name> includedNames,
byte[] salt, int iterations, int dsDigestAlg, byte[] salt, int iterations, int ds_digest_alg,
long nsec3paramttl) throws IOException, long nsec3paramttl) throws IOException,
GeneralSecurityException { GeneralSecurityException {
if (useOptOut) { if (useOptOut) {
return signZone(zonename, records, kskpairs, zskpairs, start, expire, return signZone(zonename, records, kskpairs, zskpairs, start, expire,
fullySignKeyset, dsDigestAlg, NSEC3_OPTOUT_MODE, includedNames, fullySignKeyset, ds_digest_alg, NSEC3_OPTOUT_MODE, includedNames,
salt, iterations, nsec3paramttl, false); salt, iterations, nsec3paramttl, false);
} else { } else {
return signZone(zonename, records, kskpairs, zskpairs, start, expire, return signZone(zonename, records, kskpairs, zskpairs, start, expire,
fullySignKeyset, dsDigestAlg, NSEC3_MODE, null, salt, iterations, fullySignKeyset, ds_digest_alg, NSEC3_MODE, null, salt, iterations,
nsec3paramttl, false); nsec3paramttl, false);
} }
} }
@ -493,25 +560,37 @@ public class JCEDnsSecSigner {
* Given a zone, sign it using experimental Opt-In NSEC records (see RFC * Given a zone, sign it using experimental Opt-In NSEC records (see RFC
* 4956). * 4956).
* *
* @param zonename the name of the zone. * @param zonename
* @param records the records comprising the zone. They do not * the name of the zone.
* have to be in any particular order, as this * @param records
* method will order them as necessary. * the records comprising the zone. They do not have
* @param kskpairs the key pairs that are designated as "key * to be in any
* particular order, as this method will order them
* as necessary.
* @param kskpairs
* the key pairs that are designated as "key signing
* keys".
* @param zskpairs
* this key pairs that are designated as "zone
* signing keys". * signing keys".
* @param zskpairs this key pairs that are designated as "zone * @param start
* signing keys". * the RRSIG inception time.
* @param start the RRSIG inception time. * @param expire
* @param expire the RRSIG expiration time. * the RRSIG expiration time.
* @param useConservativeOptIn if true, Opt-In NSEC records will only be * @param useConservativeOptIn
* generated if there are insecure, unsigned * if true, Opt-In NSEC records will only be
* delegations in the span. * generated if there are
* @param fullySignKeyset sign the zone apex keyset with all available * insecure, unsigned delegations in the span.
* @param fullySignKeyset
* sign the zone apex keyset with all available
* keys. * keys.
* @param dsDigestAlg The digest algorithm to use when generating DS * @param ds_digest_alg
* The digest algorithm to use when generating DS
* records. * records.
* @param nsecIncludeNames names that are to be included in the NSEC chain * @param NSECIncludeNames
* regardless. This may be null. * names that are to be included in the NSEC chain
* regardless. This
* may be null.
* @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.
*/ */
@ -519,12 +598,12 @@ public class JCEDnsSecSigner {
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs, List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs,
Instant start, Instant expire, Instant start, Instant expire,
boolean useConservativeOptIn, boolean useConservativeOptIn,
boolean fullySignKeyset, List<Name> nsecIncludeNames, boolean fullySignKeyset, List<Name> NSECIncludeNames,
int dsDigestAlg) throws IOException, int ds_digest_alg) throws IOException,
GeneralSecurityException { GeneralSecurityException {
return signZone(zonename, records, kskpairs, zskpairs, start, expire, return signZone(zonename, records, kskpairs, zskpairs, start, expire,
fullySignKeyset, dsDigestAlg, NSEC_EXP_OPT_IN, nsecIncludeNames, fullySignKeyset, ds_digest_alg, NSEC_EXP_OPT_IN, NSECIncludeNames,
null, 0, 0, useConservativeOptIn); null, 0, 0, useConservativeOptIn);
} }
} }

View File

@ -33,7 +33,6 @@ import org.xbill.DNS.Type;
public class RecordComparator implements Comparator<Record> { public class RecordComparator implements Comparator<Record> {
public RecordComparator() { public RecordComparator() {
// nothing to initialize
} }
/** /**
@ -66,15 +65,15 @@ public class RecordComparator implements Comparator<Record> {
} }
private int compareRDATA(Record a, Record b) { private int compareRDATA(Record a, Record b) {
byte[] aRdata = a.rdataToWireCanonical(); byte[] a_rdata = a.rdataToWireCanonical();
byte[] bRdata = b.rdataToWireCanonical(); byte[] b_rdata = b.rdataToWireCanonical();
for (int i = 0; i < aRdata.length && i < bRdata.length; i++) { for (int i = 0; i < a_rdata.length && i < b_rdata.length; i++) {
int n = (aRdata[i] & 0xFF) - (bRdata[i] & 0xFF); int n = (a_rdata[i] & 0xFF) - (b_rdata[i] & 0xFF);
if (n != 0) if (n != 0)
return n; return n;
} }
return (aRdata.length - bRdata.length); return (a_rdata.length - b_rdata.length);
} }
public int compare(Record a, Record b) { public int compare(Record a, Record b) {
@ -89,27 +88,27 @@ public class RecordComparator implements Comparator<Record> {
if (res != 0) if (res != 0)
return res; return res;
int aType = a.getType(); int a_type = a.getType();
int bType = b.getType(); int b_type = b.getType();
int sigType = 0; int sig_type = 0;
if (aType == Type.RRSIG) { if (a_type == Type.RRSIG) {
aType = ((RRSIGRecord) a).getTypeCovered(); a_type = ((RRSIGRecord) a).getTypeCovered();
if (bType != Type.RRSIG) if (b_type != Type.RRSIG)
sigType = 1; sig_type = 1;
} }
if (bType == Type.RRSIG) { if (b_type == Type.RRSIG) {
bType = ((RRSIGRecord) b).getTypeCovered(); b_type = ((RRSIGRecord) b).getTypeCovered();
if (a.getType() != Type.RRSIG) if (a.getType() != Type.RRSIG)
sigType = -1; sig_type = -1;
} }
res = compareTypes(aType, bType); res = compareTypes(a_type, b_type);
if (res != 0) if (res != 0)
return res; return res;
if (sigType != 0) if (sig_type != 0)
return sigType; return sig_type;
return compareRDATA(a, b); return compareRDATA(a, b);
} }

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,7 @@ public class TypeMap {
private Set<Integer> typeSet; private Set<Integer> typeSet;
public TypeMap() { public TypeMap() {
this.typeSet = new HashSet<>(); this.typeSet = new HashSet<Integer>();
} }
/** Add the given type to the typemap. */ /** Add the given type to the typemap. */
@ -78,20 +78,20 @@ public class TypeMap {
TypeMap typemap = new TypeMap(); TypeMap typemap = new TypeMap();
int page; int page;
int byteLength; int byte_length;
while (m < map.length) { while (m < map.length) {
page = map[m++]; page = map[m++];
byteLength = map[m++]; byte_length = map[m++];
for (int i = 0; i < byteLength; i++) { for (int i = 0; i < byte_length; i++) {
for (int j = 0; j < 8; j++) { for (int j = 0; j < 8; j++) {
if (((map[m + i] & 0xFF) & (1 << (7 - j))) != 0) { if ((map[m + i] & (1 << (7 - j))) != 0) {
typemap.set((page << 8) + (i * 8) + j); typemap.set((page << 8) + (i * 8) + j);
} }
} }
} }
m += byteLength; m += byte_length;
} }
return typemap; return typemap;
@ -115,7 +115,7 @@ public class TypeMap {
int[] types = getTypes(); int[] types = getTypes();
Arrays.sort(types); Arrays.sort(types);
StringBuilder sb = new StringBuilder(); StringBuffer sb = new StringBuffer();
for (int i = 0; i < types.length; i++) { for (int i = 0; i < types.length; i++) {
if (i > 0) if (i > 0)
@ -129,16 +129,16 @@ public class TypeMap {
protected static void mapToWire(DNSOutput out, int[] types, int base, int start, int end) { protected static void mapToWire(DNSOutput out, int[] types, int base, int start, int end) {
// calculate the length of this map by looking at the largest // calculate the length of this map by looking at the largest
// typecode in this section. // typecode in this section.
int maxType = types[end - 1] & 0xFF; int max_type = types[end - 1] & 0xFF;
int mapLength = (maxType / 8) + 1; int map_length = (max_type / 8) + 1;
// write the map "header" -- the base and the length of the map. // write the map "header" -- the base and the length of the map.
out.writeU8(base & 0xFF); out.writeU8(base & 0xFF);
out.writeU8(mapLength & 0xFF); out.writeU8(map_length & 0xFF);
// allocate a temporary scratch space for caculating the actual // allocate a temporary scratch space for caculating the actual
// bitmap. // bitmap.
byte[] map = new byte[mapLength]; byte[] map = new byte[map_length];
// for each type in our sub-array, set its corresponding bit in the map. // for each type in our sub-array, set its corresponding bit in the map.
for (int i = start; i < end; i++) { for (int i = start; i < end; i++) {
@ -179,7 +179,7 @@ public class TypeMap {
} }
public int[] getTypes() { public int[] getTypes() {
Integer[] a = typeSet.toArray(integerArray); Integer[] a = (Integer[]) typeSet.toArray(integerArray);
int[] res = new int[a.length]; int[] res = new int[a.length];
for (int i = 0; i < res.length; i++) { for (int i = 0; i < res.length; i++) {
@ -189,8 +189,8 @@ public class TypeMap {
return res; return res;
} }
public static int[] fromWireToTypes(byte[] wireFmt) { public static int[] fromWireToTypes(byte[] wire_fmt) {
return TypeMap.fromBytes(wireFmt).getTypes(); return TypeMap.fromBytes(wire_fmt).getTypes();
} }
public static byte[] fromTypesToWire(int[] types) { public static byte[] fromTypesToWire(int[] types) {

View File

@ -39,10 +39,6 @@ import org.xbill.DNS.Type;
*/ */
public class ZoneUtils { public class ZoneUtils {
private ZoneUtils() {
}
/** /**
* Load a zone file. * Load a zone file.
* *
@ -57,10 +53,19 @@ public class ZoneUtils {
* if something goes wrong reading the zone file. * if something goes wrong reading the zone file.
*/ */
public static List<Record> readZoneFile(String zonefile, Name origin) throws IOException { public static List<Record> readZoneFile(String zonefile, Name origin) throws IOException {
ArrayList<Record> records = new ArrayList<>(); ArrayList<Record> records = new ArrayList<Record>();
try (Master m = zonefile.equals("-") ? new Master(System.in) : new Master(zonefile, origin)) { Master m;
try {
if (zonefile.equals("-")) {
m = new Master(System.in);
} else {
m = new Master(zonefile, origin);
}
Record r = null; Record r = null;
while ((r = m.nextRecord()) != null) { while ((r = m.nextRecord()) != null) {
records.add(r); records.add(r);
} }
} catch (IOException e) { } catch (IOException e) {
@ -115,7 +120,7 @@ public class ZoneUtils {
} }
public static List<Record> findRRs(List<Record> records, Name name, int type) { public static List<Record> findRRs(List<Record> records, Name name, int type) {
List<Record> res = new ArrayList<>(); List<Record> res = new ArrayList<Record>();
for (Record r : records) { for (Record r : records) {
if (r.getName().equals(name) && r.getType() == type) { if (r.getName().equals(name) && r.getType() == type) {
res.add(r); res.add(r);

View File

@ -88,12 +88,10 @@ public class ZoneVerifier {
public boolean equals(Object o) { public boolean equals(Object o) {
return super.equals(o); return super.equals(o);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return super.hashCode(); return super.hashCode();
} }
boolean getMark() { boolean getMark() {
return mIsMarked; return mIsMarked;
} }
@ -150,8 +148,7 @@ public class ZoneVerifier {
/** /**
* Add a record to the various maps. * Add a record to the various maps.
* *
* @return true if the RR was added, false if it wasn't (because it was a * @return true if the RR was added, false if it wasn't (because it was a duplicate)
* duplicate)
*/ */
private boolean addRR(Record r) { private boolean addRR(Record r) {
Name n = r.getName(); Name n = r.getName();
@ -209,7 +206,7 @@ public class ZoneVerifier {
* Given an unsorted list of records, load the node and rrset maps, as well as * Given an unsorted list of records, load the node and rrset maps, as well as
* determine the NSEC3 parameters and signing type. * determine the NSEC3 parameters and signing type.
* *
* @param records an unsorted list of {@link org.xbill.DNS.Record} objects. * @param records
* @return the number of errors encountered. * @return the number of errors encountered.
*/ */
private int calculateNodes(List<Record> records) { private int calculateNodes(List<Record> records) {
@ -254,7 +251,7 @@ public class ZoneVerifier {
* Given a name, typeset, and name of the last zone cut, determine the node * Given a name, typeset, and name of the last zone cut, determine the node
* type. * type.
*/ */
private NodeType determineNodeType(Name n, Set<Integer> typeset, Name lastCut) { private NodeType determineNodeType(Name n, Set<Integer> typeset, Name last_cut) {
// All RRs at the zone apex are normal // All RRs at the zone apex are normal
if (n.equals(mZoneName)) if (n.equals(mZoneName))
return NodeType.NORMAL; return NodeType.NORMAL;
@ -266,7 +263,7 @@ public class ZoneVerifier {
} }
// If the node is below a zone cut (either a delegation or DNAME), it is // If the node is below a zone cut (either a delegation or DNAME), it is
// glue. // glue.
if (lastCut != null && n.subdomain(lastCut) && !n.equals(lastCut)) { if (last_cut != null && n.subdomain(last_cut) && !n.equals(last_cut)) {
return NodeType.GLUE; return NodeType.GLUE;
} }
@ -297,13 +294,13 @@ public class ZoneVerifier {
*/ */
private int processNodes() throws NoSuchAlgorithmException, TextParseException { private int processNodes() throws NoSuchAlgorithmException, TextParseException {
int errors = 0; int errors = 0;
Name lastCut = null; Name last_cut = null;
for (Map.Entry<Name, Set<Integer>> entry : mNodeMap.entrySet()) { for (Map.Entry<Name, Set<Integer>> entry : mNodeMap.entrySet()) {
Name n = entry.getKey(); Name n = entry.getKey();
Set<Integer> typeset = entry.getValue(); Set<Integer> typeset = entry.getValue();
NodeType ntype = determineNodeType(n, typeset, lastCut); NodeType ntype = determineNodeType(n, typeset, last_cut);
log.finest("Node " + n + " is type " + ntype); log.finest("Node " + n + " is type " + ntype);
// we can ignore glue/invalid RRs. // we can ignore glue/invalid RRs.
@ -312,7 +309,7 @@ public class ZoneVerifier {
// record the last zone cut if this node is a zone cut. // record the last zone cut if this node is a zone cut.
if (ntype == NodeType.DELEGATION || typeset.contains(Type.DNAME)) { if (ntype == NodeType.DELEGATION || typeset.contains(Type.DNAME)) {
lastCut = n; last_cut = n;
} }
// check all of the RRsets that should be signed // check all of the RRsets that should be signed