diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 00a51af..0000000 --- a/.gitattributes +++ /dev/null @@ -1,6 +0,0 @@ -# -# https://help.github.com/articles/dealing-with-line-endings/ -# -# These are explicitly windows files and should use crlf -*.bat text eol=crlf - diff --git a/build.gradle b/build.gradle deleted file mode 100644 index fe7f1ed..0000000 --- a/build.gradle +++ /dev/null @@ -1,25 +0,0 @@ -/** - -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') -} diff --git a/build.properties b/build.properties index b4d59bd..5fd8860 100644 --- a/build.properties +++ b/build.properties @@ -1,3 +1,3 @@ -#build.compiler=jikes -#build.compiler=modern build.deprecation=true +build.debug=false +build.java_version=17 diff --git a/build.xml b/build.xml index a48e9df..d7fb0ff 100644 --- a/build.xml +++ b/build.xml @@ -44,11 +44,11 @@ + debug="${build.debug}" + release="${build.java_version}" /> @@ -154,13 +154,11 @@ - - - + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e708b1c..0000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 4d9ca16..0000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -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 diff --git a/gradlew b/gradlew deleted file mode 100755 index 4f906e0..0000000 --- a/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/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" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index ac1b06f..0000000 --- a/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@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 diff --git a/lib/commons-cli-1.5.0.jar b/lib/commons-cli-1.5.0.jar deleted file mode 100644 index e036456..0000000 Binary files a/lib/commons-cli-1.5.0.jar and /dev/null differ diff --git a/lib/commons-cli-1.6.0.jar b/lib/commons-cli-1.6.0.jar new file mode 100644 index 0000000..4103ab9 Binary files /dev/null and b/lib/commons-cli-1.6.0.jar differ diff --git a/lib/dnsjava-3.5.1.jar b/lib/dnsjava-3.5.3.jar similarity index 55% rename from lib/dnsjava-3.5.1.jar rename to lib/dnsjava-3.5.3.jar index 6333f86..a07936b 100644 Binary files a/lib/dnsjava-3.5.1.jar and b/lib/dnsjava-3.5.3.jar differ diff --git a/lib/eddsa-0.3.0.jar b/lib/eddsa-0.3.0.jar deleted file mode 100644 index 22c0981..0000000 Binary files a/lib/eddsa-0.3.0.jar and /dev/null differ diff --git a/src/main/java/com/verisignlabs/dnssec/cl/DSTool.java b/src/main/java/com/verisignlabs/dnssec/cl/DSTool.java index 3054555..0fba4a8 100644 --- a/src/main/java/com/verisignlabs/dnssec/cl/DSTool.java +++ b/src/main/java/com/verisignlabs/dnssec/cl/DSTool.java @@ -56,7 +56,7 @@ public class DSTool extends CLBase { public dsType createType = dsType.DS; public String outputfile = null; public String keyname = null; - public int digestId = DNSSEC.Digest.SHA1; + public int digestId = DNSSEC.Digest.SHA256; public CLIState() { super("jdnssec-dstool [..options..] keyfile"); @@ -71,7 +71,8 @@ public class DSTool extends CLBase { protected void setupOptions(Options opts) { 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("d").hasArg().argName("id").longOpt("digest").desc("The digest algorithm to use").build()); + opts.addOption( + 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()); } @@ -120,9 +121,9 @@ public class DSTool extends CLBase { log.fine("creating CDS."); CDSRecord cds = new CDSRecord(ds.getName(), ds.getDClass(), ds.getTTL(), ds.getFootprint(), ds.getAlgorithm(), ds.getDClass(), ds.getDigest()); - res = cds; + res = cds; } - + if (state.outputfile != null && !state.outputfile.equals("-")) { try (PrintWriter out = new PrintWriter(new FileWriter(state.outputfile))) { out.println(res); diff --git a/src/main/java/com/verisignlabs/dnssec/cl/KeyGen.java b/src/main/java/com/verisignlabs/dnssec/cl/KeyGen.java index 16b292b..f757d75 100644 --- a/src/main/java/com/verisignlabs/dnssec/cl/KeyGen.java +++ b/src/main/java/com/verisignlabs/dnssec/cl/KeyGen.java @@ -44,8 +44,8 @@ public class KeyGen extends CLBase { * state. */ protected static class CLIState extends CLIStateBase { - public int algorithm = 8; - public int keylength = 1024; + public int algorithm = 13; + public int keylength = 2048; public boolean useLargeE = true; public String outputfile = null; public File keydir = null; @@ -77,10 +77,10 @@ public class KeyGen extends CLBase { String[] algStrings = DnsKeyAlgorithm.getInstance().supportedAlgMnemonics(); String algStringSet = String.join(" | ", algStrings); opts.addOption(Option.builder("a").hasArg().argName("algorithm") - .desc(algStringSet + " | alias, RSASHA256 is default.").build()); + .desc(algStringSet + " | alias, ECDSAP256SHA256 is default.").build()); opts.addOption(Option.builder("b").hasArg().argName("size").desc( - "key size, in bits (default 1024). RSA: [512..4096], DSA: [512..1024], DH: [128..4096], ECDSA: ignored, EdDSA: ignored") + "key size, in bits (default 2048). RSA: [512..4096], DSA: [512..1024], DH: [128..4096], ECDSA: ignored, EdDSA: ignored") .build()); opts.addOption(Option.builder("f").hasArg().argName("file").longOpt("output-file") .desc("base filename from the public/private key files").build()); diff --git a/src/main/java/com/verisignlabs/dnssec/cl/KeyInfoTool.java b/src/main/java/com/verisignlabs/dnssec/cl/KeyInfoTool.java index 25df385..5df30b2 100644 --- a/src/main/java/com/verisignlabs/dnssec/cl/KeyInfoTool.java +++ b/src/main/java/com/verisignlabs/dnssec/cl/KeyInfoTool.java @@ -84,13 +84,13 @@ public class KeyInfoTool extends CLBase { + " (" + dnskey.getAlgorithm() + ")"); System.out.println("ID: " + dnskey.getFootprint()); System.out.println("KeyFileBase: " + BINDKeyUtils.keyFileBase(key)); - int basetype = dnskeyalg.baseType(dnskey.getAlgorithm()); + DnsKeyAlgorithm.BaseAlgorithm basetype = dnskeyalg.baseType(dnskey.getAlgorithm()); - if (basetype == DnsKeyAlgorithm.RSA) { + if (basetype == DnsKeyAlgorithm.BaseAlgorithm.RSA) { RSAPublicKey pub = (RSAPublicKey) key.getPublic(); System.out.println("RSA Public Exponent: " + pub.getPublicExponent()); System.out.println("RSA Modulus: " + pub.getModulus()); - } else if (basetype == DnsKeyAlgorithm.DSA) { + } else if (basetype == DnsKeyAlgorithm.BaseAlgorithm.DSA) { DSAPublicKey pub = (DSAPublicKey) key.getPublic(); System.out.println("DSA base (G): " + pub.getParams().getG()); System.out.println("DSA prime (P): " + pub.getParams().getP()); diff --git a/src/main/java/com/verisignlabs/dnssec/cl/SignKeyset.java b/src/main/java/com/verisignlabs/dnssec/cl/SignKeyset.java index fc2dbf5..86a0776 100644 --- a/src/main/java/com/verisignlabs/dnssec/cl/SignKeyset.java +++ b/src/main/java/com/verisignlabs/dnssec/cl/SignKeyset.java @@ -75,10 +75,14 @@ public class SignKeyset extends CLBase { opts.addOption("a", "verify", false, "verify generated signatures>"); // Argument options - opts.addOption(Option.builder("D").hasArg().argName("dir").longOpt("key-directory").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("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()); + opts.addOption(Option.builder("D").hasArg().argName("dir").longOpt("key-directory") + .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("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 @@ -129,11 +133,9 @@ public class SignKeyset extends CLBase { /** * Verify the generated signatures. - * - * @param records - * a list of {@link org.xbill.DNS.Record}s. - * @param keypairs - * a list of keypairs used the sign the zone. + * + * @param records 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. */ private static boolean verifySigs(List records, @@ -168,16 +170,13 @@ public class SignKeyset extends CLBase { /** * Load the key pairs from the key files. - * - * @param keyfiles - * a string array containing the base names or paths of the - * keys - * to be loaded. - * @param startIndex - * 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). + * + * @param keyfiles a string array containing the base names or paths of the + * keys to be loaded. + * @param startIndex 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. */ private static List getKeys(String[] keyfiles, int startIndex, @@ -244,8 +243,8 @@ public class SignKeyset extends CLBase { } // Make sure that all records are DNSKEYs with the same name. - Name keysetName = null; - RRset keyset = new RRset(); + Name keysetName = null; + RRset keyset = new RRset(); for (Record r : records) { if (r.getType() != Type.DNSKEY) { diff --git a/src/main/java/com/verisignlabs/dnssec/cl/SignRRset.java b/src/main/java/com/verisignlabs/dnssec/cl/SignRRset.java index 940537f..46f39b5 100644 --- a/src/main/java/com/verisignlabs/dnssec/cl/SignRRset.java +++ b/src/main/java/com/verisignlabs/dnssec/cl/SignRRset.java @@ -55,14 +55,14 @@ public class SignRRset extends CLBase { * This is an inner class used to hold all of the command line option state. */ protected static class CLIState extends CLIStateBase { - private File keyDirectory = null; - public String[] keyFiles = null; - public Instant start = null; - public Instant expire = null; - public String inputfile = null; - public String outputfile = null; - public boolean verifySigs = false; - public boolean verboseSigning = false; + private File keyDirectory = null; + public String[] keyFiles = null; + public Instant start = null; + public Instant expire = null; + public String inputfile = null; + public String outputfile = null; + public boolean verifySigs = false; + public boolean verboseSigning = false; public CLIState() { super("jdnssec-signrrset [..options..] rrset_file key_file [key_file ...]"); @@ -137,10 +137,8 @@ public class SignRRset extends CLBase { /** * Verify the generated signatures. * - * @param records - * a list of {@link org.xbill.DNS.Record}s. - * @param keypairs - * a list of keypairs used the sign the zone. + * @param records 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. */ private static boolean verifySigs(List records, List keypairs) { @@ -176,15 +174,12 @@ public class SignRRset extends CLBase { /** * Load the key pairs from the key files. * - * @param keyfiles - * a string array containing the base names or paths of the - * keys - * to be loaded. - * @param startIndex - * 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). + * @param keyfiles a string array containing the base names or paths of the + * keys to be loaded. + * @param startIndex 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. */ private static List getKeys(String[] keyfiles, int startIndex, diff --git a/src/main/java/com/verisignlabs/dnssec/cl/SignZone.java b/src/main/java/com/verisignlabs/dnssec/cl/SignZone.java index 96f9fa5..2268755 100644 --- a/src/main/java/com/verisignlabs/dnssec/cl/SignZone.java +++ b/src/main/java/com/verisignlabs/dnssec/cl/SignZone.java @@ -79,6 +79,8 @@ public class SignZone extends CLBase { public long nsec3paramttl = -1; public boolean verboseSigning = false; + private static final Random rand = new Random(); + public CLIState() { super("jdnssec-signzone [..options..] zone_file [key_file ...]"); } @@ -198,9 +200,8 @@ public class SignZone extends CLBase { if ((optstr = cli.getOptionValue('R')) != null) { int length = parseInt(optstr, 0); if (length > 0 && length <= 255) { - Random random = new Random(); salt = new byte[length]; - random.nextBytes(salt); + rand.nextBytes(salt); } } @@ -241,8 +242,8 @@ public class SignZone extends CLBase { /** * Load a list of DNS names from a file. * - * @param nameListFile - * the path of a file containing a bare list of DNS names. + * @param nameListFile the path of a file containing a bare list of DNS + * names. * @return a list of {@link org.xbill.DNS.Name} objects. */ private static List getNameList(File nameListFile) throws IOException { @@ -254,9 +255,6 @@ public class SignZone extends CLBase { try { Name n = Name.fromString(line); // 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()) n = Name.concatenate(n, Name.root); @@ -274,14 +272,12 @@ public class SignZone extends CLBase { /** * Verify the generated signatures. * - * @param records - * a list of {@link org.xbill.DNS.Record}s. - * @param keypairs - * a list of keypairs used the sign the zone. + * @param records 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. */ private static boolean verifyZoneSigs(List records, - List keypairs) { + List keypairs, List kskpairs) { boolean secure = true; DnsSecVerifier verifier = new DnsSecVerifier(); @@ -289,7 +285,9 @@ public class SignZone extends CLBase { for (DnsKeyPair pair : keypairs) { verifier.addTrustedKey(pair); } - + for (DnsKeyPair pair : kskpairs) { + verifier.addTrustedKey(pair); + } verifier.setVerifyAllSigs(true); List rrsets = SignUtils.assembleIntoRRsets(records); @@ -303,6 +301,7 @@ public class SignZone extends CLBase { boolean result = verifier.verify(rrset); if (!result) { + System.err.println("Signatures did not verify for RRset: " + rrset); staticLog.fine("Signatures did not verify for RRset: " + rrset); secure = false; } @@ -314,17 +313,12 @@ public class SignZone extends CLBase { /** * Load the key pairs from the key files. * - * @param keyfiles - * a string array containing the base names or paths of the - * keys to - * be loaded. - * @param startIndex - * 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). + * @param keyfiles a string array containing the base names or paths of the + * keys to be loaded. + * @param startIndex 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. */ private static List getKeys(String[] keyfiles, int startIndex, @@ -418,19 +412,12 @@ public class SignZone extends CLBase { /** * Load keysets (which contain delegation point security info). * - * @param inDirectory - * the directory to look for the keyset files (may be null, - * in - * which - * case it defaults to looking in the current working - * 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. + * @param inDirectory the directory to look for the keyset files (may be null, + * in which case it defaults to looking in the current + * working 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 getKeysets(File inDirectory, Name zonename) throws IOException { @@ -463,13 +450,9 @@ public class SignZone extends CLBase { /** * Determine if the given keypairs can be used to sign the zone. * - * @param zonename - * the zone origin. - * @param keypairs - * a list of {@link DnsKeyPair} objects that will be used to - * sign - * the - * zone. + * @param zonename the zone origin. + * @param keypairs a list of {@link DnsKeyPair} objects that will be used to + * sign the zone. * @return true if the keypairs valid. */ private static boolean keyPairsValidForZone(Name zonename, List keypairs) { @@ -503,55 +486,71 @@ public class SignZone extends CLBase { return; } - // Load the key pairs. - + // Load the key pairs. Note that getKeys() always returns an ArrayList, + // which may be empty. List keypairs = getKeys(state.keyFiles, 0, state.keyDirectory); List kskpairs = getKeys(state.kskFiles, 0, state.keyDirectory); // If we didn't get any keys on the command line, look at the zone apex for // any public keys. - if (keypairs == null && kskpairs == null) { + if (keypairs.isEmpty()) { List dnskeys = ZoneUtils.findRRs(records, zonename, Type.DNSKEY); keypairs = getKeys(dnskeys, state.keyDirectory); } // If we *still* don't have any key pairs, look for keys the key directory // that match - if (keypairs == null && kskpairs == null) { + if (keypairs.isEmpty()) { keypairs = findZoneKeys(state.keyDirectory, zonename); } // If we don't have any KSKs, but we do have more than one zone // signing key (presumably), presume that the zone signing keys // are just not differentiated and try to figure out which keys - // are actually ksks by looking at the SEP flag. - if ((kskpairs == null || kskpairs.isEmpty()) && keypairs != null - && keypairs.size() > 1) { + // are actually KSKs by looking at the SEP flag. + if (kskpairs.isEmpty() && !keypairs.isEmpty()) { for (Iterator i = keypairs.iterator(); i.hasNext();) { DnsKeyPair pair = i.next(); DNSKEYRecord kr = pair.getDNSKEYRecord(); if ((kr.getFlags() & DNSKEYRecord.Flags.SEP_KEY) != 0) { - if (kskpairs == null) - kskpairs = new ArrayList<>(); kskpairs.add(pair); i.remove(); } } } - // If there are no ZSKs defined at this point (yet there are KSKs - // 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()) { + // If we have zero keypairs at all, we are stuck. + if (keypairs.isEmpty() && kskpairs.isEmpty()) { System.err.println("No zone signing keys could be determined."); state.usage(); 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. if (state.outputfile == null && !state.zonefile.equals("-")) { if (zonename.isAbsolute()) { @@ -571,12 +570,12 @@ public class SignZone extends CLBase { // We force the signing keys to be in the zone by just appending // them to the zone here. Currently JCEDnsSecSigner.signZone // removes duplicate records. - if (kskpairs != null) { + if (!kskpairs.isEmpty()) { for (DnsKeyPair pair : kskpairs) { records.add(pair.getDNSKEYRecord()); } } - if (keypairs != null) { + if (!keypairs.isEmpty()) { for (DnsKeyPair pair : keypairs) { records.add(pair.getDNSKEYRecord()); } @@ -608,15 +607,11 @@ public class SignZone extends CLBase { // write out the signed zone ZoneUtils.writeZoneFile(signedRecords, state.outputfile); + System.out.println("zone signing complete"); if (state.verifySigs) { - // FIXME: ugh. - if (kskpairs != null) { - keypairs.addAll(kskpairs); - } - log.fine("verifying generated signatures"); - boolean res = verifyZoneSigs(signedRecords, keypairs); + boolean res = verifyZoneSigs(signedRecords, keypairs, kskpairs); if (res) { System.out.println("Generated signatures verified"); @@ -624,7 +619,6 @@ public class SignZone extends CLBase { System.out.println("Generated signatures did not verify."); } } - } public static void main(String[] args) { diff --git a/src/main/java/com/verisignlabs/dnssec/cl/ZoneFormat.java b/src/main/java/com/verisignlabs/dnssec/cl/ZoneFormat.java index 96ff79e..7e8422c 100644 --- a/src/main/java/com/verisignlabs/dnssec/cl/ZoneFormat.java +++ b/src/main/java/com/verisignlabs/dnssec/cl/ZoneFormat.java @@ -100,7 +100,6 @@ public class ZoneFormat extends CLBase { private static void formatZone(List zone) { - for (Record r : zone) { System.out.println(r.toString()); } diff --git a/src/main/java/com/verisignlabs/dnssec/security/BINDKeyUtils.java b/src/main/java/com/verisignlabs/dnssec/security/BINDKeyUtils.java index 450f8d4..381a525 100644 --- a/src/main/java/com/verisignlabs/dnssec/security/BINDKeyUtils.java +++ b/src/main/java/com/verisignlabs/dnssec/security/BINDKeyUtils.java @@ -46,7 +46,8 @@ import org.xbill.DNS.utils.base64; */ public class BINDKeyUtils { - private BINDKeyUtils() { } + private BINDKeyUtils() { + } /** * Calculate the BIND9 key file base name (i.e., without the ".key" or @@ -60,18 +61,18 @@ public class BINDKeyUtils { /** Reads in the DNSKEYRecord from the public key file */ private static DNSKEYRecord loadPublicKeyFile(File publicKeyFile) throws IOException { - Master m = new Master(publicKeyFile.getAbsolutePath(), null, 600); + try (Master m = new Master(publicKeyFile.getAbsolutePath(), null, 600)) { + Record r; + DNSKEYRecord result = null; - Record r; - DNSKEYRecord result = null; - - while ((r = m.nextRecord()) != null) { - if (r.getType() == Type.DNSKEY) { - 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 */ @@ -106,17 +107,12 @@ public class BINDKeyUtils { * Given the information necessary to construct the path to a BIND9 generated * key pair, load the key pair. * - * @param signer - * the DNS name of the key. - * @param algorithm - * the DNSSEC algorithm of the key. - * @param keyid - * the DNSSEC key footprint. - * @param inDirectory - * the directory to look for the files (may be null). + * @param signer the DNS name of the key. + * @param algorithm 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. - * @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, File inDirectory) throws IOException { @@ -128,16 +124,12 @@ public class BINDKeyUtils { /** * Given a base path to a BIND9 key pair, load the key pair. * - * @param keyFileBasePath - * the base filename (or real filename for either the - * public or - * private key) of the key. - * @param inDirectory - * the directory to look in, if the keyFileBasePath is + * @param keyFileBasePath the base filename (or real filename for either the + * public or private key) of the key. + * @param inDirectory the directory to look in, if the keyFileBasePath is * relative. * @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) throws IOException { @@ -162,15 +154,12 @@ public class BINDKeyUtils { * Given a base path to a BIND9 key pair, load the public part (only) of the * 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. - * @param inDirectory - * the directory to look in if the path is relative (may - * be null). + * @param inDirectory the directory to look in if the path is relative + * (may be null). * @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) throws IOException { @@ -190,15 +179,11 @@ public class BINDKeyUtils { * "keyset-[signer]." where [signer] is the DNS owner name of the key. The * keyset may be signed, but doesn't have to be. * - * @param keysetFileName - * the name of the keyset file. - * @param inDirectory - * the directory to look in if the path is relative (may - * be null, - * defaults to the current working directory). + * @param keysetFileName the name of the keyset file. + * @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. - * @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) throws IOException { @@ -218,8 +203,8 @@ public class BINDKeyUtils { /** * Calculate the key file base for this key pair. * - * @param pair - * the {@link DnsKeyPair} to work from. It only needs a public key. + * @param pair the {@link DnsKeyPair} to work from. It only needs a public + * key. * @return the base name of the key files. */ public static String keyFileBase(DnsKeyPair pair) { @@ -259,8 +244,7 @@ public class BINDKeyUtils { * Given a the contents of a BIND9 private key file, convert it into a native * {@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} */ public static PrivateKey convertPrivateKeyString(String privateKeyString) { @@ -272,7 +256,7 @@ public class BINDKeyUtils { try { DnsKeyConverter conv = new DnsKeyConverter(); return conv.parsePrivateKeyString(privateKeyString); - } catch (IOException|NoSuchAlgorithmException e) { + } catch (IOException | NoSuchAlgorithmException e) { e.printStackTrace(); } @@ -283,10 +267,8 @@ public class BINDKeyUtils { * Given a native private key, convert it into a BIND9 private key file * format. * - * @param priv - * the private key to convert. - * @param pub - * the private key's corresponding public key. Some algorithms + * @param priv the private key to convert. + * @param pub the private key's corresponding public key. Some algorithms * require information from both. * @return a string containing the contents of a BIND9 private key file. */ @@ -327,16 +309,11 @@ public class BINDKeyUtils { /** * This routine will write out the BIND9 dnssec-* tool compatible files. * - * @param baseFileName - * use this base file name. If null, the standard BIND9 base - * file - * name will be computed. - * @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. + * @param baseFileName use this base file name. If null, the standard BIND9 + * base file name will be computed. + * @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, File inDirectory) throws IOException { @@ -369,10 +346,8 @@ public class BINDKeyUtils { * This routine will write out the BIND9 dnssec-* tool compatible files to the * standard file names. * - * @param pair - * the key pair in question. - * @param inDirectory - * the directory to write to (may be null). + * @param pair the key pair in question. + * @param inDirectory the directory to write to (may be null). */ public static void writeKeyFiles(DnsKeyPair pair, File inDirectory) throws IOException { diff --git a/src/main/java/com/verisignlabs/dnssec/security/ByteArrayComparator.java b/src/main/java/com/verisignlabs/dnssec/security/ByteArrayComparator.java index 84082f1..6230a3c 100644 --- a/src/main/java/com/verisignlabs/dnssec/security/ByteArrayComparator.java +++ b/src/main/java/com/verisignlabs/dnssec/security/ByteArrayComparator.java @@ -27,7 +27,7 @@ import java.util.logging.Logger; * @author David Blacka */ public class ByteArrayComparator implements Comparator { - private int mOffset = 0; + private int mOffset = 0; private boolean mDebug = false; private Logger log; diff --git a/src/main/java/com/verisignlabs/dnssec/security/DnsKeyAlgorithm.java b/src/main/java/com/verisignlabs/dnssec/security/DnsKeyAlgorithm.java index debecc2..07f9dc8 100644 --- a/src/main/java/com/verisignlabs/dnssec/security/DnsKeyAlgorithm.java +++ b/src/main/java/com/verisignlabs/dnssec/security/DnsKeyAlgorithm.java @@ -34,7 +34,6 @@ import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.Provider; -import java.security.SecureRandom; import java.security.Security; import java.security.Signature; import java.security.spec.ECFieldFp; @@ -43,6 +42,7 @@ import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.EllipticCurve; import java.security.spec.InvalidParameterSpecException; +import java.security.spec.NamedParameterSpec; import java.security.spec.RSAKeyGenParameterSpec; import java.util.Arrays; import java.util.HashMap; @@ -51,12 +51,6 @@ import java.util.logging.Logger; 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 * usable java implementations. @@ -72,21 +66,24 @@ public class DnsKeyAlgorithm { // Our base algorithm numbers. This is a normalization of the DNSSEC // algorithms (which are really signature algorithms). Thus RSASHA1, - // RSASHA256, etc. all boil down to 'RSA' here. - public static final int UNKNOWN = -1; - public static final int RSA = 1; - public static final int DH = 2; - public static final int DSA = 3; - public static final int ECC_GOST = 4; - public static final int ECDSA = 5; - public static final int EDDSA = 6; + // RSASHA256, etc. all boil down to 'RSA' here. Similarly, ECDSAP256SHA256 and + // ECDSAP384SHA384 both become 'ECDSA'. + public enum BaseAlgorithm { + UNKNOWN, + RSA, + DH, + DSA, + ECC_GOST, + ECDSA, + EDDSA; + } private static class AlgEntry { public int dnssecAlgorithm; public String sigName; - public int baseType; + public BaseAlgorithm baseType; - public AlgEntry(int algorithm, String sigName, int baseType) { + public AlgEntry(int algorithm, String sigName, BaseAlgorithm baseType) { this.dnssecAlgorithm = algorithm; this.sigName = sigName; this.baseType = baseType; @@ -96,18 +93,20 @@ public class DnsKeyAlgorithm { private static class ECAlgEntry extends AlgEntry { public ECParameterSpec ecSpec; - public ECAlgEntry(int algorithm, String sigName, int baseType, ECParameterSpec spec) { + public ECAlgEntry(int algorithm, String sigName, BaseAlgorithm baseType, ECParameterSpec spec) { super(algorithm, sigName, baseType); this.ecSpec = spec; } } private static class EdAlgEntry extends AlgEntry { - public EdDSAParameterSpec edSpec; + public String curveName; + public NamedParameterSpec paramSpec; - public EdAlgEntry(int algorithm, String sigName, int baseType, EdDSAParameterSpec spec) { + public EdAlgEntry(int algorithm, String sigName, BaseAlgorithm baseType, String curveName) { super(algorithm, sigName, baseType); - this.edSpec = spec; + this.curveName = curveName; + this.paramSpec = new NamedParameterSpec(curveName); } } @@ -143,24 +142,15 @@ public class DnsKeyAlgorithm { private static DnsKeyAlgorithm mInstance = null; public DnsKeyAlgorithm() { - // Attempt to add the bouncycastle provider. - // This is so we can use this provider if it is available, but not require - // the user to add it as one of the java.security providers. + // Attempt to add the bouncycastle provider. This is so we can use this + // provider if it is available, but not require the user to add it as one of + // the java.security providers. try { Class bcProviderClass = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider"); Provider bcProvider = (Provider) bcProviderClass.getDeclaredConstructor().newInstance(); Security.addProvider(bcProvider); } catch (ReflectiveOperationException e) { - 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"); + log.fine("Unable to load BC provider"); } initialize(); @@ -172,16 +162,16 @@ public class DnsKeyAlgorithm { mIdToMnemonicMap = new HashMap<>(); // Load the standard DNSSEC algorithms. - addAlgorithm(DNSSEC.Algorithm.RSAMD5, "MD5withRSA", RSA); + addAlgorithm(DNSSEC.Algorithm.RSAMD5, "MD5withRSA", BaseAlgorithm.RSA); addMnemonic("RSAMD5", DNSSEC.Algorithm.RSAMD5); - addAlgorithm(DNSSEC.Algorithm.DH, "", DH); + addAlgorithm(DNSSEC.Algorithm.DH, "", BaseAlgorithm.DH); addMnemonic("DH", DNSSEC.Algorithm.DH); - addAlgorithm(DNSSEC.Algorithm.DSA, "SHA1withDSA", DSA); + addAlgorithm(DNSSEC.Algorithm.DSA, "SHA1withDSA", BaseAlgorithm.DSA); addMnemonic("DSA", DNSSEC.Algorithm.DSA); - addAlgorithm(DNSSEC.Algorithm.RSASHA1, "SHA1withRSA", RSA); + addAlgorithm(DNSSEC.Algorithm.RSASHA1, "SHA1withRSA", BaseAlgorithm.RSA); addMnemonic("RSASHA1", DNSSEC.Algorithm.RSASHA1); addMnemonic("RSA", DNSSEC.Algorithm.RSASHA1); @@ -193,79 +183,114 @@ public class DnsKeyAlgorithm { addMnemonic("NSEC3RSASHA1", DNSSEC.Algorithm.RSA_NSEC3_SHA1); // Algorithms added by RFC 5702. - addAlgorithm(DNSSEC.Algorithm.RSASHA256, "SHA256withRSA", RSA); + addAlgorithm(DNSSEC.Algorithm.RSASHA256, "SHA256withRSA", BaseAlgorithm.RSA); addMnemonic("RSASHA256", DNSSEC.Algorithm.RSASHA256); - addAlgorithm(DNSSEC.Algorithm.RSASHA512, "SHA512withRSA", RSA); + addAlgorithm(DNSSEC.Algorithm.RSASHA512, "SHA512withRSA", BaseAlgorithm.RSA); addMnemonic("RSASHA512", DNSSEC.Algorithm.RSASHA512); // ECC-GOST is not supported by Java 1.8's Sun crypto provider. The // bouncycastle.org provider, however, does support it. // GostR3410-2001-CryptoPro-A is the named curve in the BC provider, but we // will get the parameters directly. - addAlgorithm(DNSSEC.Algorithm.ECC_GOST, "GOST3411withECGOST3410", ECC_GOST, null); + addAlgorithm(DNSSEC.Algorithm.ECC_GOST, "GOST3411withECGOST3410", BaseAlgorithm.ECC_GOST, null); addMnemonic("ECCGOST", DNSSEC.Algorithm.ECC_GOST); addMnemonic("ECC-GOST", DNSSEC.Algorithm.ECC_GOST); - addAlgorithm(DNSSEC.Algorithm.ECDSAP256SHA256, "SHA256withECDSA", ECDSA, "secp256r1"); + addAlgorithm(DNSSEC.Algorithm.ECDSAP256SHA256, "SHA256withECDSA", BaseAlgorithm.ECDSA, "secp256r1"); addMnemonic("ECDSAP256SHA256", DNSSEC.Algorithm.ECDSAP256SHA256); addMnemonic("ECDSA-P256", DNSSEC.Algorithm.ECDSAP256SHA256); - addAlgorithm(DNSSEC.Algorithm.ECDSAP384SHA384, "SHA384withECDSA", ECDSA, "secp384r1"); + addAlgorithm(DNSSEC.Algorithm.ECDSAP384SHA384, "SHA384withECDSA", BaseAlgorithm.ECDSA, "secp384r1"); addMnemonic("ECDSAP384SHA384", DNSSEC.Algorithm.ECDSAP384SHA384); addMnemonic("ECDSA-P384", DNSSEC.Algorithm.ECDSAP384SHA384); - // EdDSA is not supported by either the Java 1.8 Sun crypto - // provider or bouncycastle. It is added by the Ed25519-Java - // library. We don't have a corresponding constant in - // org.xbill.DNS.DNSSEC yet, though. - addAlgorithm(15, "NONEwithEdDSA", EDDSA, "Ed25519"); + // For the Edwards Curve implementations, we just initialize Signature and + // KeyPairGenerator with the curve name. + addAlgorithm(15, "Ed25519", BaseAlgorithm.EDDSA, "Ed25519"); addMnemonic("ED25519", 15); + addAlgorithm(16, "Ed448", BaseAlgorithm.EDDSA, "Ed448"); + addMnemonic(("ED448"), 16); } - private void addAlgorithm(int algorithm, String sigName, int baseType) { + private void addAlgorithm(int algorithm, String sigName, BaseAlgorithm baseType) { mAlgorithmMap.put(algorithm, new AlgEntry(algorithm, sigName, baseType)); } - private void addAlgorithm(int algorithm, String sigName, int baseType, String curveName) { - if (baseType == ECDSA) { - ECParameterSpec ecSpec = ECSpecFromAlgorithm(algorithm); - if (ecSpec == null) - ecSpec = ECSpecFromName(curveName); - if (ecSpec == null) - return; + /** + * Add a ECDSA (algorithms 13/14) to the set, looking up the curve names. + * + * @param algorithm the DNSSEC algorithm number. + * @param sigName the name of the signature scheme. + * @param curveName the official name of the elliptic curve in our crypto + * library (SunEC). + */ + 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. - 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; - } - 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); + // 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; } - + 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) { // Do not add mnemonics for algorithms that ended up not actually being // supported. @@ -276,19 +301,19 @@ public class DnsKeyAlgorithm { mIdToMnemonicMap.computeIfAbsent(alg, k -> m); } - public void addAlias(int alias, String mnemonic, int original_algorithm) { + public void addAlias(int alias, String mnemonic, int origAlgorithm) { if (mAlgorithmMap.containsKey(alias)) { log.warning("Unable to alias algorithm " + alias + " because it already exists."); return; } - if (!mAlgorithmMap.containsKey(original_algorithm)) { + if (!mAlgorithmMap.containsKey(origAlgorithm)) { log.warning("Unable to alias algorithm " + alias - + " to unknown algorithm identifier " + original_algorithm); + + " to unknown algorithm identifier " + origAlgorithm); return; } - mAlgorithmMap.put(alias, mAlgorithmMap.get(original_algorithm)); + mAlgorithmMap.put(alias, mAlgorithmMap.get(origAlgorithm)); if (mnemonic != null) { addMnemonic(mnemonic, alias); @@ -304,16 +329,16 @@ public class DnsKeyAlgorithm { // the ECC-GOST curve. private ECParameterSpec ECSpecFromAlgorithm(int algorithm) { if (algorithm == DNSSEC.Algorithm.ECC_GOST) { - // From RFC 4357 Section 11.4 - BigInteger p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97", 16); - BigInteger a = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94", 16); - BigInteger b = new BigInteger("A6", 16); - BigInteger gx = new BigInteger("1", 16); - BigInteger gy = new BigInteger("8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14", 16); - BigInteger n = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893", 16); + // From RFC 4357 Section 11.4 + BigInteger p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97", 16); + BigInteger a = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94", 16); + BigInteger b = new BigInteger("A6", 16); + BigInteger gx = new BigInteger("1", 16); + BigInteger gy = new BigInteger("8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14", 16); + BigInteger n = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893", 16); - EllipticCurve curve = new EllipticCurve(new ECFieldFp(p), a, b); - return new ECParameterSpec(curve, new ECPoint(gx, gy), n, 1); + EllipticCurve curve = new EllipticCurve(new ECFieldFp(p), a, b); + return new ECParameterSpec(curve, new ECPoint(gx, gy), n, 1); } return null; } @@ -322,8 +347,8 @@ public class DnsKeyAlgorithm { private ECParameterSpec ECSpecFromName(String stdName) { try { AlgorithmParameters ap = AlgorithmParameters.getInstance("EC"); - ECGenParameterSpec ecg_spec = new ECGenParameterSpec(stdName); - ap.init(ecg_spec); + ECGenParameterSpec ecgSpec = new ECGenParameterSpec(stdName); + ap.init(ecgSpec); return ap.getParameterSpec(ECParameterSpec.class); } catch (NoSuchAlgorithmException e) { log.info("Elliptic Curve not supported by any crypto provider: " + e.getMessage()); @@ -333,24 +358,6 @@ public class DnsKeyAlgorithm { 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() { Set keyset = mAlgorithmMap.keySet(); Integer[] algs = keyset.toArray(new Integer[keyset.size()]); @@ -388,11 +395,10 @@ public class DnsKeyAlgorithm { } /** - * Given one of the ECDSA algorithms (ECDSAP256SHA256, etc.) return - * the elliptic curve parameters. + * Given one of the ECDSA algorithms (ECDSAP256SHA256, etc.) return 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 * null if not a recognized/supported EC algorithm. */ @@ -402,37 +408,35 @@ public class DnsKeyAlgorithm { return null; if (!(entry instanceof ECAlgEntry)) return null; - ECAlgEntry ec_entry = (ECAlgEntry) entry; + ECAlgEntry ecEntry = (ECAlgEntry) entry; - return ec_entry.ecSpec; + return ecEntry.ecSpec; } /** - * Given one of the EdDSA algorithms (Ed25519, Ed448) return the - * elliptic curve parameters. + * Given one of the EdDSA algorithms (ED25519 or ED448), return the named + * parameter spec. * - * @param algorithm - * The DNSSEC algorithm number. - * @return The stored EdDSAParameterSpec for that algorithm, or - * null if not a recognized/supported EdDSA algorithm. + * @param algorithm The DNSSEC algorithm number. + * @return The NamedParameterSpec for that DNSSEC algorithm, nor null if the + * algorithm wasn't a supported EdDSA algorithm. */ - public EdDSAParameterSpec getEdwardsCurveParams(int algorithm) { + public NamedParameterSpec getEdwardsCurveSpec(int algorithm) { AlgEntry entry = getEntry(algorithm); if (entry == null) return null; if (!(entry instanceof EdAlgEntry)) return null; - EdAlgEntry ed_entry = (EdAlgEntry) entry; + EdAlgEntry edEntry = (EdAlgEntry) entry; - return ed_entry.edSpec; + return edEntry.paramSpec; } /** * Translate a possible algorithm alias back to the original DNSSEC algorithm * 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 * if it is. */ @@ -458,8 +462,7 @@ public class DnsKeyAlgorithm { * Given an algorithm mnemonic, convert the mnemonic to a DNSSEC algorithm * 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 * number if it is. */ @@ -473,8 +476,7 @@ public class DnsKeyAlgorithm { /** * 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 * recognized. */ @@ -482,15 +484,15 @@ public class DnsKeyAlgorithm { return mIdToMnemonicMap.get(algorithm); } - public int baseType(int algorithm) { + public BaseAlgorithm baseType(int algorithm) { AlgEntry entry = getEntry(algorithm); if (entry != null) return entry.baseType; - return UNKNOWN; + return BaseAlgorithm.UNKNOWN; } public boolean isDSA(int algorithm) { - return (baseType(algorithm) == DSA); + return (baseType(algorithm) == BaseAlgorithm.DSA); } public KeyPair generateKeyPair(int algorithm, int keysize, boolean useLargeExp) @@ -502,14 +504,14 @@ public class DnsKeyAlgorithm { mRSAKeyGenerator = KeyPairGenerator.getInstance("RSA"); } - RSAKeyGenParameterSpec rsa_spec; + RSAKeyGenParameterSpec rsaSpec; if (useLargeExp) { - rsa_spec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F4); + rsaSpec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F4); } else { - rsa_spec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F0); + rsaSpec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F0); } try { - mRSAKeyGenerator.initialize(rsa_spec); + mRSAKeyGenerator.initialize(rsaSpec); } catch (InvalidAlgorithmParameterException e) { // Fold the InvalidAlgorithmParameterException into our existing // thrown exception. Ugly, but requires less code change. @@ -560,18 +562,9 @@ public class DnsKeyAlgorithm { break; } case EDDSA: { - if (mEdKeyGenerator == null) { - mEdKeyGenerator = KeyPairGenerator.getInstance("EdDSA"); - } + EdAlgEntry entry = (EdAlgEntry) getEntry(algorithm); + mEdKeyGenerator = KeyPairGenerator.getInstance(entry.curveName); - 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(); break; } diff --git a/src/main/java/com/verisignlabs/dnssec/security/DnsKeyConverter.java b/src/main/java/com/verisignlabs/dnssec/security/DnsKeyConverter.java index bf65af2..e4eccd1 100644 --- a/src/main/java/com/verisignlabs/dnssec/security/DnsKeyConverter.java +++ b/src/main/java/com/verisignlabs/dnssec/security/DnsKeyConverter.java @@ -30,12 +30,16 @@ import java.security.interfaces.DSAPrivateKey; import java.security.interfaces.DSAPublicKey; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; +import java.security.interfaces.EdECPrivateKey; +import java.security.interfaces.EdECPublicKey; import java.security.interfaces.RSAPrivateCrtKey; import java.security.spec.DSAPrivateKeySpec; import java.security.spec.ECParameterSpec; import java.security.spec.ECPrivateKeySpec; +import java.security.spec.EdECPrivateKeySpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; +import java.security.spec.NamedParameterSpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.RSAPrivateCrtKeySpec; import java.util.StringTokenizer; @@ -50,13 +54,6 @@ import org.xbill.DNS.DNSSEC.DNSSECException; import org.xbill.DNS.Name; 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 * key formats. @@ -87,7 +84,6 @@ public class DnsKeyConverter { // Because we have arbitrarily aliased algorithms, we need to possibly // translate the aliased algorithm back to the actual algorithm. - int originalAlgorithm = mAlgorithms.originalAlgorithm(pKeyRecord.getAlgorithm()); if (originalAlgorithm <= 0) @@ -101,16 +97,6 @@ public class DnsKeyConverter { 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 { // This uses DNSJava's DNSSEC.toPublicKey() method. return pKeyRecord.getPublicKey(); @@ -119,30 +105,12 @@ 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. */ public DNSKEYRecord generateDNSKEYRecord(Name name, int dclass, long ttl, int flags, int alg, PublicKey key) { 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, key); } catch (DNSSECException e) { @@ -152,13 +120,6 @@ 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 /** @@ -168,9 +129,9 @@ public class DnsKeyConverter { PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(key); try { switch (mAlgorithms.baseType(algorithm)) { - case DnsKeyAlgorithm.RSA: + case RSA: return mRSAKeyFactory.generatePrivate(spec); - case DnsKeyAlgorithm.DSA: + case DSA: return mDSAKeyFactory.generatePrivate(spec); default: return null; @@ -225,17 +186,17 @@ public class DnsKeyConverter { int alg = parseInt(val, -1); switch (mAlgorithms.baseType(alg)) { - case DnsKeyAlgorithm.RSA: + case RSA: return parsePrivateRSA(lines); - case DnsKeyAlgorithm.DSA: + case DSA: return parsePrivateDSA(lines); - case DnsKeyAlgorithm.DH: + case DH: return parsePrivateDH(lines); - case DnsKeyAlgorithm.ECC_GOST: + case ECC_GOST: return parsePrivateECDSA(lines, alg); - case DnsKeyAlgorithm.ECDSA: + case ECDSA: return parsePrivateECDSA(lines, alg); - case DnsKeyAlgorithm.EDDSA: + case EDDSA: return parsePrivateEdDSA(lines, alg); default: throw new IOException("unsupported private key algorithm: " + val); @@ -272,12 +233,12 @@ public class DnsKeyConverter { private PrivateKey parsePrivateRSA(StringTokenizer lines) throws NoSuchAlgorithmException { BigInteger modulus = null; - BigInteger public_exponent = null; - BigInteger private_exponent = null; - BigInteger prime_p = null; - BigInteger prime_q = null; - BigInteger prime_p_exponent = null; - BigInteger prime_q_exponent = null; + BigInteger publicExponent = null; + BigInteger privateExponent = null; + BigInteger primeP = null; + BigInteger primeQ = null; + BigInteger primePExponent = null; + BigInteger primeQExponent = null; BigInteger coefficient = null; while (lines.hasMoreTokens()) { @@ -296,33 +257,28 @@ public class DnsKeyConverter { if (line.startsWith("Modulus: ")) { modulus = new BigInteger(1, data); - // printBigIntCompare(data, modulus); } else if (line.startsWith("PublicExponent: ")) { - public_exponent = new BigInteger(1, data); - // printBigIntCompare(data, public_exponent); + publicExponent = new BigInteger(1, data); } else if (line.startsWith("PrivateExponent: ")) { - private_exponent = new BigInteger(1, data); - // printBigIntCompare(data, private_exponent); + privateExponent = new BigInteger(1, data); } else if (line.startsWith("Prime1: ")) { - prime_p = new BigInteger(1, data); - // printBigIntCompare(data, prime_p); + primeP = new BigInteger(1, data); } else if (line.startsWith("Prime2: ")) { - prime_q = new BigInteger(1, data); - // printBigIntCompare(data, prime_q); + primeQ = new BigInteger(1, data); } else if (line.startsWith("Exponent1: ")) { - prime_p_exponent = new BigInteger(1, data); + primePExponent = new BigInteger(1, data); } else if (line.startsWith("Exponent2: ")) { - prime_q_exponent = new BigInteger(1, data); + primeQExponent = new BigInteger(1, data); } else if (line.startsWith("Coefficient: ")) { coefficient = new BigInteger(1, data); } } try { - KeySpec spec = new RSAPrivateCrtKeySpec(modulus, public_exponent, - private_exponent, prime_p, - prime_q, prime_p_exponent, - prime_q_exponent, coefficient); + KeySpec spec = new RSAPrivateCrtKeySpec(modulus, publicExponent, + privateExponent, primeP, + primeQ, primePExponent, + primeQExponent, coefficient); if (mRSAKeyFactory == null) { mRSAKeyFactory = KeyFactory.getInstance("RSA"); } @@ -466,13 +422,13 @@ public class DnsKeyConverter { if (mECKeyFactory == null) { mECKeyFactory = KeyFactory.getInstance("EC"); } - ECParameterSpec ec_spec = mAlgorithms.getEllipticCurveParams(algorithm); - if (ec_spec == null) { + ECParameterSpec ecSpec = mAlgorithms.getEllipticCurveParams(algorithm); + if (ecSpec == null) { throw new NoSuchAlgorithmException("DNSSEC algorithm " + algorithm + " is not a recognized Elliptic Curve algorithm"); } - KeySpec spec = new ECPrivateKeySpec(s, ec_spec); + KeySpec spec = new ECPrivateKeySpec(s, ecSpec); try { return mECKeyFactory.generatePrivate(spec); @@ -516,13 +472,13 @@ public class DnsKeyConverter { if (mEdKeyFactory == null) { mEdKeyFactory = KeyFactory.getInstance("EdDSA"); } - EdDSAParameterSpec ed_spec = mAlgorithms.getEdwardsCurveParams(algorithm); - if (ed_spec == null) { + NamedParameterSpec namedSpec = mAlgorithms.getEdwardsCurveSpec(algorithm); + if (namedSpec == null) { throw new NoSuchAlgorithmException("DNSSEC algorithm " + algorithm + " is not a recognized Edwards Curve algorithm"); } - KeySpec spec = new EdDSAPrivateKeySpec(seed, ed_spec); + EdECPrivateKeySpec spec = new EdECPrivateKeySpec(namedSpec, seed); try { return mEdKeyFactory.generatePrivate(spec); @@ -545,8 +501,8 @@ public class DnsKeyConverter { return generatePrivateDH((DHPrivateKey) priv, (DHPublicKey) pub, alg); } else if (priv instanceof ECPrivateKey && pub instanceof ECPublicKey) { return generatePrivateEC((ECPrivateKey) priv, (ECPublicKey) pub, alg); - } else if (priv instanceof EdDSAPrivateKey && pub instanceof EdDSAPublicKey) { - return generatePrivateED((EdDSAPrivateKey) priv, (EdDSAPublicKey) pub, alg); + } else if (priv instanceof EdECPrivateKey && pub instanceof EdECPublicKey) { + return generatePrivateED((EdECPrivateKey) priv, (EdECPublicKey) pub, alg); } return null; @@ -556,16 +512,16 @@ public class DnsKeyConverter { * Convert from 'unsigned' big integer to original 'signed format' in Base64 */ private static String b64BigInt(BigInteger i) { - byte[] orig_bytes = i.toByteArray(); + byte[] origBytes = i.toByteArray(); - if (orig_bytes[0] != 0 || orig_bytes.length == 1) { - return base64.toString(orig_bytes); + if (origBytes[0] != 0 || origBytes.length == 1) { + return base64.toString(origBytes); } - byte[] signed_bytes = new byte[orig_bytes.length - 1]; - System.arraycopy(orig_bytes, 1, signed_bytes, 0, signed_bytes.length); + byte[] signedBytes = new byte[origBytes.length - 1]; + System.arraycopy(origBytes, 1, signedBytes, 0, signedBytes.length); - return base64.toString(signed_bytes); + return base64.toString(signedBytes); } /** @@ -668,7 +624,7 @@ public class DnsKeyConverter { * Given an edwards curve key pair, and the actual algorithm (which will * describe the curve used), return the BIND9-style text encoding. */ - private String generatePrivateED(EdDSAPrivateKey priv, EdDSAPublicKey pub, int alg) { + private String generatePrivateED(EdECPrivateKey priv, EdECPublicKey pub, int alg) { StringWriter sw = new StringWriter(); PrintWriter out = new PrintWriter(sw); @@ -676,7 +632,8 @@ public class DnsKeyConverter { out.println("Algorithm: " + alg + " (" + mAlgorithms.algToString(alg) + ")"); out.print("PrivateKey: "); - out.println(base64.toString(priv.getSeed())); + byte[] keyBytes = priv.getBytes().orElse("null".getBytes()); + out.println(base64.toString(keyBytes)); return sw.toString(); } diff --git a/src/main/java/com/verisignlabs/dnssec/security/DnsKeyPair.java b/src/main/java/com/verisignlabs/dnssec/security/DnsKeyPair.java index eb3da10..e427da4 100644 --- a/src/main/java/com/verisignlabs/dnssec/security/DnsKeyPair.java +++ b/src/main/java/com/verisignlabs/dnssec/security/DnsKeyPair.java @@ -264,18 +264,22 @@ public class DnsKeyPair { * @throws NoSuchAlgorithmException */ public Signature getVerifier() { - if (mVerifier == null) { - mVerifier = getSignature(); - PublicKey pk = getPublic(); - if (mVerifier != null && pk != null) { - try { - mVerifier.initVerify(pk); - } catch (InvalidKeyException e) { - } - } else { - // do not return an uninitialized verifier - return null; - } + if (mVerifier != null) + return mVerifier; + + mVerifier = getSignature(); + PublicKey pk = getPublic(); + + if (mVerifier == null || pk == null) { + log.warning("Could not get a Signature object for this key pair" + this); + return null; + } + + try { + mVerifier.initVerify(pk); + } catch (InvalidKeyException e) { + log.warning("Key pair cannot initialize with public key: " + this); + return null; } return mVerifier; @@ -327,15 +331,16 @@ public class DnsKeyPair { 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 private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII); + public static String toHex(byte[] bytes) { byte[] hexChars = new byte[bytes.length * 2]; for (int j = 0; j < bytes.length; j++) { - int v = bytes[j] & 0xFF; - hexChars[j * 2] = HEX_ARRAY[v >>> 4]; - hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; + int v = bytes[j] & 0xFF; + hexChars[j * 2] = HEX_ARRAY[v >>> 4]; + hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; } return new String(hexChars, StandardCharsets.UTF_8); } diff --git a/src/main/java/com/verisignlabs/dnssec/security/DnsSecVerifier.java b/src/main/java/com/verisignlabs/dnssec/security/DnsSecVerifier.java index dca81b3..de77695 100644 --- a/src/main/java/com/verisignlabs/dnssec/security/DnsSecVerifier.java +++ b/src/main/java/com/verisignlabs/dnssec/security/DnsSecVerifier.java @@ -238,13 +238,13 @@ public class DnsSecVerifier { for (DnsKeyPair keypair : keypairs) { Signature signer = keypair.getVerifier(); signer.update(data); - + byte[] sig = sigrec.getSignature(); - - if (algs.baseType(sigrec.getAlgorithm()) == DnsKeyAlgorithm.DSA) { + + if (algs.baseType(sigrec.getAlgorithm()) == DnsKeyAlgorithm.BaseAlgorithm.DSA) { sig = SignUtils.convertDSASignature(sig); } - + if (sigrec.getAlgorithm() == DNSSEC.Algorithm.ECDSAP256SHA256 || sigrec.getAlgorithm() == DNSSEC.Algorithm.ECDSAP384SHA384) { sig = SignUtils.convertECDSASignature(sig); diff --git a/src/main/java/com/verisignlabs/dnssec/security/JCEDnsSecSigner.java b/src/main/java/com/verisignlabs/dnssec/security/JCEDnsSecSigner.java index 34b36b8..223b278 100644 --- a/src/main/java/com/verisignlabs/dnssec/security/JCEDnsSecSigner.java +++ b/src/main/java/com/verisignlabs/dnssec/security/JCEDnsSecSigner.java @@ -68,21 +68,14 @@ public class JCEDnsSecSigner { /** * Cryptographically generate a new DNSSEC key. * - * @param owner - * the KEY RR's owner name. - * @param ttl - * the KEY RR's TTL. - * @param dclass - * the KEY RR's DNS class. - * @param algorithm - * the DNSSEC algorithm (RSASHA258, RSASHA512, + * @param owner the KEY RR's owner name. + * @param ttl the KEY RR's TTL. + * @param dclass the KEY RR's DNS class. + * @param algorithm the DNSSEC algorithm (RSASHA258, RSASHA512, * 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. + * @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. */ public DnsKeyPair generateKey(Name owner, long ttl, int dclass, int algorithm, @@ -113,29 +106,25 @@ public class JCEDnsSecSigner { /** * Sign an RRset. * - * @param rrset - * the RRset to sign -- any existing signatures are ignored. - * @param keypars - * 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. + * @param rrset the RRset to sign -- any existing signatures are ignored. + * @param keypars 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. */ public List signRRset(RRset rrset, List keypairs, Instant start, Instant expire) throws IOException, GeneralSecurityException { if (rrset == null || keypairs == null) - return null; + return new ArrayList<>(); // default start to now, expire to start + 1 second. if (start == null) start = Instant.now(); if (expire == null) expire = start.plusSeconds(1); - if (keypairs.size() == 0) - return null; + if (keypairs.isEmpty()) + return new ArrayList<>(); if (mVerboseSigning) { log.info("Signing RRset:"); @@ -143,9 +132,9 @@ public class JCEDnsSecSigner { } // first, pre-calculate the RRset bytes. - byte[] rrset_data = SignUtils.generateCanonicalRRsetData(rrset, 0, 0); + byte[] rrsetData = SignUtils.generateCanonicalRRsetData(rrset, 0, 0); - ArrayList sigs = new ArrayList(keypairs.size()); + ArrayList sigs = new ArrayList<>(keypairs.size()); // for each keypair, sign the RRset. for (DnsKeyPair pair : keypairs) { @@ -155,13 +144,13 @@ public class JCEDnsSecSigner { RRSIGRecord presig = SignUtils.generatePreRRSIG(rrset, keyrec, start, expire, rrset.getTTL()); - byte[] sign_data = SignUtils.generateSigData(rrset_data, presig); + byte[] signData = SignUtils.generateSigData(rrsetData, presig); if (mVerboseSigning) { log.info("Canonical pre-signature data to sign with key " + keyrec.getName().toString() + "/" + keyrec.getAlgorithm() + "/" + keyrec.getFootprint() + ":"); - log.info(hexdump.dump(null, sign_data)); + log.info(hexdump.dump(null, signData)); } Signature signer = pair.getSigner(); @@ -174,7 +163,7 @@ public class JCEDnsSecSigner { } // sign the data. - signer.update(sign_data); + signer.update(signData); byte[] sig = signer.sign(); if (mVerboseSigning) { @@ -184,7 +173,7 @@ public class JCEDnsSecSigner { DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance(); // Convert to RFC 2536 format, if necessary. - if (algs.baseType(pair.getDNSKEYAlgorithm()) == DnsKeyAlgorithm.DSA) { + if (algs.baseType(pair.getDNSKEYAlgorithm()) == DnsKeyAlgorithm.BaseAlgorithm.DSA) { DSAPublicKey pk = (DSAPublicKey) pair.getPublic(); sig = SignUtils.convertDSASignature(pk.getParams(), sig); } @@ -206,12 +195,9 @@ public class JCEDnsSecSigner { /** * Create a completely self-signed DNSKEY RRset. * - * @param keypairs - * the public & private keypairs to use in the keyset. - * @param start - * the RRSIG inception time. - * @param expire - * the RRSIG expiration time. + * @param keypairs the public & private keypairs to use in the keyset. + * @param start the RRSIG inception time. + * @param expire the RRSIG expiration time. * @return a signed RRset. */ public RRset makeKeySet(List keypairs, Instant start, Instant expire) @@ -236,67 +222,55 @@ public class JCEDnsSecSigner { /** * Conditionally sign an RRset and add it to the toList. * - * @param toList - * the list to which we are adding the processed RRsets. - * @param zonename - * the zone apex name. - * @param rrset - * the RRset under consideration. - * @param kskpairs - * the List of KSKs.. - * @param zskpairs - * 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. + * @param toList the list to which we are adding the processed RRsets. + * @param zonename the zone apex name. + * @param rrset the RRset under consideration. + * @param kskpairs the List of KSKs.. + * @param zskpairs 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 lastCut the name of the last delegation point encountered. * * @return the name of the new last_cut. */ private Name addRRset(List toList, Name zonename, RRset rrset, List kskpairs, List zskpairs, Instant start, - Instant expire, boolean fullySignKeyset, Name last_cut, - Name last_dname) throws IOException, GeneralSecurityException { + Instant expire, boolean fullySignKeyset, Name lastCut, + Name lastDname) throws IOException, GeneralSecurityException { // add the records themselves - rrset.rrs().forEach(record -> { - toList.add(record); - }); + rrset.rrs().forEach(toList::add); int type = SignUtils.recordSecType(zonename, rrset.getName(), rrset.getType(), - last_cut, last_dname); + lastCut, lastDname); // we don't sign non-normal sets (delegations, glue, invalid). if (type == SignUtils.RR_DELEGATION) { return rrset.getName(); } if (type == SignUtils.RR_GLUE || type == SignUtils.RR_INVALID) { - return last_cut; + return lastCut; } // check for the zone apex keyset. - if (rrset.getName().equals(zonename) && rrset.getType() == Type.DNSKEY) { + if (rrset.getName().equals(zonename) && rrset.getType() == Type.DNSKEY && kskpairs != null && !kskpairs.isEmpty()) { // if we have ksks, sign the keyset with them, otherwise we will just sign // them with the zsks. - if (kskpairs != null && kskpairs.size() > 0) { - List sigs = signRRset(rrset, kskpairs, start, expire); - toList.addAll(sigs); + List 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. List sigs = signRRset(rrset, zskpairs, start, expire); toList.addAll(sigs); - return last_cut; + return lastCut; } // Various NSEC/NSEC3 generation modes @@ -311,49 +285,31 @@ public class JCEDnsSecSigner { * Opt-Out, etc.) External users of this class are expected to use the * appropriate public signZone* methods instead of this. * - * @param zonename - * The name of the zone - * @param records - * The records comprising the zone. They do not have to - * be in any - * particular order, as this method will order them as - * necessary. - * @param kskpairs - * The key pairs designated as "key signing keys" - * @param zskpairs - * 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 + * @param zonename The name of the zone + * @param records The records comprising the zone. They do not have to + * be in any particular order, as this method will + * order them as necessary. + * @param kskpairs The key pairs designated as "key signing keys" + * @param zskpairs 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 dsDigestAlg The hash algorithm to use for generating DS records * (DSRecord.SHA1_DIGEST_ID, e.g.) - * @param mode - * The NSEC/NSEC3 generation mode: NSEC_MODE, NSEC3_MODE, - * NSEC3_OPTOUT_MODE, etc. - * @param includedNames - * When using an Opt-In/Opt-Out mode, the names listed - * here will be - * 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 + * @param mode The NSEC/NSEC3 generation mode: NSEC_MODE, + * NSEC3_MODE, NSEC3_OPTOUT_MODE, etc. + * @param includedNames When using an Opt-In/Opt-Out mode, the names listed + * here will be 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 - * @param beConservative - * If true, then only turn on the Opt-In flag when there - * are insecure - * delegations in the span. Currently this only works for - * NSEC_EXP_OPT_IN mode. - * @param nsec3paramttl - * The TTL to use for the generated NSEC3PARAM record. - * Negative - * values will use the SOA TTL. + * @param beConservative If true, then only turn on the Opt-In flag when + * there are insecure delegations in the span. + * Currently this only works for 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, * representing the signed zone. * @@ -363,7 +319,7 @@ public class JCEDnsSecSigner { private List signZone(Name zonename, List records, List kskpairs, List zskpairs, Instant start, Instant expire, boolean fullySignKeyset, - int ds_digest_alg, int mode, List includedNames, + int dsDigestAlg, int mode, List includedNames, byte[] salt, int iterations, long nsec3paramttl, boolean beConservative) throws IOException, GeneralSecurityException { @@ -380,7 +336,7 @@ public class JCEDnsSecSigner { // Generate DS records. This replaces any non-zone-apex DNSKEY RRs with DS // RRs. - SignUtils.generateDSRecords(zonename, records, ds_digest_alg); + SignUtils.generateDSRecords(zonename, records, dsDigestAlg); // Generate the NSEC or NSEC3 records based on 'mode' switch (mode) { @@ -398,6 +354,8 @@ public class JCEDnsSecSigner { SignUtils.generateOptInNSECRecords(zonename, records, includedNames, beConservative); break; + default: + throw new NoSuchAlgorithmException("Unknown NSEC/NSEC3 mode: " + mode); } // Re-sort so we can assemble into rrsets. @@ -405,9 +363,9 @@ public class JCEDnsSecSigner { // Assemble into RRsets and sign. RRset rrset = new RRset(); - ArrayList signed_records = new ArrayList(); - Name last_cut = null; - Name last_dname = null; + ArrayList signedRecords = new ArrayList<>(); + Name lastCut = null; + Name lastDname = null; for (ListIterator i = records.listIterator(); i.hasNext();) { Record r = i.next(); @@ -430,48 +388,38 @@ public class JCEDnsSecSigner { // add the RRset to the list of signed_records, regardless of // whether or not we actually end up signing the set. - last_cut = addRRset(signed_records, zonename, rrset, kskpairs, zskpairs, start, - expire, fullySignKeyset, last_cut, last_dname); + lastCut = addRRset(signedRecords, zonename, rrset, kskpairs, zskpairs, start, + expire, fullySignKeyset, lastCut, lastDname); if (rrset.getType() == Type.DNAME) - last_dname = rrset.getName(); + lastDname = rrset.getName(); rrset.clear(); rrset.addRR(r); } // add the last RR set - addRRset(signed_records, zonename, rrset, kskpairs, zskpairs, start, expire, - fullySignKeyset, last_cut, last_dname); + addRRset(signedRecords, zonename, rrset, kskpairs, zskpairs, start, expire, + fullySignKeyset, lastCut, lastDname); - return signed_records; + return signedRecords; } /** * Given a zone, sign it using standard NSEC records. * - * @param zonename - * The name of the zone. - * @param records - * The records comprising the zone. They do not have to - * be in any - * particular order, as this method will order them as - * necessary. - * @param kskpairs - * The key pairs that are designated as "key signing + * @param zonename The name of the zone. + * @param records The records comprising the zone. They do not have to + * be in any particular order, as this method will + * order them as necessary. + * @param kskpairs The key pairs that are designated as "key signing * keys". - * @param zskpairs - * This key pairs that are designated as "zone signing + * @param zskpairs This key pairs that are designated as "zone signing * keys". - * @param start - * The RRSIG inception time. - * @param expire - * The RRSIG expiration time. - * @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 + * @param start The RRSIG inception time. + * @param expire The RRSIG expiration time. + * @param fullySignKeyset Sign the zone apex keyset with all available keys + * (instead of just the key signing keys). + * @param dsDigestAlg The digest algorithm to use when generating DS * records. * * @return an ordered list of {@link org.xbill.DNS.Record} objects, @@ -480,58 +428,42 @@ public class JCEDnsSecSigner { public List signZone(Name zonename, List records, List kskpairs, List zskpairs, Instant start, Instant expire, boolean fullySignKeyset, - int ds_digest_alg) throws IOException, + int dsDigestAlg) throws IOException, GeneralSecurityException { return signZone(zonename, records, kskpairs, zskpairs, start, expire, - fullySignKeyset, ds_digest_alg, NSEC_MODE, null, null, 0, 0, false); + fullySignKeyset, dsDigestAlg, NSEC_MODE, null, null, 0, 0, false); } /** * Given a zone, sign it using NSEC3 records. * - * @param signer - * A signer (utility) object used to actually sign stuff. - * @param zonename - * The name of the zone being signed. - * @param records - * The records comprising the zone. They do not have to - * be in any - * particular order, as this method will order them as - * necessary. - * @param kskpairs - * The key pairs that are designated as "key signing + * @param signer A signer (utility) object used to actually sign + * stuff. + * @param zonename The name of the zone being signed. + * @param records The records comprising the zone. They do not have to + * be in any particular order, as this method will + * order them as necessary. + * @param kskpairs The key pairs that are designated as "key signing * keys". - * @param zskpairs - * This key pairs that are designated as "zone signing + * @param zskpairs This key pairs that are designated as "zone signing * keys". - * @param start - * The RRSIG inception time. - * @param expire - * The RRSIG expiration time. - * @param fullySignKeyset - * If true then the DNSKEY RRset will be signed by all - * available - * keys, if false, only the key signing keys. - * @param useOptOut - * If true, insecure delegations will be omitted from the - * NSEC3 - * chain, and all NSEC3 records will have the Opt-Out - * flag set. - * @param includedNames - * A list of names to include in the NSEC3 chain + * @param start The RRSIG inception time. + * @param expire The RRSIG expiration time. + * @param fullySignKeyset If true then the DNSKEY RRset will be signed by all + * available keys, if false, only the key signing keys. + * @param useOptOut If true, insecure delegations will be omitted from + * the NSEC3 chain, and all NSEC3 records will have the + * Opt-Out flag set. + * @param includedNames A list of names to include in the NSEC3 chain * regardless. - * @param salt - * The salt to use for the NSEC3 hashing. null means no + * @param salt The salt to use for the NSEC3 hashing. null means no * salt. - * @param iterations - * The number of iterations to use for the NSEC3 hashing. - * @param ds_digest_alg - * The digest algorithm to use when generating DS + * @param iterations The number of iterations to use for the NSEC3 + * hashing. + * @param dsDigestAlg The digest algorithm to use when generating DS * records. - * @param nsec3paramttl - * The TTL to use for the generated NSEC3PARAM record. - * Negative - * values will use the SOA TTL. + * @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, * representing the signed zone. * @@ -542,16 +474,16 @@ public class JCEDnsSecSigner { List kskpairs, List zskpairs, Instant start, Instant expire, boolean fullySignKeyset, boolean useOptOut, List includedNames, - byte[] salt, int iterations, int ds_digest_alg, + byte[] salt, int iterations, int dsDigestAlg, long nsec3paramttl) throws IOException, GeneralSecurityException { if (useOptOut) { return signZone(zonename, records, kskpairs, zskpairs, start, expire, - fullySignKeyset, ds_digest_alg, NSEC3_OPTOUT_MODE, includedNames, + fullySignKeyset, dsDigestAlg, NSEC3_OPTOUT_MODE, includedNames, salt, iterations, nsec3paramttl, false); } else { return signZone(zonename, records, kskpairs, zskpairs, start, expire, - fullySignKeyset, ds_digest_alg, NSEC3_MODE, null, salt, iterations, + fullySignKeyset, dsDigestAlg, NSEC3_MODE, null, salt, iterations, nsec3paramttl, false); } } @@ -560,37 +492,25 @@ public class JCEDnsSecSigner { * Given a zone, sign it using experimental Opt-In NSEC records (see RFC * 4956). * - * @param zonename - * the name of the zone. - * @param records - * the records comprising the zone. They do not have - * to be in any - * particular order, as this method will order them - * as necessary. - * @param kskpairs - * the key pairs that are designated as "key signing - * keys". - * @param zskpairs - * this key pairs that are designated as "zone + * @param zonename the name of the zone. + * @param records the records comprising the zone. They do not + * have to be in any particular order, as this + * method will order them as necessary. + * @param kskpairs the key pairs that are designated as "key * signing keys". - * @param start - * the RRSIG inception time. - * @param expire - * the RRSIG expiration time. - * @param useConservativeOptIn - * if true, Opt-In NSEC records will only be - * generated if there are - * insecure, unsigned delegations in the span. - * @param fullySignKeyset - * sign the zone apex keyset with all available + * @param zskpairs this key pairs that are designated as "zone + * signing keys". + * @param start the RRSIG inception time. + * @param expire the RRSIG expiration time. + * @param useConservativeOptIn if true, Opt-In NSEC records will only be + * generated if there are insecure, unsigned + * delegations in the span. + * @param fullySignKeyset sign the zone apex keyset with all available * keys. - * @param ds_digest_alg - * The digest algorithm to use when generating DS + * @param dsDigestAlg The digest algorithm to use when generating DS * records. - * @param NSECIncludeNames - * names that are to be included in the NSEC chain - * regardless. This - * may be null. + * @param nsecIncludeNames 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, * representing the signed zone. */ @@ -598,12 +518,12 @@ public class JCEDnsSecSigner { List kskpairs, List zskpairs, Instant start, Instant expire, boolean useConservativeOptIn, - boolean fullySignKeyset, List NSECIncludeNames, - int ds_digest_alg) throws IOException, + boolean fullySignKeyset, List nsecIncludeNames, + int dsDigestAlg) throws IOException, GeneralSecurityException { return signZone(zonename, records, kskpairs, zskpairs, start, expire, - fullySignKeyset, ds_digest_alg, NSEC_EXP_OPT_IN, NSECIncludeNames, + fullySignKeyset, dsDigestAlg, NSEC_EXP_OPT_IN, nsecIncludeNames, null, 0, 0, useConservativeOptIn); } } diff --git a/src/main/java/com/verisignlabs/dnssec/security/RecordComparator.java b/src/main/java/com/verisignlabs/dnssec/security/RecordComparator.java index 9f6b312..cba43b5 100644 --- a/src/main/java/com/verisignlabs/dnssec/security/RecordComparator.java +++ b/src/main/java/com/verisignlabs/dnssec/security/RecordComparator.java @@ -33,6 +33,7 @@ import org.xbill.DNS.Type; public class RecordComparator implements Comparator { public RecordComparator() { + // nothing to initialize } /** @@ -65,15 +66,15 @@ public class RecordComparator implements Comparator { } private int compareRDATA(Record a, Record b) { - byte[] a_rdata = a.rdataToWireCanonical(); - byte[] b_rdata = b.rdataToWireCanonical(); + byte[] aRdata = a.rdataToWireCanonical(); + byte[] bRdata = b.rdataToWireCanonical(); - for (int i = 0; i < a_rdata.length && i < b_rdata.length; i++) { - int n = (a_rdata[i] & 0xFF) - (b_rdata[i] & 0xFF); + for (int i = 0; i < aRdata.length && i < bRdata.length; i++) { + int n = (aRdata[i] & 0xFF) - (bRdata[i] & 0xFF); if (n != 0) return n; } - return (a_rdata.length - b_rdata.length); + return (aRdata.length - bRdata.length); } public int compare(Record a, Record b) { @@ -88,27 +89,27 @@ public class RecordComparator implements Comparator { if (res != 0) return res; - int a_type = a.getType(); - int b_type = b.getType(); - int sig_type = 0; + int aType = a.getType(); + int bType = b.getType(); + int sigType = 0; - if (a_type == Type.RRSIG) { - a_type = ((RRSIGRecord) a).getTypeCovered(); - if (b_type != Type.RRSIG) - sig_type = 1; + if (aType == Type.RRSIG) { + aType = ((RRSIGRecord) a).getTypeCovered(); + if (bType != Type.RRSIG) + sigType = 1; } - if (b_type == Type.RRSIG) { - b_type = ((RRSIGRecord) b).getTypeCovered(); + if (bType == Type.RRSIG) { + bType = ((RRSIGRecord) b).getTypeCovered(); if (a.getType() != Type.RRSIG) - sig_type = -1; + sigType = -1; } - res = compareTypes(a_type, b_type); + res = compareTypes(aType, bType); if (res != 0) return res; - if (sig_type != 0) - return sig_type; + if (sigType != 0) + return sigType; return compareRDATA(a, b); } diff --git a/src/main/java/com/verisignlabs/dnssec/security/SignUtils.java b/src/main/java/com/verisignlabs/dnssec/security/SignUtils.java index 384ee2c..2f4d46e 100644 --- a/src/main/java/com/verisignlabs/dnssec/security/SignUtils.java +++ b/src/main/java/com/verisignlabs/dnssec/security/SignUtils.java @@ -77,28 +77,25 @@ public class SignUtils { log = v; } + private SignUtils() { + } + /** * Generate from some basic information a prototype RRSIG RR containing * everything but the actual signature itself. - * - * @param rrset - * the RRset being signed. - * @param key - * the public DNSKEY RR counterpart to the key being used to sign - * the - * RRset - * @param start - * the RRSIG inception time. - * @param expire - * the RRSIG expiration time. - * @param sig_ttl - * the TTL of the resulting RRSIG record. - * + * + * @param rrset the RRset being signed. + * @param key the public DNSKEY RR counterpart to the key being used to sign + * the RRset + * @param start the RRSIG inception time. + * @param expire the RRSIG expiration time. + * @param sigTTL the TTL of the resulting RRSIG record. + * * @return a prototype signature based on the RRset and key information. */ public static RRSIGRecord generatePreRRSIG(RRset rrset, DNSKEYRecord key, Instant start, - Instant expire, long sig_ttl) { - return new RRSIGRecord(rrset.getName(), rrset.getDClass(), sig_ttl, rrset.getType(), + Instant expire, long sigTTL) { + return new RRSIGRecord(rrset.getName(), rrset.getDClass(), sigTTL, rrset.getType(), key.getAlgorithm(), (int) rrset.getTTL(), expire, start, key.getFootprint(), key.getName(), null); } @@ -106,43 +103,36 @@ public class SignUtils { /** * Generate from some basic information a prototype RRSIG RR containing * everything but the actual signature itself. - * - * @param rec - * the DNS record being signed (forming an entire RRset). - * @param key - * the public DNSKEY RR counterpart to the key signing the - * record. - * @param start - * the RRSIG inception time. - * @param expire - * the RRSIG expiration time. - * @param sig_ttl - * the TTL of the result RRSIG record. - * + * + * @param rec the DNS record being signed (forming an entire RRset). + * @param key the public DNSKEY RR counterpart to the key signing the record. + * @param start the RRSIG inception time. + * @param expire the RRSIG expiration time. + * @param sigTTL the TTL of the result RRSIG record. + * * @return a prototype signature based on the Record and key information. */ public static RRSIGRecord generatePreRRSIG(Record rec, DNSKEYRecord key, Instant start, - Instant expire, long sig_ttl) { - return new RRSIGRecord(rec.getName(), rec.getDClass(), sig_ttl, rec.getType(), + Instant expire, long sigTTL) { + return new RRSIGRecord(rec.getName(), rec.getDClass(), sigTTL, rec.getType(), key.getAlgorithm(), rec.getTTL(), expire, start, key.getFootprint(), key.getName(), null); } /** * Generate the binary image of the prototype RRSIG RR. - * - * @param presig - * the RRSIG RR prototype. + * + * @param presig the RRSIG RR prototype. * @return the RDATA portion of the prototype RRSIG record. This forms the * first part of the data to be signed. */ private static byte[] generatePreSigRdata(RRSIGRecord presig) { - // Generate the binary image; + // Generate the binary image DNSOutput image = new DNSOutput(); // precalc some things - long start_time = presig.getTimeSigned().getEpochSecond(); - long expire_time = presig.getExpire().getEpochSecond(); + long startTime = presig.getTimeSigned().getEpochSecond(); + long expireTime = presig.getExpire().getEpochSecond(); Name signer = presig.getSigner(); // first write out the partial SIG record (this is the SIG RDATA @@ -151,8 +141,8 @@ public class SignUtils { image.writeU8(presig.getAlgorithm()); image.writeU8(presig.getLabels()); image.writeU32((int) presig.getOrigTTL()); - image.writeU32(expire_time); - image.writeU32(start_time); + image.writeU32(expireTime); + image.writeU32(startTime); image.writeU16(presig.getFootprint()); image.writeByteArray(signer.toWireCanonical()); @@ -161,15 +151,12 @@ public class SignUtils { /** * Calculate the canonical wire line format of the RRset. - * - * @param rrset - * the RRset to convert. - * @param ttl - * the TTL to use when canonicalizing -- this is generally the - * TTL of the signature if there is a pre-existing signature. If - * not it is just the ttl of the rrset itself. - * @param labels - * the labels field of the signature, or 0. + * + * @param rrset the RRset to convert. + * @param ttl the TTL to use when canonicalizing -- this is generally the TTL + * of the signature if there is a pre-existing signature. If not + * it is just the ttl of the rrset itself. + * @param labels the labels field of the signature, or 0. * @return the canonical wire line format of the rrset. This is the second * part of data to be signed. */ @@ -196,7 +183,7 @@ public class SignUtils { // now convert the wire format records in the RRset into a // list of byte arrays. - ArrayList canonical_rrs = new ArrayList(); + ArrayList canonicalRRs = new ArrayList<>(); for (Record r : rrset.rrs()) { if (r.getTTL() != ttl || wildcardName) { // If necessary, we need to create a new record with a new ttl @@ -205,8 +192,8 @@ public class SignUtils { // response. r = Record.newRecord(n, r.getType(), r.getDClass(), ttl, r.rdataToWireCanonical()); } - byte[] wire_fmt = r.toWireCanonical(); - canonical_rrs.add(wire_fmt); + byte[] wireFmt = r.toWireCanonical(); + canonicalRRs.add(wireFmt); } // put the records into the correct ordering. @@ -216,9 +203,9 @@ public class SignUtils { int offset = rrset.getName().toWireCanonical().length + 10; ByteArrayComparator bac = new ByteArrayComparator(offset, false); - Collections.sort(canonical_rrs, bac); + Collections.sort(canonicalRRs, bac); - for (byte[] wire_fmt_rec : canonical_rrs) { + for (byte[] wire_fmt_rec : canonicalRRs) { image.writeByteArray(wire_fmt_rec); } @@ -228,44 +215,38 @@ public class SignUtils { /** * Given an RRset and the prototype signature, generate the canonical data * that is to be signed. - * - * @param rrset - * the RRset to be signed. - * @param presig - * a prototype SIG RR created using the same RRset. + * + * @param rrset the RRset to be signed. + * @param presig a prototype SIG RR created using the same RRset. * @return a block of data ready to be signed. */ public static byte[] generateSigData(RRset rrset, RRSIGRecord presig) throws IOException { - byte[] rrset_data = generateCanonicalRRsetData(rrset, presig.getOrigTTL(), + byte[] rrsetData = generateCanonicalRRsetData(rrset, presig.getOrigTTL(), presig.getLabels()); - return generateSigData(rrset_data, presig); + return generateSigData(rrsetData, presig); } /** * Given an RRset and the prototype signature, generate the canonical data * that is to be signed. - * - * @param rrset_data - * the RRset converted into canonical wire line format (as per - * the - * canonicalization rules in RFC 2535). - * @param presig - * the prototype signature based on the same RRset represented - * in - * rrset_data. + * + * @param rrsetData the RRset converted into canonical wire line format (as + * per the canonicalization rules in RFC 2535). + * @param presig the prototype signature based on the same RRset represented + * in rrset_data. * @return a block of data ready to be signed. */ - public static byte[] generateSigData(byte[] rrset_data, RRSIGRecord presig) + public static byte[] generateSigData(byte[] rrsetData, RRSIGRecord presig) throws IOException { - byte[] sig_rdata = generatePreSigRdata(presig); + byte[] sigRdata = generatePreSigRdata(presig); - ByteArrayOutputStream image = new ByteArrayOutputStream(sig_rdata.length - + rrset_data.length); + ByteArrayOutputStream image = new ByteArrayOutputStream(sigRdata.length + + rrsetData.length); - image.write(sig_rdata); - image.write(rrset_data); + image.write(sigRdata); + image.write(rrsetData); return image.toByteArray(); } @@ -273,11 +254,9 @@ public class SignUtils { /** * Given the actual signature and the prototype signature, combine them and * return the fully formed RRSIGRecord. - * - * @param signature - * the cryptographic signature, in DNSSEC format. - * @param presig - * the prototype RRSIG RR to add the signature to. + * + * @param signature the cryptographic signature, in DNSSEC format. + * @param presig the prototype RRSIG RR to add the signature to. * @return the fully formed RRSIG RR. */ public static RRSIGRecord generateRRSIG(byte[] signature, RRSIGRecord presig) { @@ -291,61 +270,58 @@ public class SignUtils { /** * Converts from a RFC 2536 formatted DSA signature to a JCE (ASN.1) formatted * signature. - * + * *

* ASN.1 format = ASN1_SEQ . seq_length . ASN1_INT . Rlength . R . ANS1_INT . * Slength . S *

- * + * * The integers R and S may have a leading null byte to force the integer * positive. - * - * @param signature - * the RFC 2536 formatted DSA signature. + * + * @param signature the RFC 2536 formatted DSA signature. * @return The ASN.1 formatted DSA signature. - * @throws SignatureException - * if there was something wrong with the RFC 2536 - * formatted - * signature. + * @throws SignatureException if there was something wrong with the RFC 2536 + * formatted signature. */ public static byte[] convertDSASignature(byte[] signature) throws SignatureException { if (signature.length != 41) throw new SignatureException("RFC 2536 signature not expected length."); - byte r_pad = 0; - byte s_pad = 0; + byte rPad = 0; + byte sPad = 0; // handle initial null byte padding. if (signature[1] < 0) - r_pad++; + rPad++; if (signature[21] < 0) - s_pad++; + sPad++; // ASN.1 length = R length + S length + (2 + 2 + 2), where each 2 // is for a ASN.1 type-length byte pair of which there are three // (SEQ, INT, INT). - byte sig_length = (byte) (40 + r_pad + s_pad + 6); + byte sigLength = (byte) (40 + rPad + sPad + 6); - byte sig[] = new byte[sig_length]; + byte[] sig = new byte[sigLength]; byte pos = 0; sig[pos++] = ASN1_SEQ; - sig[pos++] = (byte) (sig_length - 2); // all but the SEQ type+length. + sig[pos++] = (byte) (sigLength - 2); // all but the SEQ type+length. sig[pos++] = ASN1_INT; - sig[pos++] = (byte) (20 + r_pad); + sig[pos++] = (byte) (20 + rPad); // copy the value of R, leaving a null byte if necessary - if (r_pad == 1) + if (rPad == 1) sig[pos++] = 0; System.arraycopy(signature, 1, sig, pos, 20); pos += 20; sig[pos++] = ASN1_INT; - sig[pos++] = (byte) (20 + s_pad); + sig[pos++] = (byte) (20 + sPad); // copy the value of S, leaving a null byte if necessary - if (s_pad == 1) + if (sPad == 1) sig[pos++] = 0; System.arraycopy(signature, 21, sig, pos, 20); @@ -356,24 +332,20 @@ public class SignUtils { /** * Converts from a JCE (ASN.1) formatted DSA signature to a RFC 2536 compliant * signature. - * + * *

* rfc2536 format = T . R . S *

- * + * * where T is a number between 0 and 8, which is based on the DSA key length, * and R & S are formatted to be exactly 20 bytes each (no leading null * bytes). - * - * @param params - * the DSA parameters associated with the DSA key used to - * generate - * the signature. - * @param signature - * the ASN.1 formatted DSA signature. + * + * @param params the DSA parameters associated with the DSA key used to + * generate the signature. + * @param signature the ASN.1 formatted DSA signature. * @return a RFC 2536 formatted DSA signature. - * @throws SignatureException - * if something is wrong with the ASN.1 format. + * @throws SignatureException if something is wrong with the ASN.1 format. */ public static byte[] convertDSASignature(DSAParams params, byte[] signature) throws SignatureException { @@ -381,16 +353,16 @@ public class SignUtils { throw new SignatureException("Invalid ASN.1 signature format: expected SEQ, INT"); } - byte r_pad = (byte) (signature[3] - 20); + byte rPad = (byte) (signature[3] - 20); - if (signature[24 + r_pad] != ASN1_INT) { + if (signature[24 + rPad] != ASN1_INT) { throw new SignatureException( "Invalid ASN.1 signature format: expected SEQ, INT, INT"); } log.finer("(start) ASN.1 DSA Sig:\n" + base64.toString(signature)); - byte s_pad = (byte) (signature[25 + r_pad] - 20); + byte sPad = (byte) (signature[25 + rPad] - 20); byte[] sig = new byte[41]; // all rfc2536 signatures are 41 bytes. @@ -398,26 +370,26 @@ public class SignUtils { sig[0] = (byte) ((params.getP().bitLength() - 512) / 64); // copy R value - if (r_pad >= 0) { - System.arraycopy(signature, 4 + r_pad, sig, 1, 20); + if (rPad >= 0) { + System.arraycopy(signature, 4 + rPad, sig, 1, 20); } else { // R is shorter than 20 bytes, so right justify the number // (r_pad is negative here, remember?). - Arrays.fill(sig, 1, 1 - r_pad, (byte) 0); - System.arraycopy(signature, 4, sig, 1 - r_pad, 20 + r_pad); + Arrays.fill(sig, 1, 1 - rPad, (byte) 0); + System.arraycopy(signature, 4, sig, 1 - rPad, 20 + rPad); } // copy S value - if (s_pad >= 0) { - System.arraycopy(signature, 26 + r_pad + s_pad, sig, 21, 20); + if (sPad >= 0) { + System.arraycopy(signature, 26 + rPad + sPad, sig, 21, 20); } else { // S is shorter than 20 bytes, so right justify the number // (s_pad is negative here). - Arrays.fill(sig, 21, 21 - s_pad, (byte) 0); - System.arraycopy(signature, 26 + r_pad, sig, 21 - s_pad, 20 + s_pad); + Arrays.fill(sig, 21, 21 - sPad, (byte) 0); + System.arraycopy(signature, 26 + rPad, sig, 21 - sPad, 20 + sPad); } - if (r_pad < 0 || s_pad < 0) { + if (rPad < 0 || sPad < 0) { log.finer("(finish ***) RFC 2536 DSA Sig:\n" + base64.toString(sig)); } else { @@ -444,103 +416,107 @@ public class SignUtils { /** * Convert a JCE standard ECDSA signature (which is a ASN.1 encoding) into a * standard DNS signature. - * + * * The format of the ASN.1 signature is - * + * * ASN1_SEQ . seq_length . ASN1_INT . r_length . R . ANS1_INT . s_length . S - * + * * where R and S may have a leading zero byte if without it the values would * be negative. * * The format of the DNSSEC signature is just R . S where R and S are both * exactly "length" bytes. - * - * @param signature - * The output of a ECDSA signature object. + * + * @param signature The output of a ECDSA signature object. * @return signature data formatted for use in DNSSEC. * @throws SignatureException if the ASN.1 encoding appears to be corrupt. */ public static byte[] convertECDSASignature(int algorithm, byte[] signature) throws SignatureException { - int exp_length = ecdsaLength(algorithm); - byte[] sig = new byte[exp_length * 2]; + int expLength = ecdsaLength(algorithm); + byte[] sig = new byte[expLength * 2]; if (signature[0] != ASN1_SEQ || signature[2] != ASN1_INT) { throw new SignatureException("Invalid ASN.1 signature format: expected SEQ, INT"); } - int r_len = signature[3]; - int r_pos = 4; + int rLen = signature[3]; + int rPos = 4; - if (signature[r_pos + r_len] != ASN1_INT) { + if (signature[rPos + rLen] != ASN1_INT) { throw new SignatureException("Invalid ASN.1 signature format: expected SEQ, INT, INT"); } - int s_pos = r_pos + r_len + 2; - int s_len = signature[r_pos + r_len + 1]; + int sPos = rPos + rLen + 2; + int sLen = signature[rPos + rLen + 1]; // Adjust for leading zeros on both R and S - if (signature[r_pos] == 0) { - r_pos++; - r_len--; + if (signature[rPos] == 0) { + rPos++; + rLen--; } - if (signature[s_pos] == 0) { - s_pos++; - s_len--; + if (signature[sPos] == 0) { + sPos++; + sLen--; } - System.arraycopy(signature, r_pos, sig, 0 + (exp_length - r_len), r_len); - System.arraycopy(signature, s_pos, sig, exp_length + (exp_length - s_len), s_len); + System.arraycopy(signature, rPos, sig, 0 + (expLength - rLen), rLen); + System.arraycopy(signature, sPos, sig, expLength + (expLength - sLen), sLen); return sig; } /** - * Convert a DNS standard ECDSA signature (defined in RFC 6605) into a - * JCE standard ECDSA signature, which is encoded in ASN.1. - * + * Convert a DNS standard ECDSA signature (defined in RFC 6605) into a JCE + * standard ECDSA signature, which is encoded in ASN.1. + * * The format of the ASN.1 signature is - * + * * ASN1_SEQ . seq_length . ASN1_INT . r_length . R . ANS1_INT . s_length . S - * + * * where R and S may have a leading zero byte if without it the values would * be negative. * * The format of the DNSSEC signature is just R . S where R and S are both * exactly "length" bytes. - * - * @param signature - * The binary signature data from an RRSIG record. + * + * @param signature The binary signature data from an RRSIG record. * @return signature data that may be used in a JCE Signature object for * verification purposes. */ public static byte[] convertECDSASignature(byte[] signature) { - byte r_src_pos, r_src_len, r_pad, s_src_pos, s_src_len, s_pad, len; + byte rSrcPos; + byte rSrcLen; + byte rPad; + byte sSrcPos; + byte sSrcLen; + byte sPad; + byte len; - r_src_len = s_src_len = (byte) (signature.length / 2); - r_src_pos = 0; - r_pad = 0; - s_src_pos = (byte) (r_src_pos + r_src_len); - s_pad = 0; - len = (byte) (6 + r_src_len + s_src_len); + rSrcLen = sSrcLen = (byte) (signature.length / 2); + rSrcPos = 0; + rPad = 0; + sSrcPos = (byte) (rSrcPos + rSrcLen); + sPad = 0; + len = (byte) (6 + rSrcLen + sSrcLen); // leading zeroes are forbidden - while (signature[r_src_pos] == 0 && r_src_len > 0) { - r_src_pos++; - r_src_len--; + while (signature[rSrcPos] == 0 && rSrcLen > 0) { + rSrcPos++; + rSrcLen--; len--; } - while (signature[s_src_pos] == 0 && s_src_len > 0) { - s_src_pos++; - s_src_len--; + while (signature[sSrcPos] == 0 && sSrcLen > 0) { + sSrcPos++; + sSrcLen--; len--; } // except when they are mandatory - if (r_src_len > 0 && signature[r_src_pos] < 0) { - r_pad = 1; + if (rSrcLen > 0 && signature[rSrcPos] < 0) { + rPad = 1; len++; } - if (s_src_len > 0 && signature[s_src_pos] < 0) { - s_pad = 1; + if (sSrcLen > 0 && signature[sSrcPos] < 0) { + sPad = 1; len++; } byte[] sig = new byte[len]; @@ -549,60 +525,56 @@ public class SignUtils { sig[pos++] = ASN1_SEQ; sig[pos++] = (byte) (len - 2); sig[pos++] = ASN1_INT; - sig[pos++] = (byte) (r_src_len + r_pad); - pos += r_pad; - System.arraycopy(signature, r_src_pos, sig, pos, r_src_len); - pos += r_src_len; + sig[pos++] = (byte) (rSrcLen + rPad); + pos += rPad; + System.arraycopy(signature, rSrcPos, sig, pos, rSrcLen); + pos += rSrcLen; sig[pos++] = ASN1_INT; - sig[pos++] = (byte) (s_src_len + s_pad); - pos += s_pad; - System.arraycopy(signature, s_src_pos, sig, pos, s_src_len); + sig[pos++] = (byte) (sSrcLen + sPad); + pos += sPad; + System.arraycopy(signature, sSrcPos, sig, pos, sSrcLen); return sig; } /** * This is a convenience routine to help us classify records/RRsets. - * + * * It characterizes a record/RRset as one of the following classes:
*
- * + * *
NORMAL
*
This record/set is properly within the zone an subject to all NXT and * SIG processing.
- * + * *
DELEGATION
*
This is a zone delegation point (or cut). It is used in NXT processing * but is not signed.
- * + * *
GLUE
*
This is a glue record and therefore not properly within the zone. It is * not included in NXT or SIG processing. Normally glue records are A records, * but this routine calls anything that is below a zone delegation glue.
- * + * *
INVALID
*
This record doesn't even belong in the zone.
- * + * *
*
- * + * * This method must be called successively on records in the canonical name * ordering, and the caller must maintain the last_cut parameter. - * - * @param zonename - * the name of the zone that is being processed. - * @param name - * the name of the record/set under consideration. - * @param type - * the type of the record/set under consideration. - * @param last_cut - * the name of the last DELEGATION record/set that was - * encountered - * while iterating over the zone in canonical order. + * + * @param zonename the name of the zone that is being processed. + * @param name the name of the record/set under consideration. + * @param type the type of the record/set under consideration. + * @param lastCut the name of the last DELEGATION record/set that was + * encountered while iterating over the zone in canonical + * order. */ - public static int recordSecType(Name zonename, Name name, int type, Name last_cut, - Name last_dname) { + public static int recordSecType(Name zonename, Name name, int type, Name lastCut, + Name lastDname) { // records not even in the zone itself are invalid. if (!name.subdomain(zonename)) return RR_INVALID; @@ -611,11 +583,11 @@ public class SignUtils { if (name.equals(zonename)) return RR_NORMAL; - if (last_cut != null && name.subdomain(last_cut)) { + if (lastCut != null && name.subdomain(lastCut)) { // if we are at the same level as a delegation point, but not one of a set of // types allowed at // a delegation point (NS, DS, NSEC), this is glue. - if (name.equals(last_cut)) { + if (name.equals(lastCut)) { if (type != Type.NS && type != Type.DS && type != Type.NXT && type != Type.NSEC) { return RR_GLUE; } @@ -628,8 +600,8 @@ public class SignUtils { } // if we are below a DNAME, then the RR is invalid. - if (last_dname != null && name.subdomain(last_dname) - && name.labels() > last_dname.labels()) { + if (lastDname != null && name.subdomain(lastDname) + && name.labels() > lastDname.labels()) { return RR_INVALID; } @@ -652,7 +624,7 @@ public class SignUtils { */ public static List assembleIntoRRsets(List records) { RRset rrset = new RRset(); - ArrayList rrsets = new ArrayList(); + ArrayList rrsets = new ArrayList<>(); for (Record r : records) { // First record @@ -702,7 +674,7 @@ public class SignUtils { this.type = nodeType; this.ttl = r.getTTL(); this.dclass = r.getDClass(); - this.typemap = new HashSet(); + this.typemap = new HashSet<>(); this.isSecureNode = false; this.hasOptInSpan = false; addType(r.getType()); @@ -723,7 +695,7 @@ public class SignUtils { } public String toString() { - StringBuffer sb = new StringBuffer(name.toString()); + StringBuilder sb = new StringBuilder(name.toString()); if (isSecureNode) sb.append("(S)"); if (hasOptInSpan) @@ -745,83 +717,79 @@ public class SignUtils { /** * Given a canonical (by name) ordered list of records in a zone, generate the * NSEC records in place. - * + * * Note that the list that the records are stored in must support the * listIterator.add() operation. - * - * @param zonename - * the name of the zone (used to distinguish between zone apex - * NS - * RRsets and delegations). - * @param records - * a list of {@link org.xbill.DNS.Record} objects in DNSSEC - * canonical - * order. + * + * @param zonename the name of the zone (used to distinguish between zone apex + * NS RRsets and delegations). + * @param records a list of {@link org.xbill.DNS.Record} objects in DNSSEC + * canonical order. */ public static void generateNSECRecords(Name zonename, List records) { // This works by iterating over a known sorted list of records. - NodeInfo last_node = null; - NodeInfo current_node = null; + NodeInfo lastNode = null; + NodeInfo currentNode = null; - Name last_cut = null; - Name last_dname = null; + Name lastCut = null; + Name lastDname = null; int backup; - long nsec_ttl = 0; + long nsecTTL = 0; // First find the SOA record -- it should be near the beginning -- and get // the soa minimum for (Record r : records) { if (r.getType() == Type.SOA) { SOARecord soa = (SOARecord) r; - nsec_ttl = Math.min(soa.getMinimum(), soa.getTTL()); + nsecTTL = Math.min(soa.getMinimum(), soa.getTTL()); break; } } - if (nsec_ttl == 0) { + if (nsecTTL == 0) { throw new IllegalArgumentException("Zone did not contain a SOA record"); } for (ListIterator i = records.listIterator(); i.hasNext();) { Record r = i.next(); - Name r_name = r.getName(); - int r_type = r.getType(); - int r_sectype = recordSecType(zonename, r_name, r_type, last_cut, last_dname); + Name rName = r.getName(); + int rType = r.getType(); + int rSecType = recordSecType(zonename, rName, rType, lastCut, lastDname); // skip irrelevant records - if (r_sectype == RR_INVALID || r_sectype == RR_GLUE) + if (rSecType == RR_INVALID || rSecType == RR_GLUE) continue; // note our last delegation point so we can recognize glue. - if (r_sectype == RR_DELEGATION) - last_cut = r_name; + if (rSecType == RR_DELEGATION) + lastCut = rName; // if this is a DNAME, note it so we can recognize junk - if (r_type == Type.DNAME) - last_dname = r_name; + if (rType == Type.DNAME) + lastDname = rName; // first node -- initialize - if (current_node == null) { - current_node = new NodeInfo(r, r_sectype); - current_node.addType(Type.RRSIG); - current_node.addType(Type.NSEC); + if (currentNode == null) { + currentNode = new NodeInfo(r, rSecType); + currentNode.addType(Type.RRSIG); + currentNode.addType(Type.NSEC); continue; } // record name hasn't changed, so we are still on the same node. - if (r_name.equals(current_node.name)) { - current_node.addType(r_type); + if (rName.equals(currentNode.name)) { + currentNode.addType(rType); continue; } - if (last_node != null) { - NSECRecord nsec = new NSECRecord(last_node.name, last_node.dclass, nsec_ttl, - current_node.name, last_node.getTypes()); + if (lastNode != null) { + NSECRecord nsec = new NSECRecord(lastNode.name, lastNode.dclass, nsecTTL, + currentNode.name, lastNode.getTypes()); // Note: we have to add this through the iterator, otherwise // the next access via the iterator will generate a // ConcurrencyModificationException. - backup = i.nextIndex() - last_node.nsecIndex; + backup = i.nextIndex() - lastNode.nsecIndex; for (int j = 0; j < backup; j++) i.previous(); i.add(nsec); @@ -831,25 +799,25 @@ public class SignUtils { log.finer("Generated: " + nsec); } - last_node = current_node; + lastNode = currentNode; - current_node.nsecIndex = i.previousIndex(); - current_node = new NodeInfo(r, r_sectype); - current_node.addType(Type.RRSIG); - current_node.addType(Type.NSEC); + currentNode.nsecIndex = i.previousIndex(); + currentNode = new NodeInfo(r, rSecType); + currentNode.addType(Type.RRSIG); + currentNode.addType(Type.NSEC); } // Generate next to last NSEC - if (last_node != null) { - NSECRecord nsec = new NSECRecord(last_node.name, last_node.dclass, nsec_ttl, - current_node.name, last_node.getTypes()); - records.add(last_node.nsecIndex - 1, nsec); + if (lastNode != null) { + NSECRecord nsec = new NSECRecord(lastNode.name, lastNode.dclass, nsecTTL, + currentNode.name, lastNode.getTypes()); + records.add(lastNode.nsecIndex - 1, nsec); log.finer("Generated: " + nsec); } // Generate last NSEC - NSECRecord nsec = new NSECRecord(current_node.name, current_node.dclass, nsec_ttl, - zonename, current_node.getTypes()); + NSECRecord nsec = new NSECRecord(currentNode.name, currentNode.dclass, nsecTTL, + zonename, currentNode.getTypes()); records.add(nsec); log.finer("Generated: " + nsec); @@ -858,100 +826,92 @@ public class SignUtils { /** * Given a canonical (by name) ordered list of records in a zone, generate the * NSEC3 records in place. - * + * * Note that the list that the records are stored in must support the * listIterator.add() operation. - * - * @param zonename - * the name of the zone (used to distinguish between zone - * apex NS - * RRsets and delegations). - * @param records - * a list of {@link org.xbill.DNS.Record} objects in - * DNSSEC canonical - * order. - * @param salt - * The NSEC3 salt to use (may be null or empty for no - * salt). - * @param iterations - * The number of hash iterations to use. - * @param nsec3param_ttl - * The TTL to use for the generated NSEC3PARAM records - * (NSEC3 records - * will use the SOA minimum) + * + * @param zonename the name of the zone (used to distinguish between zone + * apex NS RRsets and delegations). + * @param records a list of {@link org.xbill.DNS.Record} objects in + * DNSSEC canonical order. + * @param salt The NSEC3 salt to use (may be null or empty for no + * salt). + * @param iterations The number of hash iterations to use. + * @param nsec3paramTTL The TTL to use for the generated NSEC3PARAM records + * (NSEC3 records will use the SOA minimum) * @throws NoSuchAlgorithmException */ public static void generateNSEC3Records(Name zonename, List records, - byte[] salt, int iterations, long nsec3param_ttl) + byte[] salt, int iterations, long nsec3paramTTL) throws NoSuchAlgorithmException { - List proto_nsec3s = new ArrayList(); - NodeInfo current_node = null; - NodeInfo last_node = null; + List protoNSEC3s = new ArrayList<>(); + NodeInfo currentNode = null; + NodeInfo lastNode = null; // For detecting glue. - Name last_cut = null; + Name lastCut = null; // For detecting junk below a DNAME - Name last_dname = null; + Name lastDname = null; - long nsec3_ttl = 0; + long nsec3TTL = 0; for (Record r : records) { - Name r_name = r.getName(); - int r_type = r.getType(); + Name rName = r.getName(); + int rType = r.getType(); // Classify this record so we know if we can skip it. - int r_sectype = recordSecType(zonename, r_name, r_type, last_cut, last_dname); + int rSecType = recordSecType(zonename, rName, rType, lastCut, lastDname); // skip irrelevant records - if (r_sectype == RR_INVALID || r_sectype == RR_GLUE) + if (rSecType == RR_INVALID || rSecType == RR_GLUE) continue; // note our last delegation point so we can recognize glue. - if (r_sectype == RR_DELEGATION) - last_cut = r_name; + if (rSecType == RR_DELEGATION) + lastCut = rName; // note our last DNAME point, so we can recognize junk. - if (r_type == Type.DNAME) - last_dname = r_name; + if (rType == Type.DNAME) + lastDname = rName; - if (r_type == Type.SOA) { + if (rType == Type.SOA) { SOARecord soa = (SOARecord) r; - nsec3_ttl = Math.min(soa.getMinimum(), soa.getTTL()); - if (nsec3param_ttl < 0) { - nsec3param_ttl = nsec3_ttl; + nsec3TTL = Math.min(soa.getMinimum(), soa.getTTL()); + if (nsec3paramTTL < 0) { + nsec3paramTTL = nsec3TTL; } } // For the first iteration, we create our current node. - if (current_node == null) { - current_node = new NodeInfo(r, r_sectype); + if (currentNode == null) { + currentNode = new NodeInfo(r, rSecType); continue; } // If we are at the same name, we are on the same node. - if (r_name.equals(current_node.name)) { - current_node.addType(r_type); + if (rName.equals(currentNode.name)) { + currentNode.addType(rType); continue; } // At this point, r represents the start of a new node. // So we move current_node to last_node and generate a new current node. // But first, we need to do something with the last node. - generateNSEC3ForNode(last_node, zonename, salt, iterations, false, proto_nsec3s); + generateNSEC3ForNode(lastNode, zonename, salt, iterations, false, protoNSEC3s); - last_node = current_node; - current_node = new NodeInfo(r, r_sectype); + lastNode = currentNode; + currentNode = new NodeInfo(r, rSecType); } // process last two nodes. - generateNSEC3ForNode(last_node, zonename, salt, iterations, false, proto_nsec3s); - generateNSEC3ForNode(current_node, zonename, salt, iterations, false, proto_nsec3s); + generateNSEC3ForNode(lastNode, zonename, salt, iterations, false, protoNSEC3s); + generateNSEC3ForNode(currentNode, zonename, salt, iterations, false, protoNSEC3s); - List nsec3s = finishNSEC3s(proto_nsec3s, nsec3_ttl); + List nsec3s = finishNSEC3s(protoNSEC3s, nsec3TTL); records.addAll(nsec3s); NSEC3PARAMRecord nsec3param = new NSEC3PARAMRecord(zonename, DClass.IN, - nsec3param_ttl, + nsec3paramTTL, NSEC3Record.SHA1_DIGEST_ID, (byte) 0, iterations, salt); records.add(nsec3param); @@ -963,118 +923,108 @@ public class SignUtils { * NSEC3 records in place using Opt-Out NSEC3 records. This means that * non-apex NS RRs (and glue below those delegations) will, by default, not be * included in the NSEC3 chain. - * + * * Note that the list that the records are stored in must support the * listIterator.add() operation. - * - * @param zonename - * the name of the zone (used to distinguish between zone - * apex NS - * RRsets and delegations). - * @param records - * a list of {@link org.xbill.DNS.Record} objects in - * DNSSEC canonical - * order. - * @param includedNames - * A list of {@link org.xbill.DNS.Name} objects. These - * names will be - * included in the NSEC3 chain (if they exist in the zone) - * regardless. - * @param salt - * The NSEC3 salt to use (may be null or empty for no - * salt). - * @param iterations - * The number of hash iterations to use. - * @param nsec3param_ttl - * The TTL to use for the generated NSEC3PARAM records - * (NSEC3 records - * will use the SOA minimum) + * + * @param zonename the name of the zone (used to distinguish between zone + * apex NS RRsets and delegations). + * @param records a list of {@link org.xbill.DNS.Record} objects in + * DNSSEC canonical order. + * @param includedNames A list of {@link org.xbill.DNS.Name} objects. These + * names will be included in the NSEC3 chain (if they + * exist in the zone) regardless. + * @param salt The NSEC3 salt to use (may be null or empty for no + * salt). + * @param iterations The number of hash iterations to use. + * @param nsec3paramTTL The TTL to use for the generated NSEC3PARAM records + * (NSEC3 records will use the SOA minimum) * @throws NoSuchAlgorithmException */ public static void generateOptOutNSEC3Records(Name zonename, List records, List includedNames, byte[] salt, - int iterations, long nsec3param_ttl) + int iterations, long nsec3paramTTL) throws NoSuchAlgorithmException { - List proto_nsec3s = new ArrayList(); - NodeInfo current_node = null; - NodeInfo last_node = null; + List protoNSEC3s = new ArrayList<>(); + NodeInfo currentNode = null; + NodeInfo lastNode = null; // For detecting glue. - Name last_cut = null; + Name lastCut = null; // For detecting out-of-zone records below a DNAME - Name last_dname = null; + Name lastDname = null; - long nsec3_ttl = 0; + long nsec3TTL = 0; HashSet includeSet = null; if (includedNames != null) { - includeSet = new HashSet(includedNames); + includeSet = new HashSet<>(includedNames); } for (Record r : records) { - Name r_name = r.getName(); - int r_type = r.getType(); + Name rName = r.getName(); + int rType = r.getType(); // Classify this record so we know if we can skip it. - int r_sectype = recordSecType(zonename, r_name, r_type, last_cut, last_dname); + int rSecType = recordSecType(zonename, rName, rType, lastCut, lastDname); // skip irrelevant records - if (r_sectype == RR_INVALID || r_sectype == RR_GLUE) + if (rSecType == RR_INVALID || rSecType == RR_GLUE) continue; // note our last delegation point so we can recognize glue. - if (r_sectype == RR_DELEGATION) - last_cut = r_name; + if (rSecType == RR_DELEGATION) + lastCut = rName; - if (r_type == Type.DNAME) - last_dname = r_name; + if (rType == Type.DNAME) + lastDname = rName; - if (r_type == Type.SOA) { + if (rType == Type.SOA) { SOARecord soa = (SOARecord) r; - nsec3_ttl = Math.min(soa.getMinimum(), soa.getTTL()); - if (nsec3param_ttl < 0) { - nsec3param_ttl = nsec3_ttl; + nsec3TTL = Math.min(soa.getMinimum(), soa.getTTL()); + if (nsec3paramTTL < 0) { + nsec3paramTTL = nsec3TTL; } } // For the first iteration, we create our current node. - if (current_node == null) { - current_node = new NodeInfo(r, r_sectype); + if (currentNode == null) { + currentNode = new NodeInfo(r, rSecType); continue; } // If we are at the same name, we are on the same node. - if (r_name.equals(current_node.name)) { - current_node.addType(r_type); + if (rName.equals(currentNode.name)) { + currentNode.addType(rType); continue; } - if (includeSet != null && includeSet.contains(current_node.name)) { - current_node.isSecureNode = true; + if (includeSet != null && includeSet.contains(currentNode.name)) { + currentNode.isSecureNode = true; } // At this point, r represents the start of a new node. // So we move current_node to last_node and generate a new current node. // But first, we need to do something with the last node. - generateNSEC3ForNode(last_node, zonename, salt, iterations, true, proto_nsec3s); + generateNSEC3ForNode(lastNode, zonename, salt, iterations, true, protoNSEC3s); - if (current_node.isSecureNode) { - last_node = current_node; + if (currentNode.isSecureNode) { + lastNode = currentNode; } else { - last_node.hasOptInSpan = true; + lastNode.hasOptInSpan = true; } - current_node = new NodeInfo(r, r_sectype); + currentNode = new NodeInfo(r, rSecType); } // process last two nodes. - generateNSEC3ForNode(last_node, zonename, salt, iterations, true, proto_nsec3s); - generateNSEC3ForNode(current_node, zonename, salt, iterations, true, proto_nsec3s); + generateNSEC3ForNode(lastNode, zonename, salt, iterations, true, protoNSEC3s); + generateNSEC3ForNode(currentNode, zonename, salt, iterations, true, protoNSEC3s); - List nsec3s = finishNSEC3s(proto_nsec3s, nsec3_ttl); + List nsec3s = finishNSEC3s(protoNSEC3s, nsec3TTL); records.addAll(nsec3s); NSEC3PARAMRecord nsec3param = new NSEC3PARAMRecord(zonename, DClass.IN, - nsec3param_ttl, + nsec3paramTTL, NSEC3Record.SHA1_DIGEST_ID, (byte) 0, iterations, salt); records.add(nsec3param); @@ -1084,19 +1034,13 @@ public class SignUtils { * For a given node (representing all of the RRsets at a given name), generate * all of the necessary NSEC3 records for it. That is, generate the NSEC3 for * the node itself, and for any potential empty non-terminals. - * - * @param node - * The node in question. - * @param zonename - * The zonename. - * @param salt - * The salt to use for the NSEC3 RRs - * @param iterations - * The iterations to use for the NSEC3 RRs. - * @param optIn - * If true, the NSEC3 will have the Opt-Out flag set. - * @param nsec3s - * The current list of NSEC3s -- this will be updated. + * + * @param node The node in question. + * @param zonename The zonename. + * @param salt The salt to use for the NSEC3 RRs + * @param iterations The iterations to use for the NSEC3 RRs. + * @param optIn If true, the NSEC3 will have the Opt-Out flag set. + * @param nsec3s The current list of NSEC3s -- this will be updated. * @throws NoSuchAlgorithmException */ private static void generateNSEC3ForNode(NodeInfo node, Name zonename, byte[] salt, @@ -1132,23 +1076,16 @@ public class SignUtils { /** * Create a "prototype" NSEC3 record. Basically, a mutable NSEC3 record. - * - * @param name - * The original ownername to use. - * @param zonename - * The zonename to use. - * @param ttl - * The TTL to use. - * @param salt - * The salt to use. - * @param iterations - * The number of hash iterations to use. - * @param optIn - * The value of the Opt-Out flag. - * @param types - * The typecodes present at this name. + * + * @param name The original ownername to use. + * @param zonename The zonename to use. + * @param ttl The TTL to use. + * @param salt The salt to use. + * @param iterations The number of hash iterations to use. + * @param optIn The value of the Opt-Out flag. + * @param types The typecodes present at this name. * @return A mutable NSEC3 record. - * + * * @throws NoSuchAlgorithmException */ private static ProtoNSEC3 generateNSEC3(Name name, Name zonename, long ttl, @@ -1169,62 +1106,59 @@ public class SignUtils { * Given a list of {@link ProtoNSEC3} object (mutable NSEC3 RRs), convert the * list into the set of actual {@link org.xbill.DNS.NSEC3Record} objects. This * will remove duplicates and finalize the records. - * - * @param nsec3s - * The list of ProtoNSEC3 objects - * @param ttl - * The TTL to assign to the finished NSEC3 records. In general, - * this - * should match the SOA minimum value for the zone. + * + * @param nsec3s The list of ProtoNSEC3 objects + * @param ttl The TTL to assign to the finished NSEC3 records. In general, + * this should match the SOA minimum value for the zone. * @return The list of {@link org.xbill.DNS.NSEC3Record} objects. */ private static List finishNSEC3s(List nsec3s, long ttl) { if (nsec3s == null) - return null; + return new ArrayList<>(); Collections.sort(nsec3s, new ProtoNSEC3.Comparator()); - ProtoNSEC3 prev_nsec3 = null; - ProtoNSEC3 cur_nsec3 = null; - byte[] first_nsec3_hash = null; + ProtoNSEC3 prevNSEC3 = null; + ProtoNSEC3 curNSEC3 = null; + byte[] firstNSEC3Hash = null; for (ListIterator i = nsec3s.listIterator(); i.hasNext();) { - cur_nsec3 = i.next(); + curNSEC3 = i.next(); // check to see if cur is a duplicate (by name) - if (prev_nsec3 != null - && Arrays.equals(prev_nsec3.getOwner(), cur_nsec3.getOwner())) { + if (prevNSEC3 != null + && Arrays.equals(prevNSEC3.getOwner(), curNSEC3.getOwner())) { log.fine("found duplicate NSEC3 (by name) -- merging type maps: " - + prev_nsec3.getTypemap() + " and " + cur_nsec3.getTypemap()); + + prevNSEC3.getTypemap() + " and " + curNSEC3.getTypemap()); i.remove(); - prev_nsec3.mergeTypes(cur_nsec3.getTypemap()); - log.fine("merged type map: " + prev_nsec3.getTypemap()); + prevNSEC3.mergeTypes(curNSEC3.getTypemap()); + log.fine("merged type map: " + prevNSEC3.getTypemap()); continue; } - byte[] next = cur_nsec3.getOwner(); + byte[] next = curNSEC3.getOwner(); - if (prev_nsec3 == null) { - prev_nsec3 = cur_nsec3; - first_nsec3_hash = next; + if (prevNSEC3 == null) { + prevNSEC3 = curNSEC3; + firstNSEC3Hash = next; continue; } - prev_nsec3.setNext(next); - prev_nsec3 = cur_nsec3; + prevNSEC3.setNext(next); + prevNSEC3 = curNSEC3; } // Handle last NSEC3. - if (prev_nsec3.getNext() == null) { + if (prevNSEC3.getNext() == null) { // if prev_nsec3's next field hasn't been set, then it is the last // record (i.e., all remaining records were duplicates.) - prev_nsec3.setNext(first_nsec3_hash); + prevNSEC3.setNext(firstNSEC3Hash); } else { // otherwise, cur_nsec3 is the last record. - cur_nsec3.setNext(first_nsec3_hash); + curNSEC3.setNext(firstNSEC3Hash); } // Convert our ProtoNSEC3s to actual (immutable) NSEC3Record objects. - List res = new ArrayList(nsec3s.size()); + List res = new ArrayList<>(nsec3s.size()); for (ProtoNSEC3 p : nsec3s) { p.setTTL(ttl); res.add(p.getNSEC3Record()); @@ -1236,90 +1170,85 @@ public class SignUtils { /** * Given a canonical (by name) ordered list of records in a zone, generate the * NSEC records in place. - * + * * Note that the list that the records are stored in must support the * listIterator.add operation. - * - * @param zonename - * the name of the zone apex, used to distinguish between - * authoritative and delegation NS RRsets. - * @param records - * a list of {@link org.xbill.DNS.Record}s in DNSSEC + * + * @param zonename the name of the zone apex, used to distinguish + * between authoritative and delegation NS RRsets. + * @param records a list of {@link org.xbill.DNS.Record}s in DNSSEC * canonical order. - * @param includeNames - * a list of names that should be in the NXT chain - * regardless. This - * may be null. - * @param beConservative - * if true, then Opt-In NXTs will only be generated where - * there is - * actually a span of insecure delegations. + * @param includeNames a list of names that should be in the NXT chain + * regardless. This may be null. + * @param beConservative if true, then Opt-In NXTs will only be generated + * where there is actually a span of insecure + * delegations. */ public static void generateOptInNSECRecords(Name zonename, List records, List includeNames, boolean beConservative) { // This works by iterating over a known sorted list of records. - NodeInfo last_node = null; - NodeInfo current_node = null; + NodeInfo lastNode = null; + NodeInfo currentNode = null; - Name last_cut = null; - Name last_dname = null; + Name lastCut = null; + Name lastDname = null; int backup; HashSet includeSet = null; if (includeNames != null) { - includeSet = new HashSet(includeNames); + includeSet = new HashSet<>(includeNames); } for (ListIterator i = records.listIterator(); i.hasNext();) { Record r = i.next(); - Name r_name = r.getName(); - int r_type = r.getType(); - int r_sectype = recordSecType(zonename, r_name, r_type, last_cut, last_dname); + Name rName = r.getName(); + int rType = r.getType(); + int rSecType = recordSecType(zonename, rName, rType, lastCut, lastDname); // skip irrelevant records - if (r_sectype == RR_INVALID || r_sectype == RR_GLUE) + if (rSecType == RR_INVALID || rSecType == RR_GLUE) continue; // note our last delegation point so we can recognize glue. - if (r_sectype == RR_DELEGATION) - last_cut = r_name; + if (rSecType == RR_DELEGATION) + lastCut = rName; - if (r_type == Type.DNAME) - last_dname = r_name; + if (rType == Type.DNAME) + lastDname = rName; // first node -- initialize - if (current_node == null) { - current_node = new NodeInfo(r, r_sectype); - current_node.addType(Type.RRSIG); + if (currentNode == null) { + currentNode = new NodeInfo(r, rSecType); + currentNode.addType(Type.RRSIG); continue; } // record name hasn't changed, so we are still on the same node. - if (r_name.equals(current_node.name)) { - current_node.addType(r_type); + if (rName.equals(currentNode.name)) { + currentNode.addType(rType); continue; } // If the name is in the set of included names, mark it as // secure. - if (includeSet != null && includeSet.contains(current_node.name)) { - current_node.isSecureNode = true; + if (includeSet != null && includeSet.contains(currentNode.name)) { + currentNode.isSecureNode = true; } - if (last_node != null && current_node.isSecureNode) { + if (lastNode != null && currentNode.isSecureNode) { // generate a NSEC record. - if (beConservative && !last_node.hasOptInSpan) { - last_node.addType(Type.NSEC); + if (beConservative && !lastNode.hasOptInSpan) { + lastNode.addType(Type.NSEC); } - NSECRecord nsec = new NSECRecord(last_node.name, last_node.dclass, last_node.ttl, - current_node.name, last_node.getTypes()); + NSECRecord nsec = new NSECRecord(lastNode.name, lastNode.dclass, lastNode.ttl, + currentNode.name, lastNode.getTypes()); // Note: we have to add this through the iterator, otherwise // the next access via the iterator will generate a // ConcurrencyModificationException. - backup = i.nextIndex() - last_node.nsecIndex; + backup = i.nextIndex() - lastNode.nsecIndex; for (int j = 0; j < backup; j++) i.previous(); i.add(nsec); @@ -1329,49 +1258,49 @@ public class SignUtils { log.finer("Generated: " + nsec); } - if (current_node.isSecureNode) { - last_node = current_node; - } else if (last_node != null) { + if (currentNode.isSecureNode) { + lastNode = currentNode; + } else if (lastNode != null) { // last_node does not change -- last_node is essentially the // last *secure* node, and current_node is not secure. // However, we need to note the passing of the insecure node. - last_node.hasOptInSpan = true; + lastNode.hasOptInSpan = true; } - current_node.nsecIndex = i.previousIndex(); - current_node = new NodeInfo(r, r_sectype); - current_node.addType(Type.RRSIG); + currentNode.nsecIndex = i.previousIndex(); + currentNode = new NodeInfo(r, rSecType); + currentNode.addType(Type.RRSIG); } // Generate next to last NSEC - if (last_node != null && current_node.isSecureNode) { + if (lastNode != null && currentNode.isSecureNode) { // generate a NSEC record. - if (beConservative && !last_node.hasOptInSpan) { - last_node.addType(Type.NSEC); + if (beConservative && !lastNode.hasOptInSpan) { + lastNode.addType(Type.NSEC); } - NSECRecord nsec = new NSECRecord(last_node.name, last_node.dclass, last_node.ttl, - current_node.name, last_node.getTypes()); - records.add(last_node.nsecIndex - 1, nsec); + NSECRecord nsec = new NSECRecord(lastNode.name, lastNode.dclass, lastNode.ttl, + currentNode.name, lastNode.getTypes()); + records.add(lastNode.nsecIndex - 1, nsec); log.finer("Generated: " + nsec); } // Generate last NSEC NSECRecord nsec; - if (current_node.isSecureNode) { + if (currentNode.isSecureNode) { if (beConservative) { - current_node.addType(Type.NSEC); + currentNode.addType(Type.NSEC); } - nsec = new NSECRecord(current_node.name, current_node.dclass, current_node.ttl, - zonename, current_node.getTypes()); + nsec = new NSECRecord(currentNode.name, currentNode.dclass, currentNode.ttl, + zonename, currentNode.getTypes()); // we can just tack this on the end as we are working on the // last node. records.add(nsec); } else { - nsec = new NSECRecord(last_node.name, last_node.dclass, last_node.ttl, zonename, - last_node.getTypes()); + nsec = new NSECRecord(lastNode.name, lastNode.dclass, lastNode.ttl, zonename, + lastNode.getTypes()); // We need to tack this on after the last secure node, not the // end of the whole list. - records.add(last_node.nsecIndex, nsec); + records.add(lastNode.nsecIndex, nsec); } log.finer("Generated: " + nsec); @@ -1380,30 +1309,26 @@ public class SignUtils { /** * Given a zone with DNSKEY records at delegation points, convert those KEY * records into their corresponding DS records in place. - * - * @param zonename - * the name of the zone, used to reliably distinguish the zone - * apex - * from other records. - * @param records - * a list of {@link org.xbill.DNS.Record} objects. - * @param digest_alg - * The digest algorithm to use. + * + * @param zonename the name of the zone, used to reliably distinguish the + * zone apex from other records. + * @param records a list of {@link org.xbill.DNS.Record} objects. + * @param digestAlg The digest algorithm to use. */ - public static void generateDSRecords(Name zonename, List records, int digest_alg) { + public static void generateDSRecords(Name zonename, List records, int digestAlg) { for (ListIterator i = records.listIterator(); i.hasNext();) { Record r = i.next(); if (r == null) continue; // this should never be true. - Name r_name = r.getName(); - if (r_name == null) + Name rName = r.getName(); + if (rName == null) continue; // this should never be true. // Convert non-zone level KEY records into DS records. - if (r.getType() == Type.DNSKEY && !r_name.equals(zonename)) { - DSRecord ds = calculateDSRecord((DNSKEYRecord) r, digest_alg, r.getTTL()); + if (r.getType() == Type.DNSKEY && !rName.equals(zonename)) { + DSRecord ds = calculateDSRecord((DNSKEYRecord) r, digestAlg, r.getTTL()); i.set(ds); } @@ -1412,15 +1337,13 @@ public class SignUtils { /** * Given a zone, remove all records that are generated. - * - * @param zonename - * the name of the zone. - * @param records - * a list of {@link org.xbill.DNS.Record} objects. + * + * @param zonename the name of the zone. + * @param records a list of {@link org.xbill.DNS.Record} objects. */ public static void removeGeneratedRecords(Name zonename, List records) { for (Iterator i = records.iterator(); i.hasNext();) { - Record r = (Record) i.next(); + Record r = i.next(); if (r.getType() == Type.RRSIG || r.getType() == Type.NSEC || r.getType() == Type.NSEC3 || r.getType() == Type.NSEC3PARAM) { @@ -1433,9 +1356,8 @@ public class SignUtils { * Remove duplicate records from a list of records. This routine presumes the * list of records is in a canonical sorted order, at least on name and RR * type. - * - * @param records - * a list of {@link org.xbill.DNS.Record} object, in sorted + * + * @param records a list of {@link org.xbill.DNS.Record} object, in sorted * order. */ public static void removeDuplicateRecords(List records) { @@ -1456,18 +1378,14 @@ public class SignUtils { /** * Given a DNSKEY record, generate the DS record from it. - * - * @param keyrec - * the KEY record in question. - * @param digest_alg - * The digest algorithm (SHA-1, SHA-256, etc.). - * @param ttl - * the desired TTL for the generated DS record. If zero, or - * negative, - * the original KEY RR's TTL will be used. + * + * @param keyrec the KEY record in question. + * @param digestAlg The digest algorithm (SHA-1, SHA-256, etc.). + * @param ttl the desired TTL for the generated DS record. If zero, or + * negative, the original KEY RR's TTL will be used. * @return the corresponding {@link org.xbill.DNS.DSRecord} */ - public static DSRecord calculateDSRecord(DNSKEYRecord keyrec, int digest_alg, long ttl) { + public static DSRecord calculateDSRecord(DNSKEYRecord keyrec, int digestAlg, long ttl) { if (keyrec == null) return null; @@ -1483,7 +1401,7 @@ public class SignUtils { byte[] digest; MessageDigest md; - switch (digest_alg) { + switch (digestAlg) { case DNSSEC.Digest.SHA1: md = MessageDigest.getInstance("SHA"); digest = md.digest(os.toByteArray()); @@ -1493,11 +1411,11 @@ public class SignUtils { digest = md.digest(os.toByteArray()); break; default: - throw new IllegalArgumentException("Unknown digest id: " + digest_alg); + throw new IllegalArgumentException("Unknown digest id: " + digestAlg); } return new DSRecord(keyrec.getName(), keyrec.getDClass(), ttl, - keyrec.getFootprint(), keyrec.getAlgorithm(), digest_alg, + keyrec.getFootprint(), keyrec.getAlgorithm(), digestAlg, digest); } catch (NoSuchAlgorithmException e) { @@ -1508,35 +1426,26 @@ public class SignUtils { /** * Calculate an NSEC3 hash based on a DNS name and NSEC3 hash parameters. - * - * @param n - * The name to hash. - * @param hash_algorithm - * The hash algorithm to use. - * @param iterations - * The number of iterations to do. - * @param salt - * The salt to use. + * + * @param n The name to hash. + * @param hashAlgorithm The hash algorithm to use. + * @param iterations The number of iterations to do. + * @param salt The salt to use. * @return The calculated hash as a byte array. - * @throws NoSuchAlgorithmException - * If the hash algorithm is unrecognized. + * @throws NoSuchAlgorithmException If the hash algorithm is unrecognized. */ - public static byte[] nsec3hash(Name n, int hash_algorithm, int iterations, byte[] salt) + public static byte[] nsec3hash(Name n, int hashAlgorithm, int iterations, byte[] salt) throws NoSuchAlgorithmException { MessageDigest md; - switch (hash_algorithm) { - case NSEC3Record.SHA1_DIGEST_ID: - md = MessageDigest.getInstance("SHA1"); - break; - default: - throw new NoSuchAlgorithmException("Unknown NSEC3 algorithm identifier: " - + hash_algorithm); + if (hashAlgorithm != NSEC3Record.SHA1_DIGEST_ID) { + throw new NoSuchAlgorithmException("Unknown NSEC3 algorithm identifier: " + hashAlgorithm); } + md = MessageDigest.getInstance("SHA1"); // Construct our wire form. - byte[] wire_name = n.toWireCanonical(); - byte[] res = wire_name; // for the first iteration. + byte[] wireName = n.toWireCanonical(); + byte[] res = wireName; // for the first iteration. for (int i = 0; i <= iterations; i++) { // Concatenate the salt, if it exists. if (salt != null) { diff --git a/src/main/java/com/verisignlabs/dnssec/security/TypeMap.java b/src/main/java/com/verisignlabs/dnssec/security/TypeMap.java index 84542cd..d4a8bea 100644 --- a/src/main/java/com/verisignlabs/dnssec/security/TypeMap.java +++ b/src/main/java/com/verisignlabs/dnssec/security/TypeMap.java @@ -37,7 +37,7 @@ public class TypeMap { private Set typeSet; public TypeMap() { - this.typeSet = new HashSet(); + this.typeSet = new HashSet<>(); } /** Add the given type to the typemap. */ @@ -78,20 +78,20 @@ public class TypeMap { TypeMap typemap = new TypeMap(); int page; - int byte_length; + int byteLength; while (m < map.length) { page = map[m++]; - byte_length = map[m++]; + byteLength = map[m++]; - for (int i = 0; i < byte_length; i++) { + for (int i = 0; i < byteLength; i++) { for (int j = 0; j < 8; j++) { - if ((map[m + i] & (1 << (7 - j))) != 0) { + if (((map[m + i] & 0xFF) & (1 << (7 - j))) != 0) { typemap.set((page << 8) + (i * 8) + j); } } } - m += byte_length; + m += byteLength; } return typemap; @@ -115,7 +115,7 @@ public class TypeMap { int[] types = getTypes(); Arrays.sort(types); - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for (int i = 0; i < types.length; i++) { if (i > 0) @@ -129,16 +129,16 @@ public class TypeMap { 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 // typecode in this section. - int max_type = types[end - 1] & 0xFF; - int map_length = (max_type / 8) + 1; + int maxType = types[end - 1] & 0xFF; + int mapLength = (maxType / 8) + 1; // write the map "header" -- the base and the length of the map. out.writeU8(base & 0xFF); - out.writeU8(map_length & 0xFF); + out.writeU8(mapLength & 0xFF); // allocate a temporary scratch space for caculating the actual // bitmap. - byte[] map = new byte[map_length]; + byte[] map = new byte[mapLength]; // for each type in our sub-array, set its corresponding bit in the map. for (int i = start; i < end; i++) { @@ -179,7 +179,7 @@ public class TypeMap { } public int[] getTypes() { - Integer[] a = (Integer[]) typeSet.toArray(integerArray); + Integer[] a = typeSet.toArray(integerArray); int[] res = new int[a.length]; for (int i = 0; i < res.length; i++) { @@ -189,8 +189,8 @@ public class TypeMap { return res; } - public static int[] fromWireToTypes(byte[] wire_fmt) { - return TypeMap.fromBytes(wire_fmt).getTypes(); + public static int[] fromWireToTypes(byte[] wireFmt) { + return TypeMap.fromBytes(wireFmt).getTypes(); } public static byte[] fromTypesToWire(int[] types) { diff --git a/src/main/java/com/verisignlabs/dnssec/security/ZoneUtils.java b/src/main/java/com/verisignlabs/dnssec/security/ZoneUtils.java index 209c27d..5729197 100644 --- a/src/main/java/com/verisignlabs/dnssec/security/ZoneUtils.java +++ b/src/main/java/com/verisignlabs/dnssec/security/ZoneUtils.java @@ -39,6 +39,10 @@ import org.xbill.DNS.Type; */ public class ZoneUtils { + + private ZoneUtils() { + } + /** * Load a zone file. * @@ -53,19 +57,10 @@ public class ZoneUtils { * if something goes wrong reading the zone file. */ public static List readZoneFile(String zonefile, Name origin) throws IOException { - ArrayList records = new ArrayList(); - Master m; - try { - if (zonefile.equals("-")) { - m = new Master(System.in); - } else { - m = new Master(zonefile, origin); - } - + ArrayList records = new ArrayList<>(); + try (Master m = zonefile.equals("-") ? new Master(System.in) : new Master(zonefile, origin)) { Record r = null; - while ((r = m.nextRecord()) != null) { - records.add(r); } } catch (IOException e) { @@ -120,7 +115,7 @@ public class ZoneUtils { } public static List findRRs(List records, Name name, int type) { - List res = new ArrayList(); + List res = new ArrayList<>(); for (Record r : records) { if (r.getName().equals(name) && r.getType() == type) { res.add(r); diff --git a/src/main/java/com/verisignlabs/dnssec/security/ZoneVerifier.java b/src/main/java/com/verisignlabs/dnssec/security/ZoneVerifier.java index be2ab22..d7eaa9b 100644 --- a/src/main/java/com/verisignlabs/dnssec/security/ZoneVerifier.java +++ b/src/main/java/com/verisignlabs/dnssec/security/ZoneVerifier.java @@ -88,10 +88,12 @@ public class ZoneVerifier { public boolean equals(Object o) { return super.equals(o); } + @Override public int hashCode() { return super.hashCode(); } + boolean getMark() { return mIsMarked; } @@ -148,7 +150,8 @@ public class ZoneVerifier { /** * Add a record to the various maps. * - * @return true if the RR was added, false if it wasn't (because it was a duplicate) + * @return true if the RR was added, false if it wasn't (because it was a + * duplicate) */ private boolean addRR(Record r) { Name n = r.getName(); @@ -206,7 +209,7 @@ public class ZoneVerifier { * Given an unsorted list of records, load the node and rrset maps, as well as * determine the NSEC3 parameters and signing type. * - * @param records + * @param records an unsorted list of {@link org.xbill.DNS.Record} objects. * @return the number of errors encountered. */ private int calculateNodes(List records) { @@ -251,7 +254,7 @@ public class ZoneVerifier { * Given a name, typeset, and name of the last zone cut, determine the node * type. */ - private NodeType determineNodeType(Name n, Set typeset, Name last_cut) { + private NodeType determineNodeType(Name n, Set typeset, Name lastCut) { // All RRs at the zone apex are normal if (n.equals(mZoneName)) return NodeType.NORMAL; @@ -263,7 +266,7 @@ public class ZoneVerifier { } // If the node is below a zone cut (either a delegation or DNAME), it is // glue. - if (last_cut != null && n.subdomain(last_cut) && !n.equals(last_cut)) { + if (lastCut != null && n.subdomain(lastCut) && !n.equals(lastCut)) { return NodeType.GLUE; } @@ -294,13 +297,13 @@ public class ZoneVerifier { */ private int processNodes() throws NoSuchAlgorithmException, TextParseException { int errors = 0; - Name last_cut = null; + Name lastCut = null; for (Map.Entry> entry : mNodeMap.entrySet()) { Name n = entry.getKey(); Set typeset = entry.getValue(); - NodeType ntype = determineNodeType(n, typeset, last_cut); + NodeType ntype = determineNodeType(n, typeset, lastCut); log.finest("Node " + n + " is type " + ntype); // we can ignore glue/invalid RRs. @@ -309,7 +312,7 @@ public class ZoneVerifier { // record the last zone cut if this node is a zone cut. if (ntype == NodeType.DELEGATION || typeset.contains(Type.DNAME)) { - last_cut = n; + lastCut = n; } // check all of the RRsets that should be signed