EdDSA, sonarlint fixes, and cleanup (#16)
* update commons-cli, dnsjava, remove gradle, set to java 17 * use baseAlgorithm enum instead of static ints * sonarlint changes * sonarlint/formatting for SignUtils * sonarlint, formatting for RecordComparitor and JCEDnsSecSigner * update a few defaults * redo the SignZone logic around finding keys; more output for it. * refactor getVerifier() * sonarlint and formatting for the rest * use SunEC for the algs 15, 16; support alg 16 finally * address my self-review comments
This commit is contained in:
parent
6118ae718e
commit
2876649a4e
6
.gitattributes
vendored
6
.gitattributes
vendored
@ -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
|
|
||||||
|
|
25
build.gradle
25
build.gradle
@ -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')
|
|
||||||
}
|
|
@ -1,3 +1,3 @@
|
|||||||
#build.compiler=jikes
|
|
||||||
#build.compiler=modern
|
|
||||||
build.deprecation=true
|
build.deprecation=true
|
||||||
|
build.debug=false
|
||||||
|
build.java_version=17
|
||||||
|
10
build.xml
10
build.xml
@ -44,11 +44,11 @@
|
|||||||
<javac srcdir="${build.src}"
|
<javac srcdir="${build.src}"
|
||||||
destdir="${build.dest}"
|
destdir="${build.dest}"
|
||||||
classpathref="project.classpath"
|
classpathref="project.classpath"
|
||||||
deprecation="true"
|
deprecation="${build.deprecation}"
|
||||||
includeantruntime="false"
|
includeantruntime="false"
|
||||||
includes="com/verisignlabs/dnssec/"
|
includes="com/verisignlabs/dnssec/"
|
||||||
source="17"
|
debug="${build.debug}"
|
||||||
target="17" />
|
release="${build.java_version}" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="sectools-jar" depends="usage,sectools">
|
<target name="sectools-jar" depends="usage,sectools">
|
||||||
@ -154,13 +154,11 @@
|
|||||||
|
|
||||||
|
|
||||||
<target name="dist" depends="sectools-dist">
|
<target name="dist" depends="sectools-dist">
|
||||||
<echo message="do not forget to tag the release:" />
|
|
||||||
<echo message=" svn-tag ${version}" />
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="usage">
|
<target name="usage">
|
||||||
<echo message=" " />
|
<echo message=" " />
|
||||||
<echo message="SECTOOLS v. ${version} Build System" />
|
<echo message="jdnssec-tools v. ${version} Build System" />
|
||||||
<echo message="--------------------------------" />
|
<echo message="--------------------------------" />
|
||||||
<echo message="Available Targets:" />
|
<echo message="Available Targets:" />
|
||||||
<echo message=" compile (default) - compiles the source code, creates jar" />
|
<echo message=" compile (default) - compiles the source code, creates jar" />
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
5
gradle/wrapper/gradle-wrapper.properties
vendored
@ -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
|
|
185
gradlew
vendored
185
gradlew
vendored
@ -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" "$@"
|
|
89
gradlew.bat
vendored
89
gradlew.bat
vendored
@ -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
|
|
Binary file not shown.
BIN
lib/commons-cli-1.6.0.jar
Normal file
BIN
lib/commons-cli-1.6.0.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -56,7 +56,7 @@ public class DSTool extends CLBase {
|
|||||||
public dsType createType = dsType.DS;
|
public dsType createType = dsType.DS;
|
||||||
public String outputfile = null;
|
public String outputfile = null;
|
||||||
public String keyname = null;
|
public String keyname = null;
|
||||||
public int digestId = DNSSEC.Digest.SHA1;
|
public int digestId = DNSSEC.Digest.SHA256;
|
||||||
|
|
||||||
public CLIState() {
|
public CLIState() {
|
||||||
super("jdnssec-dstool [..options..] keyfile");
|
super("jdnssec-dstool [..options..] keyfile");
|
||||||
@ -71,7 +71,8 @@ public class DSTool extends CLBase {
|
|||||||
protected void setupOptions(Options opts) {
|
protected void setupOptions(Options opts) {
|
||||||
opts.addOption(Option.builder("D").longOpt("dlv").desc("Generate a DLV record instead.").build());
|
opts.addOption(Option.builder("D").longOpt("dlv").desc("Generate a DLV record instead.").build());
|
||||||
opts.addOption(Option.builder("C").longOpt("cds").desc("Generate a CDS record instead").build());
|
opts.addOption(Option.builder("C").longOpt("cds").desc("Generate a CDS record instead").build());
|
||||||
opts.addOption(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());
|
opts.addOption(Option.builder("f").hasArg().argName("file").longOpt("output").desc("output to file").build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ public class KeyGen extends CLBase {
|
|||||||
* state.
|
* state.
|
||||||
*/
|
*/
|
||||||
protected static class CLIState extends CLIStateBase {
|
protected static class CLIState extends CLIStateBase {
|
||||||
public int algorithm = 8;
|
public int algorithm = 13;
|
||||||
public int keylength = 1024;
|
public int keylength = 2048;
|
||||||
public boolean useLargeE = true;
|
public boolean useLargeE = true;
|
||||||
public String outputfile = null;
|
public String outputfile = null;
|
||||||
public File keydir = null;
|
public File keydir = null;
|
||||||
@ -77,10 +77,10 @@ public class KeyGen extends CLBase {
|
|||||||
String[] algStrings = DnsKeyAlgorithm.getInstance().supportedAlgMnemonics();
|
String[] algStrings = DnsKeyAlgorithm.getInstance().supportedAlgMnemonics();
|
||||||
String algStringSet = String.join(" | ", algStrings);
|
String algStringSet = String.join(" | ", algStrings);
|
||||||
opts.addOption(Option.builder("a").hasArg().argName("algorithm")
|
opts.addOption(Option.builder("a").hasArg().argName("algorithm")
|
||||||
.desc(algStringSet + " | alias, RSASHA256 is default.").build());
|
.desc(algStringSet + " | alias, ECDSAP256SHA256 is default.").build());
|
||||||
|
|
||||||
opts.addOption(Option.builder("b").hasArg().argName("size").desc(
|
opts.addOption(Option.builder("b").hasArg().argName("size").desc(
|
||||||
"key size, in bits (default 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());
|
.build());
|
||||||
opts.addOption(Option.builder("f").hasArg().argName("file").longOpt("output-file")
|
opts.addOption(Option.builder("f").hasArg().argName("file").longOpt("output-file")
|
||||||
.desc("base filename from the public/private key files").build());
|
.desc("base filename from the public/private key files").build());
|
||||||
|
@ -84,13 +84,13 @@ public class KeyInfoTool extends CLBase {
|
|||||||
+ " (" + dnskey.getAlgorithm() + ")");
|
+ " (" + dnskey.getAlgorithm() + ")");
|
||||||
System.out.println("ID: " + dnskey.getFootprint());
|
System.out.println("ID: " + dnskey.getFootprint());
|
||||||
System.out.println("KeyFileBase: " + BINDKeyUtils.keyFileBase(key));
|
System.out.println("KeyFileBase: " + BINDKeyUtils.keyFileBase(key));
|
||||||
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();
|
RSAPublicKey pub = (RSAPublicKey) key.getPublic();
|
||||||
System.out.println("RSA Public Exponent: " + pub.getPublicExponent());
|
System.out.println("RSA Public Exponent: " + pub.getPublicExponent());
|
||||||
System.out.println("RSA Modulus: " + pub.getModulus());
|
System.out.println("RSA Modulus: " + pub.getModulus());
|
||||||
} else if (basetype == DnsKeyAlgorithm.DSA) {
|
} else if (basetype == DnsKeyAlgorithm.BaseAlgorithm.DSA) {
|
||||||
DSAPublicKey pub = (DSAPublicKey) key.getPublic();
|
DSAPublicKey pub = (DSAPublicKey) key.getPublic();
|
||||||
System.out.println("DSA base (G): " + pub.getParams().getG());
|
System.out.println("DSA base (G): " + pub.getParams().getG());
|
||||||
System.out.println("DSA prime (P): " + pub.getParams().getP());
|
System.out.println("DSA prime (P): " + pub.getParams().getP());
|
||||||
|
@ -75,10 +75,14 @@ public class SignKeyset extends CLBase {
|
|||||||
opts.addOption("a", "verify", false, "verify generated signatures>");
|
opts.addOption("a", "verify", false, "verify generated signatures>");
|
||||||
|
|
||||||
// Argument options
|
// Argument options
|
||||||
opts.addOption(Option.builder("D").hasArg().argName("dir").longOpt("key-directory").desc("directory where key files are found (default '.').").build());
|
opts.addOption(Option.builder("D").hasArg().argName("dir").longOpt("key-directory")
|
||||||
opts.addOption(Option.builder("s").hasArg().argName("time/offset").longOpt("start-time").desc("signature starting time (default is now - 1 hour)").build());
|
.desc("directory where key files are found (default '.').").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("s").hasArg().argName("time/offset").longOpt("start-time")
|
||||||
opts.addOption(Option.builder("f").hasArg().argName("outfile").desc("file the signed keyset is written to").build());
|
.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
|
@Override
|
||||||
@ -130,10 +134,8 @@ public class SignKeyset extends CLBase {
|
|||||||
/**
|
/**
|
||||||
* Verify the generated signatures.
|
* Verify the generated signatures.
|
||||||
*
|
*
|
||||||
* @param records
|
* @param records a list of {@link org.xbill.DNS.Record}s.
|
||||||
* a list of {@link org.xbill.DNS.Record}s.
|
* @param keypairs a list of keypairs used the sign the zone.
|
||||||
* @param keypairs
|
|
||||||
* a list of keypairs used the sign the zone.
|
|
||||||
* @return true if all of the signatures validated.
|
* @return true if all of the signatures validated.
|
||||||
*/
|
*/
|
||||||
private static boolean verifySigs(List<Record> records,
|
private static boolean verifySigs(List<Record> records,
|
||||||
@ -169,15 +171,12 @@ public class SignKeyset extends CLBase {
|
|||||||
/**
|
/**
|
||||||
* Load the key pairs from the key files.
|
* Load the key pairs from the key files.
|
||||||
*
|
*
|
||||||
* @param keyfiles
|
* @param keyfiles a string array containing the base names or paths of the
|
||||||
* a string array containing the base names or paths of the
|
* keys to be loaded.
|
||||||
* keys
|
* @param startIndex the starting index of keyfiles string array to use. This
|
||||||
* to be loaded.
|
* allows us to use the straight command line argument
|
||||||
* @param startIndex
|
* array.
|
||||||
* the starting index of keyfiles string array to use. This
|
* @param inDirectory the directory to look in (may be null).
|
||||||
* allows us to use the straight command line argument array.
|
|
||||||
* @param inDirectory
|
|
||||||
* the directory to look in (may be null).
|
|
||||||
* @return a list of keypair objects.
|
* @return a list of keypair objects.
|
||||||
*/
|
*/
|
||||||
private static List<DnsKeyPair> getKeys(String[] keyfiles, int startIndex,
|
private static List<DnsKeyPair> getKeys(String[] keyfiles, int startIndex,
|
||||||
|
@ -137,10 +137,8 @@ public class SignRRset extends CLBase {
|
|||||||
/**
|
/**
|
||||||
* Verify the generated signatures.
|
* Verify the generated signatures.
|
||||||
*
|
*
|
||||||
* @param records
|
* @param records a list of {@link org.xbill.DNS.Record}s.
|
||||||
* a list of {@link org.xbill.DNS.Record}s.
|
* @param keypairs a list of keypairs used the sign the zone.
|
||||||
* @param keypairs
|
|
||||||
* a list of keypairs used the sign the zone.
|
|
||||||
* @return true if all of the signatures validated.
|
* @return true if all of the signatures validated.
|
||||||
*/
|
*/
|
||||||
private static boolean verifySigs(List<Record> records, List<DnsKeyPair> keypairs) {
|
private static boolean verifySigs(List<Record> records, List<DnsKeyPair> keypairs) {
|
||||||
@ -176,15 +174,12 @@ public class SignRRset extends CLBase {
|
|||||||
/**
|
/**
|
||||||
* Load the key pairs from the key files.
|
* Load the key pairs from the key files.
|
||||||
*
|
*
|
||||||
* @param keyfiles
|
* @param keyfiles a string array containing the base names or paths of the
|
||||||
* a string array containing the base names or paths of the
|
* keys to be loaded.
|
||||||
* keys
|
* @param startIndex the starting index of keyfiles string array to use. This
|
||||||
* to be loaded.
|
* allows us to use the straight command line argument
|
||||||
* @param startIndex
|
* array.
|
||||||
* the starting index of keyfiles string array to use. This
|
* @param inDirectory the directory to look in (may be null).
|
||||||
* allows us to use the straight command line argument array.
|
|
||||||
* @param inDirectory
|
|
||||||
* the directory to look in (may be null).
|
|
||||||
* @return a list of keypair objects.
|
* @return a list of keypair objects.
|
||||||
*/
|
*/
|
||||||
private static List<DnsKeyPair> getKeys(String[] keyfiles, int startIndex,
|
private static List<DnsKeyPair> getKeys(String[] keyfiles, int startIndex,
|
||||||
|
@ -79,6 +79,8 @@ public class SignZone extends CLBase {
|
|||||||
public long nsec3paramttl = -1;
|
public long nsec3paramttl = -1;
|
||||||
public boolean verboseSigning = false;
|
public boolean verboseSigning = false;
|
||||||
|
|
||||||
|
private static final Random rand = new Random();
|
||||||
|
|
||||||
public CLIState() {
|
public CLIState() {
|
||||||
super("jdnssec-signzone [..options..] zone_file [key_file ...]");
|
super("jdnssec-signzone [..options..] zone_file [key_file ...]");
|
||||||
}
|
}
|
||||||
@ -198,9 +200,8 @@ public class SignZone extends CLBase {
|
|||||||
if ((optstr = cli.getOptionValue('R')) != null) {
|
if ((optstr = cli.getOptionValue('R')) != null) {
|
||||||
int length = parseInt(optstr, 0);
|
int length = parseInt(optstr, 0);
|
||||||
if (length > 0 && length <= 255) {
|
if (length > 0 && length <= 255) {
|
||||||
Random random = new Random();
|
|
||||||
salt = new byte[length];
|
salt = new byte[length];
|
||||||
random.nextBytes(salt);
|
rand.nextBytes(salt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,8 +242,8 @@ public class SignZone extends CLBase {
|
|||||||
/**
|
/**
|
||||||
* Load a list of DNS names from a file.
|
* Load a list of DNS names from a file.
|
||||||
*
|
*
|
||||||
* @param nameListFile
|
* @param nameListFile the path of a file containing a bare list of DNS
|
||||||
* the path of a file containing a bare list of DNS names.
|
* names.
|
||||||
* @return a list of {@link org.xbill.DNS.Name} objects.
|
* @return a list of {@link org.xbill.DNS.Name} objects.
|
||||||
*/
|
*/
|
||||||
private static List<Name> getNameList(File nameListFile) throws IOException {
|
private static List<Name> getNameList(File nameListFile) throws IOException {
|
||||||
@ -254,9 +255,6 @@ public class SignZone extends CLBase {
|
|||||||
try {
|
try {
|
||||||
Name n = Name.fromString(line);
|
Name n = Name.fromString(line);
|
||||||
// force the name to be absolute.
|
// force the name to be absolute.
|
||||||
// FIXME: we should probably get some fancy logic here to
|
|
||||||
// detect if the name needs the origin appended, or just the
|
|
||||||
// root.
|
|
||||||
if (!n.isAbsolute())
|
if (!n.isAbsolute())
|
||||||
n = Name.concatenate(n, Name.root);
|
n = Name.concatenate(n, Name.root);
|
||||||
|
|
||||||
@ -274,14 +272,12 @@ public class SignZone extends CLBase {
|
|||||||
/**
|
/**
|
||||||
* Verify the generated signatures.
|
* Verify the generated signatures.
|
||||||
*
|
*
|
||||||
* @param records
|
* @param records a list of {@link org.xbill.DNS.Record}s.
|
||||||
* a list of {@link org.xbill.DNS.Record}s.
|
* @param keypairs a list of keypairs used the sign the zone.
|
||||||
* @param keypairs
|
|
||||||
* a list of keypairs used the sign the zone.
|
|
||||||
* @return true if all of the signatures validated.
|
* @return true if all of the signatures validated.
|
||||||
*/
|
*/
|
||||||
private static boolean verifyZoneSigs(List<Record> records,
|
private static boolean verifyZoneSigs(List<Record> records,
|
||||||
List<DnsKeyPair> keypairs) {
|
List<DnsKeyPair> keypairs, List<DnsKeyPair> kskpairs) {
|
||||||
boolean secure = true;
|
boolean secure = true;
|
||||||
|
|
||||||
DnsSecVerifier verifier = new DnsSecVerifier();
|
DnsSecVerifier verifier = new DnsSecVerifier();
|
||||||
@ -289,7 +285,9 @@ public class SignZone extends CLBase {
|
|||||||
for (DnsKeyPair pair : keypairs) {
|
for (DnsKeyPair pair : keypairs) {
|
||||||
verifier.addTrustedKey(pair);
|
verifier.addTrustedKey(pair);
|
||||||
}
|
}
|
||||||
|
for (DnsKeyPair pair : kskpairs) {
|
||||||
|
verifier.addTrustedKey(pair);
|
||||||
|
}
|
||||||
verifier.setVerifyAllSigs(true);
|
verifier.setVerifyAllSigs(true);
|
||||||
|
|
||||||
List<RRset> rrsets = SignUtils.assembleIntoRRsets(records);
|
List<RRset> rrsets = SignUtils.assembleIntoRRsets(records);
|
||||||
@ -303,6 +301,7 @@ public class SignZone extends CLBase {
|
|||||||
boolean result = verifier.verify(rrset);
|
boolean result = verifier.verify(rrset);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
System.err.println("Signatures did not verify for RRset: " + rrset);
|
||||||
staticLog.fine("Signatures did not verify for RRset: " + rrset);
|
staticLog.fine("Signatures did not verify for RRset: " + rrset);
|
||||||
secure = false;
|
secure = false;
|
||||||
}
|
}
|
||||||
@ -314,17 +313,12 @@ public class SignZone extends CLBase {
|
|||||||
/**
|
/**
|
||||||
* Load the key pairs from the key files.
|
* Load the key pairs from the key files.
|
||||||
*
|
*
|
||||||
* @param keyfiles
|
* @param keyfiles a string array containing the base names or paths of the
|
||||||
* a string array containing the base names or paths of the
|
* keys to be loaded.
|
||||||
* keys to
|
* @param startIndex the starting index of keyfiles string array to use. This
|
||||||
* be loaded.
|
* allows us to use the straight command line argument
|
||||||
* @param startIndex
|
* array.
|
||||||
* the starting index of keyfiles string array to use. This
|
* @param inDirectory the directory to look in (may be null).
|
||||||
* allows
|
|
||||||
* us
|
|
||||||
* to use the straight command line argument array.
|
|
||||||
* @param inDirectory
|
|
||||||
* the directory to look in (may be null).
|
|
||||||
* @return a list of keypair objects.
|
* @return a list of keypair objects.
|
||||||
*/
|
*/
|
||||||
private static List<DnsKeyPair> getKeys(String[] keyfiles, int startIndex,
|
private static List<DnsKeyPair> getKeys(String[] keyfiles, int startIndex,
|
||||||
@ -418,19 +412,12 @@ public class SignZone extends CLBase {
|
|||||||
/**
|
/**
|
||||||
* Load keysets (which contain delegation point security info).
|
* Load keysets (which contain delegation point security info).
|
||||||
*
|
*
|
||||||
* @param inDirectory
|
* @param inDirectory the directory to look for the keyset files (may be null,
|
||||||
* the directory to look for the keyset files (may be null,
|
* in which case it defaults to looking in the current
|
||||||
* in
|
* working directory).
|
||||||
* which
|
* @param zonename the name of the zone we are signing, so we can ignore
|
||||||
* case it defaults to looking in the current working
|
* keysets that do not belong in the zone.
|
||||||
* directory).
|
* @return a list of {@link org.xbill.DNS.Record}s found in the keyset files.
|
||||||
* @param zonename
|
|
||||||
* the name of the zone we are signing, so we can ignore
|
|
||||||
* keysets
|
|
||||||
* that
|
|
||||||
* do not belong in the zone.
|
|
||||||
* @return a list of {@link org.xbill.DNS.Record}s found in the keyset
|
|
||||||
* files.
|
|
||||||
*/
|
*/
|
||||||
private static List<Record> getKeysets(File inDirectory, Name zonename)
|
private static List<Record> getKeysets(File inDirectory, Name zonename)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
@ -463,13 +450,9 @@ public class SignZone extends CLBase {
|
|||||||
/**
|
/**
|
||||||
* Determine if the given keypairs can be used to sign the zone.
|
* Determine if the given keypairs can be used to sign the zone.
|
||||||
*
|
*
|
||||||
* @param zonename
|
* @param zonename the zone origin.
|
||||||
* the zone origin.
|
* @param keypairs a list of {@link DnsKeyPair} objects that will be used to
|
||||||
* @param keypairs
|
* sign the zone.
|
||||||
* a list of {@link DnsKeyPair} objects that will be used to
|
|
||||||
* sign
|
|
||||||
* the
|
|
||||||
* zone.
|
|
||||||
* @return true if the keypairs valid.
|
* @return true if the keypairs valid.
|
||||||
*/
|
*/
|
||||||
private static boolean keyPairsValidForZone(Name zonename, List<DnsKeyPair> keypairs) {
|
private static boolean keyPairsValidForZone(Name zonename, List<DnsKeyPair> keypairs) {
|
||||||
@ -503,55 +486,71 @@ public class SignZone extends CLBase {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the key pairs.
|
// Load the key pairs. Note that getKeys() always returns an ArrayList,
|
||||||
|
// which may be empty.
|
||||||
List<DnsKeyPair> keypairs = getKeys(state.keyFiles, 0, state.keyDirectory);
|
List<DnsKeyPair> keypairs = getKeys(state.keyFiles, 0, state.keyDirectory);
|
||||||
List<DnsKeyPair> kskpairs = getKeys(state.kskFiles, 0, state.keyDirectory);
|
List<DnsKeyPair> kskpairs = getKeys(state.kskFiles, 0, state.keyDirectory);
|
||||||
|
|
||||||
// If we didn't get any keys on the command line, look at the zone apex for
|
// If we didn't get any keys on the command line, look at the zone apex for
|
||||||
// any public keys.
|
// any public keys.
|
||||||
if (keypairs == null && kskpairs == null) {
|
if (keypairs.isEmpty()) {
|
||||||
List<Record> dnskeys = ZoneUtils.findRRs(records, zonename, Type.DNSKEY);
|
List<Record> dnskeys = ZoneUtils.findRRs(records, zonename, Type.DNSKEY);
|
||||||
keypairs = getKeys(dnskeys, state.keyDirectory);
|
keypairs = getKeys(dnskeys, state.keyDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we *still* don't have any key pairs, look for keys the key directory
|
// If we *still* don't have any key pairs, look for keys the key directory
|
||||||
// that match
|
// that match
|
||||||
if (keypairs == null && kskpairs == null) {
|
if (keypairs.isEmpty()) {
|
||||||
keypairs = findZoneKeys(state.keyDirectory, zonename);
|
keypairs = findZoneKeys(state.keyDirectory, zonename);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we don't have any KSKs, but we do have more than one zone
|
// If we don't have any KSKs, but we do have more than one zone
|
||||||
// signing key (presumably), presume that the zone signing keys
|
// signing key (presumably), presume that the zone signing keys
|
||||||
// are just not differentiated and try to figure out which keys
|
// are just not differentiated and try to figure out which keys
|
||||||
// are actually ksks by looking at the SEP flag.
|
// are actually KSKs by looking at the SEP flag.
|
||||||
if ((kskpairs == null || kskpairs.isEmpty()) && keypairs != null
|
if (kskpairs.isEmpty() && !keypairs.isEmpty()) {
|
||||||
&& keypairs.size() > 1) {
|
|
||||||
for (Iterator<DnsKeyPair> i = keypairs.iterator(); i.hasNext();) {
|
for (Iterator<DnsKeyPair> i = keypairs.iterator(); i.hasNext();) {
|
||||||
DnsKeyPair pair = i.next();
|
DnsKeyPair pair = i.next();
|
||||||
DNSKEYRecord kr = pair.getDNSKEYRecord();
|
DNSKEYRecord kr = pair.getDNSKEYRecord();
|
||||||
if ((kr.getFlags() & DNSKEYRecord.Flags.SEP_KEY) != 0) {
|
if ((kr.getFlags() & DNSKEYRecord.Flags.SEP_KEY) != 0) {
|
||||||
if (kskpairs == null)
|
|
||||||
kskpairs = new ArrayList<>();
|
|
||||||
kskpairs.add(pair);
|
kskpairs.add(pair);
|
||||||
i.remove();
|
i.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are no ZSKs defined at this point (yet there are KSKs
|
// If we have zero keypairs at all, we are stuck.
|
||||||
// provided), all KSKs will be treated as ZSKs, as well.
|
if (keypairs.isEmpty() && kskpairs.isEmpty()) {
|
||||||
if (keypairs == null || keypairs.isEmpty()) {
|
|
||||||
keypairs = kskpairs;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there *still* aren't any ZSKs defined, bail.
|
|
||||||
if (keypairs == null || keypairs.isEmpty()) {
|
|
||||||
System.err.println("No zone signing keys could be determined.");
|
System.err.println("No zone signing keys could be determined.");
|
||||||
state.usage();
|
state.usage();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we only have one type of key (all ZSKs or all KSKs), then these are
|
||||||
|
// "CSKs" -- Combined signing keys, so assign one set to the other.
|
||||||
|
if (keypairs.isEmpty()) {
|
||||||
|
keypairs = kskpairs;
|
||||||
|
} else if (kskpairs.isEmpty()) {
|
||||||
|
kskpairs = keypairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output what keys we are using for what
|
||||||
|
if (keypairs == kskpairs) {
|
||||||
|
System.out.println("CSKs: ");
|
||||||
|
for (DnsKeyPair kp : keypairs) {
|
||||||
|
System.out.println(" - " + kp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("KSKs: ");
|
||||||
|
for (DnsKeyPair kp : kskpairs) {
|
||||||
|
System.out.println(" - " + kp);
|
||||||
|
}
|
||||||
|
System.out.println("ZSKs: ");
|
||||||
|
for (DnsKeyPair kp : keypairs) {
|
||||||
|
System.out.println(" - " + kp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// default the output file, if not set.
|
// default the output file, if not set.
|
||||||
if (state.outputfile == null && !state.zonefile.equals("-")) {
|
if (state.outputfile == null && !state.zonefile.equals("-")) {
|
||||||
if (zonename.isAbsolute()) {
|
if (zonename.isAbsolute()) {
|
||||||
@ -571,12 +570,12 @@ public class SignZone extends CLBase {
|
|||||||
// We force the signing keys to be in the zone by just appending
|
// We force the signing keys to be in the zone by just appending
|
||||||
// them to the zone here. Currently JCEDnsSecSigner.signZone
|
// them to the zone here. Currently JCEDnsSecSigner.signZone
|
||||||
// removes duplicate records.
|
// removes duplicate records.
|
||||||
if (kskpairs != null) {
|
if (!kskpairs.isEmpty()) {
|
||||||
for (DnsKeyPair pair : kskpairs) {
|
for (DnsKeyPair pair : kskpairs) {
|
||||||
records.add(pair.getDNSKEYRecord());
|
records.add(pair.getDNSKEYRecord());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (keypairs != null) {
|
if (!keypairs.isEmpty()) {
|
||||||
for (DnsKeyPair pair : keypairs) {
|
for (DnsKeyPair pair : keypairs) {
|
||||||
records.add(pair.getDNSKEYRecord());
|
records.add(pair.getDNSKEYRecord());
|
||||||
}
|
}
|
||||||
@ -608,15 +607,11 @@ public class SignZone extends CLBase {
|
|||||||
|
|
||||||
// write out the signed zone
|
// write out the signed zone
|
||||||
ZoneUtils.writeZoneFile(signedRecords, state.outputfile);
|
ZoneUtils.writeZoneFile(signedRecords, state.outputfile);
|
||||||
|
System.out.println("zone signing complete");
|
||||||
|
|
||||||
if (state.verifySigs) {
|
if (state.verifySigs) {
|
||||||
// FIXME: ugh.
|
|
||||||
if (kskpairs != null) {
|
|
||||||
keypairs.addAll(kskpairs);
|
|
||||||
}
|
|
||||||
|
|
||||||
log.fine("verifying generated signatures");
|
log.fine("verifying generated signatures");
|
||||||
boolean res = verifyZoneSigs(signedRecords, keypairs);
|
boolean res = verifyZoneSigs(signedRecords, keypairs, kskpairs);
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
System.out.println("Generated signatures verified");
|
System.out.println("Generated signatures verified");
|
||||||
@ -624,7 +619,6 @@ public class SignZone extends CLBase {
|
|||||||
System.out.println("Generated signatures did not verify.");
|
System.out.println("Generated signatures did not verify.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
@ -100,7 +100,6 @@ public class ZoneFormat extends CLBase {
|
|||||||
|
|
||||||
private static void formatZone(List<Record> zone) {
|
private static void formatZone(List<Record> zone) {
|
||||||
|
|
||||||
|
|
||||||
for (Record r : zone) {
|
for (Record r : zone) {
|
||||||
System.out.println(r.toString());
|
System.out.println(r.toString());
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,8 @@ import org.xbill.DNS.utils.base64;
|
|||||||
*/
|
*/
|
||||||
public class BINDKeyUtils {
|
public class BINDKeyUtils {
|
||||||
|
|
||||||
private BINDKeyUtils() { }
|
private BINDKeyUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the BIND9 key file base name (i.e., without the ".key" or
|
* Calculate the BIND9 key file base name (i.e., without the ".key" or
|
||||||
@ -60,8 +61,7 @@ public class BINDKeyUtils {
|
|||||||
/** Reads in the DNSKEYRecord from the public key file */
|
/** Reads in the DNSKEYRecord from the public key file */
|
||||||
private static DNSKEYRecord loadPublicKeyFile(File publicKeyFile)
|
private static DNSKEYRecord loadPublicKeyFile(File publicKeyFile)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
Master m = new Master(publicKeyFile.getAbsolutePath(), null, 600);
|
try (Master m = new Master(publicKeyFile.getAbsolutePath(), null, 600)) {
|
||||||
|
|
||||||
Record r;
|
Record r;
|
||||||
DNSKEYRecord result = null;
|
DNSKEYRecord result = null;
|
||||||
|
|
||||||
@ -73,6 +73,7 @@ public class BINDKeyUtils {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Reads in the private key verbatim from the private key file */
|
/** Reads in the private key verbatim from the private key file */
|
||||||
private static String loadPrivateKeyFile(File privateKeyFile)
|
private static String loadPrivateKeyFile(File privateKeyFile)
|
||||||
@ -106,17 +107,12 @@ public class BINDKeyUtils {
|
|||||||
* Given the information necessary to construct the path to a BIND9 generated
|
* Given the information necessary to construct the path to a BIND9 generated
|
||||||
* key pair, load the key pair.
|
* key pair, load the key pair.
|
||||||
*
|
*
|
||||||
* @param signer
|
* @param signer the DNS name of the key.
|
||||||
* the DNS name of the key.
|
* @param algorithm the DNSSEC algorithm of the key.
|
||||||
* @param algorithm
|
* @param keyid the DNSSEC key footprint.
|
||||||
* the DNSSEC algorithm of the key.
|
* @param inDirectory the directory to look for the files (may be null).
|
||||||
* @param keyid
|
|
||||||
* the DNSSEC key footprint.
|
|
||||||
* @param inDirectory
|
|
||||||
* the directory to look for the files (may be null).
|
|
||||||
* @return the loaded key pair.
|
* @return the loaded key pair.
|
||||||
* @throws IOException
|
* @throws IOException if there was a problem reading the BIND9 files.
|
||||||
* if there was a problem reading the BIND9 files.
|
|
||||||
*/
|
*/
|
||||||
public static DnsKeyPair loadKeyPair(Name signer, int algorithm, int keyid,
|
public static DnsKeyPair loadKeyPair(Name signer, int algorithm, int keyid,
|
||||||
File inDirectory) throws IOException {
|
File inDirectory) throws IOException {
|
||||||
@ -128,16 +124,12 @@ public class BINDKeyUtils {
|
|||||||
/**
|
/**
|
||||||
* Given a base path to a BIND9 key pair, load the key pair.
|
* Given a base path to a BIND9 key pair, load the key pair.
|
||||||
*
|
*
|
||||||
* @param keyFileBasePath
|
* @param keyFileBasePath the base filename (or real filename for either the
|
||||||
* the base filename (or real filename for either the
|
* public or private key) of the key.
|
||||||
* public or
|
* @param inDirectory the directory to look in, if the keyFileBasePath is
|
||||||
* private key) of the key.
|
|
||||||
* @param inDirectory
|
|
||||||
* the directory to look in, if the keyFileBasePath is
|
|
||||||
* relative.
|
* relative.
|
||||||
* @return the loaded key pair.
|
* @return the loaded key pair.
|
||||||
* @throws IOException
|
* @throws IOException if there was a problem reading the files
|
||||||
* if there was a problem reading the files
|
|
||||||
*/
|
*/
|
||||||
public static DnsKeyPair loadKeyPair(String keyFileBasePath, File inDirectory)
|
public static DnsKeyPair loadKeyPair(String keyFileBasePath, File inDirectory)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
@ -162,15 +154,12 @@ public class BINDKeyUtils {
|
|||||||
* Given a base path to a BIND9 key pair, load the public part (only) of the
|
* Given a base path to a BIND9 key pair, load the public part (only) of the
|
||||||
* key pair
|
* key pair
|
||||||
*
|
*
|
||||||
* @param keyFileBasePath
|
* @param keyFileBasePath the base or real path to the public part of a key
|
||||||
* the base or real path to the public part of a key
|
|
||||||
* pair.
|
* pair.
|
||||||
* @param inDirectory
|
* @param inDirectory the directory to look in if the path is relative
|
||||||
* the directory to look in if the path is relative (may
|
* (may be null).
|
||||||
* be null).
|
|
||||||
* @return a {@link DnsKeyPair} containing just the public key information.
|
* @return a {@link DnsKeyPair} containing just the public key information.
|
||||||
* @throws IOException
|
* @throws IOException if there was a problem reading the public key file.
|
||||||
* if there was a problem reading the public key file.
|
|
||||||
*/
|
*/
|
||||||
public static DnsKeyPair loadKey(String keyFileBasePath, File inDirectory)
|
public static DnsKeyPair loadKey(String keyFileBasePath, File inDirectory)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
@ -190,15 +179,11 @@ public class BINDKeyUtils {
|
|||||||
* "keyset-[signer]." where [signer] is the DNS owner name of the key. The
|
* "keyset-[signer]." where [signer] is the DNS owner name of the key. The
|
||||||
* keyset may be signed, but doesn't have to be.
|
* keyset may be signed, but doesn't have to be.
|
||||||
*
|
*
|
||||||
* @param keysetFileName
|
* @param keysetFileName the name of the keyset file.
|
||||||
* the name of the keyset file.
|
* @param inDirectory the directory to look in if the path is relative (may
|
||||||
* @param inDirectory
|
* be null, defaults to the current working directory).
|
||||||
* the directory to look in if the path is relative (may
|
|
||||||
* be null,
|
|
||||||
* defaults to the current working directory).
|
|
||||||
* @return a RRset contain the KEY records and any associated SIG records.
|
* @return a RRset contain the KEY records and any associated SIG records.
|
||||||
* @throws IOException
|
* @throws IOException if there was a problem reading the keyset file.
|
||||||
* if there was a problem reading the keyset file.
|
|
||||||
*/
|
*/
|
||||||
public static RRset loadKeySet(String keysetFileName, File inDirectory)
|
public static RRset loadKeySet(String keysetFileName, File inDirectory)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
@ -218,8 +203,8 @@ public class BINDKeyUtils {
|
|||||||
/**
|
/**
|
||||||
* Calculate the key file base for this key pair.
|
* Calculate the key file base for this key pair.
|
||||||
*
|
*
|
||||||
* @param pair
|
* @param pair the {@link DnsKeyPair} to work from. It only needs a public
|
||||||
* the {@link DnsKeyPair} to work from. It only needs a public key.
|
* key.
|
||||||
* @return the base name of the key files.
|
* @return the base name of the key files.
|
||||||
*/
|
*/
|
||||||
public static String keyFileBase(DnsKeyPair pair) {
|
public static String keyFileBase(DnsKeyPair pair) {
|
||||||
@ -259,8 +244,7 @@ public class BINDKeyUtils {
|
|||||||
* Given a the contents of a BIND9 private key file, convert it into a native
|
* Given a the contents of a BIND9 private key file, convert it into a native
|
||||||
* {@link java.security.PrivateKey} object.
|
* {@link java.security.PrivateKey} object.
|
||||||
*
|
*
|
||||||
* @param privateKeyString
|
* @param privateKeyString the contents of a BIND9 key file in string form.
|
||||||
* the contents of a BIND9 key file in string form.
|
|
||||||
* @return a {@link java.security.PrivateKey}
|
* @return a {@link java.security.PrivateKey}
|
||||||
*/
|
*/
|
||||||
public static PrivateKey convertPrivateKeyString(String privateKeyString) {
|
public static PrivateKey convertPrivateKeyString(String privateKeyString) {
|
||||||
@ -283,10 +267,8 @@ public class BINDKeyUtils {
|
|||||||
* Given a native private key, convert it into a BIND9 private key file
|
* Given a native private key, convert it into a BIND9 private key file
|
||||||
* format.
|
* format.
|
||||||
*
|
*
|
||||||
* @param priv
|
* @param priv the private key to convert.
|
||||||
* the private key to convert.
|
* @param pub the private key's corresponding public key. Some algorithms
|
||||||
* @param pub
|
|
||||||
* the private key's corresponding public key. Some algorithms
|
|
||||||
* require information from both.
|
* require information from both.
|
||||||
* @return a string containing the contents of a BIND9 private key file.
|
* @return a string containing the contents of a BIND9 private key file.
|
||||||
*/
|
*/
|
||||||
@ -327,16 +309,11 @@ public class BINDKeyUtils {
|
|||||||
/**
|
/**
|
||||||
* This routine will write out the BIND9 dnssec-* tool compatible files.
|
* This routine will write out the BIND9 dnssec-* tool compatible files.
|
||||||
*
|
*
|
||||||
* @param baseFileName
|
* @param baseFileName use this base file name. If null, the standard BIND9
|
||||||
* use this base file name. If null, the standard BIND9 base
|
* base file name will be computed.
|
||||||
* file
|
* @param pair the keypair in question.
|
||||||
* name will be computed.
|
* @param inDirectory the directory to write to (may be null).
|
||||||
* @param pair
|
* @throws IOException if there is a problem writing the files.
|
||||||
* the keypair in question.
|
|
||||||
* @param inDirectory
|
|
||||||
* the directory to write to (may be null).
|
|
||||||
* @throws IOException
|
|
||||||
* if there is a problem writing the files.
|
|
||||||
*/
|
*/
|
||||||
public static void writeKeyFiles(String baseFileName, DnsKeyPair pair,
|
public static void writeKeyFiles(String baseFileName, DnsKeyPair pair,
|
||||||
File inDirectory) throws IOException {
|
File inDirectory) throws IOException {
|
||||||
@ -369,10 +346,8 @@ public class BINDKeyUtils {
|
|||||||
* This routine will write out the BIND9 dnssec-* tool compatible files to the
|
* This routine will write out the BIND9 dnssec-* tool compatible files to the
|
||||||
* standard file names.
|
* standard file names.
|
||||||
*
|
*
|
||||||
* @param pair
|
* @param pair the key pair in question.
|
||||||
* the key pair in question.
|
* @param inDirectory the directory to write to (may be null).
|
||||||
* @param inDirectory
|
|
||||||
* the directory to write to (may be null).
|
|
||||||
*/
|
*/
|
||||||
public static void writeKeyFiles(DnsKeyPair pair, File inDirectory)
|
public static void writeKeyFiles(DnsKeyPair pair, File inDirectory)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
@ -34,7 +34,6 @@ import java.security.KeyPair;
|
|||||||
import java.security.KeyPairGenerator;
|
import java.security.KeyPairGenerator;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.Provider;
|
import java.security.Provider;
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
import java.security.spec.ECFieldFp;
|
import java.security.spec.ECFieldFp;
|
||||||
@ -43,6 +42,7 @@ import java.security.spec.ECParameterSpec;
|
|||||||
import java.security.spec.ECPoint;
|
import java.security.spec.ECPoint;
|
||||||
import java.security.spec.EllipticCurve;
|
import java.security.spec.EllipticCurve;
|
||||||
import java.security.spec.InvalidParameterSpecException;
|
import java.security.spec.InvalidParameterSpecException;
|
||||||
|
import java.security.spec.NamedParameterSpec;
|
||||||
import java.security.spec.RSAKeyGenParameterSpec;
|
import java.security.spec.RSAKeyGenParameterSpec;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -51,12 +51,6 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import org.xbill.DNS.DNSSEC;
|
import org.xbill.DNS.DNSSEC;
|
||||||
|
|
||||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
|
||||||
// for now, we need to import the EdDSA parameter spec classes
|
|
||||||
// because they have no generic form in java.security.spec.*
|
|
||||||
// sadly, this will currently fail if you don't have the lib.
|
|
||||||
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class handles translating DNS signing algorithm identifiers into various
|
* This class handles translating DNS signing algorithm identifiers into various
|
||||||
* usable java implementations.
|
* usable java implementations.
|
||||||
@ -72,21 +66,24 @@ public class DnsKeyAlgorithm {
|
|||||||
|
|
||||||
// Our base algorithm numbers. This is a normalization of the DNSSEC
|
// Our base algorithm numbers. This is a normalization of the DNSSEC
|
||||||
// algorithms (which are really signature algorithms). Thus RSASHA1,
|
// algorithms (which are really signature algorithms). Thus RSASHA1,
|
||||||
// RSASHA256, etc. all boil down to 'RSA' here.
|
// RSASHA256, etc. all boil down to 'RSA' here. Similarly, ECDSAP256SHA256 and
|
||||||
public static final int UNKNOWN = -1;
|
// ECDSAP384SHA384 both become 'ECDSA'.
|
||||||
public static final int RSA = 1;
|
public enum BaseAlgorithm {
|
||||||
public static final int DH = 2;
|
UNKNOWN,
|
||||||
public static final int DSA = 3;
|
RSA,
|
||||||
public static final int ECC_GOST = 4;
|
DH,
|
||||||
public static final int ECDSA = 5;
|
DSA,
|
||||||
public static final int EDDSA = 6;
|
ECC_GOST,
|
||||||
|
ECDSA,
|
||||||
|
EDDSA;
|
||||||
|
}
|
||||||
|
|
||||||
private static class AlgEntry {
|
private static class AlgEntry {
|
||||||
public int dnssecAlgorithm;
|
public int dnssecAlgorithm;
|
||||||
public String sigName;
|
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.dnssecAlgorithm = algorithm;
|
||||||
this.sigName = sigName;
|
this.sigName = sigName;
|
||||||
this.baseType = baseType;
|
this.baseType = baseType;
|
||||||
@ -96,18 +93,20 @@ public class DnsKeyAlgorithm {
|
|||||||
private static class ECAlgEntry extends AlgEntry {
|
private static class ECAlgEntry extends AlgEntry {
|
||||||
public ECParameterSpec ecSpec;
|
public ECParameterSpec ecSpec;
|
||||||
|
|
||||||
public ECAlgEntry(int algorithm, String sigName, int baseType, ECParameterSpec spec) {
|
public ECAlgEntry(int algorithm, String sigName, BaseAlgorithm baseType, ECParameterSpec spec) {
|
||||||
super(algorithm, sigName, baseType);
|
super(algorithm, sigName, baseType);
|
||||||
this.ecSpec = spec;
|
this.ecSpec = spec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class EdAlgEntry extends AlgEntry {
|
private static class EdAlgEntry extends AlgEntry {
|
||||||
public 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);
|
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;
|
private static DnsKeyAlgorithm mInstance = null;
|
||||||
|
|
||||||
public DnsKeyAlgorithm() {
|
public DnsKeyAlgorithm() {
|
||||||
// Attempt to add the bouncycastle provider.
|
// Attempt to add the bouncycastle provider. This is so we can use this
|
||||||
// This is so we can use this provider if it is available, but not require
|
// provider if it is available, but not require the user to add it as one of
|
||||||
// the user to add it as one of the java.security providers.
|
// the java.security providers.
|
||||||
try {
|
try {
|
||||||
Class<?> bcProviderClass = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
|
Class<?> bcProviderClass = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
|
||||||
Provider bcProvider = (Provider) bcProviderClass.getDeclaredConstructor().newInstance();
|
Provider bcProvider = (Provider) bcProviderClass.getDeclaredConstructor().newInstance();
|
||||||
Security.addProvider(bcProvider);
|
Security.addProvider(bcProvider);
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
log.info("Unable to load BC provider");
|
log.fine("Unable to load BC provider");
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to add the EdDSA-Java provider.
|
|
||||||
try {
|
|
||||||
Class<?> eddsaProviderClass = Class.forName("net.i2p.crypto.eddsa.EdDSASecurityProvider");
|
|
||||||
Provider eddsaProvider = (Provider) eddsaProviderClass.getDeclaredConstructor().newInstance();
|
|
||||||
Security.addProvider(eddsaProvider);
|
|
||||||
} catch (ReflectiveOperationException e) {
|
|
||||||
log.warning("Unable to load EdDSA provider");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
@ -172,16 +162,16 @@ public class DnsKeyAlgorithm {
|
|||||||
mIdToMnemonicMap = new HashMap<>();
|
mIdToMnemonicMap = new HashMap<>();
|
||||||
|
|
||||||
// Load the standard DNSSEC algorithms.
|
// Load the standard DNSSEC algorithms.
|
||||||
addAlgorithm(DNSSEC.Algorithm.RSAMD5, "MD5withRSA", RSA);
|
addAlgorithm(DNSSEC.Algorithm.RSAMD5, "MD5withRSA", BaseAlgorithm.RSA);
|
||||||
addMnemonic("RSAMD5", DNSSEC.Algorithm.RSAMD5);
|
addMnemonic("RSAMD5", DNSSEC.Algorithm.RSAMD5);
|
||||||
|
|
||||||
addAlgorithm(DNSSEC.Algorithm.DH, "", DH);
|
addAlgorithm(DNSSEC.Algorithm.DH, "", BaseAlgorithm.DH);
|
||||||
addMnemonic("DH", DNSSEC.Algorithm.DH);
|
addMnemonic("DH", DNSSEC.Algorithm.DH);
|
||||||
|
|
||||||
addAlgorithm(DNSSEC.Algorithm.DSA, "SHA1withDSA", DSA);
|
addAlgorithm(DNSSEC.Algorithm.DSA, "SHA1withDSA", BaseAlgorithm.DSA);
|
||||||
addMnemonic("DSA", DNSSEC.Algorithm.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("RSASHA1", DNSSEC.Algorithm.RSASHA1);
|
||||||
addMnemonic("RSA", DNSSEC.Algorithm.RSASHA1);
|
addMnemonic("RSA", DNSSEC.Algorithm.RSASHA1);
|
||||||
|
|
||||||
@ -193,42 +183,49 @@ public class DnsKeyAlgorithm {
|
|||||||
addMnemonic("NSEC3RSASHA1", DNSSEC.Algorithm.RSA_NSEC3_SHA1);
|
addMnemonic("NSEC3RSASHA1", DNSSEC.Algorithm.RSA_NSEC3_SHA1);
|
||||||
|
|
||||||
// Algorithms added by RFC 5702.
|
// Algorithms added by RFC 5702.
|
||||||
addAlgorithm(DNSSEC.Algorithm.RSASHA256, "SHA256withRSA", RSA);
|
addAlgorithm(DNSSEC.Algorithm.RSASHA256, "SHA256withRSA", BaseAlgorithm.RSA);
|
||||||
addMnemonic("RSASHA256", DNSSEC.Algorithm.RSASHA256);
|
addMnemonic("RSASHA256", DNSSEC.Algorithm.RSASHA256);
|
||||||
|
|
||||||
addAlgorithm(DNSSEC.Algorithm.RSASHA512, "SHA512withRSA", RSA);
|
addAlgorithm(DNSSEC.Algorithm.RSASHA512, "SHA512withRSA", BaseAlgorithm.RSA);
|
||||||
addMnemonic("RSASHA512", DNSSEC.Algorithm.RSASHA512);
|
addMnemonic("RSASHA512", DNSSEC.Algorithm.RSASHA512);
|
||||||
|
|
||||||
// ECC-GOST is not supported by Java 1.8's Sun crypto provider. The
|
// ECC-GOST is not supported by Java 1.8's Sun crypto provider. The
|
||||||
// bouncycastle.org provider, however, does support it.
|
// bouncycastle.org provider, however, does support it.
|
||||||
// GostR3410-2001-CryptoPro-A is the named curve in the BC provider, but we
|
// GostR3410-2001-CryptoPro-A is the named curve in the BC provider, but we
|
||||||
// will get the parameters directly.
|
// will get the parameters directly.
|
||||||
addAlgorithm(DNSSEC.Algorithm.ECC_GOST, "GOST3411withECGOST3410", ECC_GOST, null);
|
addAlgorithm(DNSSEC.Algorithm.ECC_GOST, "GOST3411withECGOST3410", BaseAlgorithm.ECC_GOST, null);
|
||||||
addMnemonic("ECCGOST", DNSSEC.Algorithm.ECC_GOST);
|
addMnemonic("ECCGOST", DNSSEC.Algorithm.ECC_GOST);
|
||||||
addMnemonic("ECC-GOST", DNSSEC.Algorithm.ECC_GOST);
|
addMnemonic("ECC-GOST", DNSSEC.Algorithm.ECC_GOST);
|
||||||
|
|
||||||
addAlgorithm(DNSSEC.Algorithm.ECDSAP256SHA256, "SHA256withECDSA", ECDSA, "secp256r1");
|
addAlgorithm(DNSSEC.Algorithm.ECDSAP256SHA256, "SHA256withECDSA", BaseAlgorithm.ECDSA, "secp256r1");
|
||||||
addMnemonic("ECDSAP256SHA256", DNSSEC.Algorithm.ECDSAP256SHA256);
|
addMnemonic("ECDSAP256SHA256", DNSSEC.Algorithm.ECDSAP256SHA256);
|
||||||
addMnemonic("ECDSA-P256", DNSSEC.Algorithm.ECDSAP256SHA256);
|
addMnemonic("ECDSA-P256", DNSSEC.Algorithm.ECDSAP256SHA256);
|
||||||
|
|
||||||
addAlgorithm(DNSSEC.Algorithm.ECDSAP384SHA384, "SHA384withECDSA", ECDSA, "secp384r1");
|
addAlgorithm(DNSSEC.Algorithm.ECDSAP384SHA384, "SHA384withECDSA", BaseAlgorithm.ECDSA, "secp384r1");
|
||||||
addMnemonic("ECDSAP384SHA384", DNSSEC.Algorithm.ECDSAP384SHA384);
|
addMnemonic("ECDSAP384SHA384", DNSSEC.Algorithm.ECDSAP384SHA384);
|
||||||
addMnemonic("ECDSA-P384", DNSSEC.Algorithm.ECDSAP384SHA384);
|
addMnemonic("ECDSA-P384", DNSSEC.Algorithm.ECDSAP384SHA384);
|
||||||
|
|
||||||
// EdDSA is not supported by either the Java 1.8 Sun crypto
|
// For the Edwards Curve implementations, we just initialize Signature and
|
||||||
// provider or bouncycastle. It is added by the Ed25519-Java
|
// KeyPairGenerator with the curve name.
|
||||||
// library. We don't have a corresponding constant in
|
addAlgorithm(15, "Ed25519", BaseAlgorithm.EDDSA, "Ed25519");
|
||||||
// org.xbill.DNS.DNSSEC yet, though.
|
|
||||||
addAlgorithm(15, "NONEwithEdDSA", EDDSA, "Ed25519");
|
|
||||||
addMnemonic("ED25519", 15);
|
addMnemonic("ED25519", 15);
|
||||||
|
addAlgorithm(16, "Ed448", BaseAlgorithm.EDDSA, "Ed448");
|
||||||
|
addMnemonic(("ED448"), 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addAlgorithm(int algorithm, String sigName, int baseType) {
|
private void addAlgorithm(int algorithm, String sigName, BaseAlgorithm baseType) {
|
||||||
mAlgorithmMap.put(algorithm, new AlgEntry(algorithm, sigName, baseType));
|
mAlgorithmMap.put(algorithm, new AlgEntry(algorithm, sigName, baseType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addAlgorithm(int algorithm, String sigName, int baseType, String curveName) {
|
/**
|
||||||
if (baseType == ECDSA) {
|
* 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);
|
ECParameterSpec ecSpec = ECSpecFromAlgorithm(algorithm);
|
||||||
if (ecSpec == null)
|
if (ecSpec == null)
|
||||||
ecSpec = ECSpecFromName(curveName);
|
ecSpec = ECSpecFromName(curveName);
|
||||||
@ -244,28 +241,56 @@ public class DnsKeyAlgorithm {
|
|||||||
// If not, do not add the algorithm.
|
// If not, do not add the algorithm.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ECAlgEntry entry = new ECAlgEntry(algorithm, sigName, baseType, ecSpec);
|
ECAlgEntry entry = new ECAlgEntry(algorithm, sigName, BaseAlgorithm.ECDSA, ecSpec);
|
||||||
mAlgorithmMap.put(algorithm, entry);
|
mAlgorithmMap.put(algorithm, entry);
|
||||||
} else if (baseType == EDDSA) {
|
}
|
||||||
EdDSAParameterSpec edSpec = EdDSASpecFromName(curveName);
|
|
||||||
if (edSpec == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
// Check to see if we can get a Signature object for this algorithm.
|
||||||
try {
|
try {
|
||||||
Signature.getInstance(sigName);
|
Signature.getInstance(sigName);
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
// for now, let's find out
|
// for now, let's find out
|
||||||
log.severe("could not get signature for " + sigName + ": " + e.getMessage());
|
log.severe("could not get signature for EdDSA curve" + curveName + ": " + e.getMessage());
|
||||||
// If not, do not add the algorithm.
|
// If not, do not add the algorithm.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EdAlgEntry entry = new EdAlgEntry(algorithm, sigName, baseType, edSpec);
|
EdAlgEntry entry = new EdAlgEntry(algorithm, sigName, BaseAlgorithm.EDDSA, curveName);
|
||||||
mAlgorithmMap.put(algorithm, entry);
|
mAlgorithmMap.put(algorithm, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an Elliptic Curve algorithm given a signing scheme and curve name.
|
||||||
|
*
|
||||||
|
* @param algorithm the DNSSEC algorithm number
|
||||||
|
* @param sigName the signature scheme (e.g., which crypto hash function are
|
||||||
|
* we using?)
|
||||||
|
* @param baseType the base type (either ECDSA or EDDSA).
|
||||||
|
* @param curveName the name of the curve.
|
||||||
|
*/
|
||||||
|
private void addAlgorithm(int algorithm, String sigName, BaseAlgorithm baseType, String curveName) {
|
||||||
|
if (baseType == BaseAlgorithm.ECDSA) {
|
||||||
|
addECDSAAlgorithm(algorithm, sigName, curveName);
|
||||||
|
} else if (baseType == BaseAlgorithm.EDDSA) {
|
||||||
|
addEdDSAAlgorithm(algorithm, sigName, curveName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an alternate mnemonic for an algorithm.
|
||||||
|
*
|
||||||
|
* @param m the new mnemonic.
|
||||||
|
* @param alg the DNSSEC algorithm number.
|
||||||
|
*/
|
||||||
private void addMnemonic(String m, int alg) {
|
private void addMnemonic(String m, int alg) {
|
||||||
// Do not add mnemonics for algorithms that ended up not actually being
|
// Do not add mnemonics for algorithms that ended up not actually being
|
||||||
// supported.
|
// supported.
|
||||||
@ -276,19 +301,19 @@ public class DnsKeyAlgorithm {
|
|||||||
mIdToMnemonicMap.computeIfAbsent(alg, k -> m);
|
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)) {
|
if (mAlgorithmMap.containsKey(alias)) {
|
||||||
log.warning("Unable to alias algorithm " + alias + " because it already exists.");
|
log.warning("Unable to alias algorithm " + alias + " because it already exists.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mAlgorithmMap.containsKey(original_algorithm)) {
|
if (!mAlgorithmMap.containsKey(origAlgorithm)) {
|
||||||
log.warning("Unable to alias algorithm " + alias
|
log.warning("Unable to alias algorithm " + alias
|
||||||
+ " to unknown algorithm identifier " + original_algorithm);
|
+ " to unknown algorithm identifier " + origAlgorithm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mAlgorithmMap.put(alias, mAlgorithmMap.get(original_algorithm));
|
mAlgorithmMap.put(alias, mAlgorithmMap.get(origAlgorithm));
|
||||||
|
|
||||||
if (mnemonic != null) {
|
if (mnemonic != null) {
|
||||||
addMnemonic(mnemonic, alias);
|
addMnemonic(mnemonic, alias);
|
||||||
@ -322,8 +347,8 @@ public class DnsKeyAlgorithm {
|
|||||||
private ECParameterSpec ECSpecFromName(String stdName) {
|
private ECParameterSpec ECSpecFromName(String stdName) {
|
||||||
try {
|
try {
|
||||||
AlgorithmParameters ap = AlgorithmParameters.getInstance("EC");
|
AlgorithmParameters ap = AlgorithmParameters.getInstance("EC");
|
||||||
ECGenParameterSpec ecg_spec = new ECGenParameterSpec(stdName);
|
ECGenParameterSpec ecgSpec = new ECGenParameterSpec(stdName);
|
||||||
ap.init(ecg_spec);
|
ap.init(ecgSpec);
|
||||||
return ap.getParameterSpec(ECParameterSpec.class);
|
return ap.getParameterSpec(ECParameterSpec.class);
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
log.info("Elliptic Curve not supported by any crypto provider: " + e.getMessage());
|
log.info("Elliptic Curve not supported by any crypto provider: " + e.getMessage());
|
||||||
@ -333,24 +358,6 @@ public class DnsKeyAlgorithm {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the curve parameters from a named EdDSA curve.
|
|
||||||
private EdDSAParameterSpec EdDSASpecFromName(String stdName) {
|
|
||||||
try {
|
|
||||||
EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(stdName);
|
|
||||||
if (spec != null)
|
|
||||||
return spec;
|
|
||||||
throw new InvalidParameterSpecException("Edwards Curve " + stdName + " not found.");
|
|
||||||
}
|
|
||||||
// catch (NoSuchAlgorithmException e) {
|
|
||||||
// log.info("Edwards Curve not supported by any crypto provider: " +
|
|
||||||
// e.getMessage());
|
|
||||||
// }
|
|
||||||
catch (InvalidParameterSpecException e) {
|
|
||||||
log.info("Edwards Curve " + stdName + " not supported");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] supportedAlgMnemonics() {
|
public String[] supportedAlgMnemonics() {
|
||||||
Set<Integer> keyset = mAlgorithmMap.keySet();
|
Set<Integer> keyset = mAlgorithmMap.keySet();
|
||||||
Integer[] algs = keyset.toArray(new Integer[keyset.size()]);
|
Integer[] algs = keyset.toArray(new Integer[keyset.size()]);
|
||||||
@ -388,11 +395,10 @@ public class DnsKeyAlgorithm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given one of the ECDSA algorithms (ECDSAP256SHA256, etc.) return
|
* Given one of the ECDSA algorithms (ECDSAP256SHA256, etc.) return the
|
||||||
* the elliptic curve parameters.
|
* elliptic curve parameters.
|
||||||
*
|
*
|
||||||
* @param algorithm
|
* @param algorithm The DNSSEC algorithm number.
|
||||||
* The DNSSEC algorithm number.
|
|
||||||
* @return The calculated JCA ECParameterSpec for that DNSSEC algorithm, or
|
* @return The calculated JCA ECParameterSpec for that DNSSEC algorithm, or
|
||||||
* null if not a recognized/supported EC algorithm.
|
* null if not a recognized/supported EC algorithm.
|
||||||
*/
|
*/
|
||||||
@ -402,37 +408,35 @@ public class DnsKeyAlgorithm {
|
|||||||
return null;
|
return null;
|
||||||
if (!(entry instanceof ECAlgEntry))
|
if (!(entry instanceof ECAlgEntry))
|
||||||
return null;
|
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
|
* Given one of the EdDSA algorithms (ED25519 or ED448), return the named
|
||||||
* elliptic curve parameters.
|
* parameter spec.
|
||||||
*
|
*
|
||||||
* @param algorithm
|
* @param algorithm The DNSSEC algorithm number.
|
||||||
* The DNSSEC algorithm number.
|
* @return The NamedParameterSpec for that DNSSEC algorithm, nor null if the
|
||||||
* @return The stored EdDSAParameterSpec for that algorithm, or
|
* algorithm wasn't a supported EdDSA algorithm.
|
||||||
* null if not a recognized/supported EdDSA algorithm.
|
|
||||||
*/
|
*/
|
||||||
public EdDSAParameterSpec getEdwardsCurveParams(int algorithm) {
|
public NamedParameterSpec getEdwardsCurveSpec(int algorithm) {
|
||||||
AlgEntry entry = getEntry(algorithm);
|
AlgEntry entry = getEntry(algorithm);
|
||||||
if (entry == null)
|
if (entry == null)
|
||||||
return null;
|
return null;
|
||||||
if (!(entry instanceof EdAlgEntry))
|
if (!(entry instanceof EdAlgEntry))
|
||||||
return null;
|
return null;
|
||||||
EdAlgEntry 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
|
* Translate a possible algorithm alias back to the original DNSSEC algorithm
|
||||||
* number
|
* number
|
||||||
*
|
*
|
||||||
* @param algorithm
|
* @param algorithm a DNSSEC algorithm that may be an alias.
|
||||||
* a DNSSEC algorithm that may be an alias.
|
|
||||||
* @return -1 if the algorithm isn't recognised, the orignal algorithm number
|
* @return -1 if the algorithm isn't recognised, the orignal algorithm number
|
||||||
* if it is.
|
* if it is.
|
||||||
*/
|
*/
|
||||||
@ -458,8 +462,7 @@ public class DnsKeyAlgorithm {
|
|||||||
* Given an algorithm mnemonic, convert the mnemonic to a DNSSEC algorithm
|
* Given an algorithm mnemonic, convert the mnemonic to a DNSSEC algorithm
|
||||||
* number.
|
* number.
|
||||||
*
|
*
|
||||||
* @param s
|
* @param s The mnemonic string. This is case-insensitive.
|
||||||
* The mnemonic string. This is case-insensitive.
|
|
||||||
* @return -1 if the mnemonic isn't recognized or supported, the algorithm
|
* @return -1 if the mnemonic isn't recognized or supported, the algorithm
|
||||||
* number if it is.
|
* number if it is.
|
||||||
*/
|
*/
|
||||||
@ -473,8 +476,7 @@ public class DnsKeyAlgorithm {
|
|||||||
/**
|
/**
|
||||||
* Given a DNSSEC algorithm number, return the "preferred" mnemonic.
|
* Given a DNSSEC algorithm number, return the "preferred" mnemonic.
|
||||||
*
|
*
|
||||||
* @param algorithm
|
* @param algorithm A DNSSEC algorithm number.
|
||||||
* A DNSSEC algorithm number.
|
|
||||||
* @return The preferred mnemonic string, or null if not supported or
|
* @return The preferred mnemonic string, or null if not supported or
|
||||||
* recognized.
|
* recognized.
|
||||||
*/
|
*/
|
||||||
@ -482,15 +484,15 @@ public class DnsKeyAlgorithm {
|
|||||||
return mIdToMnemonicMap.get(algorithm);
|
return mIdToMnemonicMap.get(algorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int baseType(int algorithm) {
|
public BaseAlgorithm baseType(int algorithm) {
|
||||||
AlgEntry entry = getEntry(algorithm);
|
AlgEntry entry = getEntry(algorithm);
|
||||||
if (entry != null)
|
if (entry != null)
|
||||||
return entry.baseType;
|
return entry.baseType;
|
||||||
return UNKNOWN;
|
return BaseAlgorithm.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDSA(int algorithm) {
|
public boolean isDSA(int algorithm) {
|
||||||
return (baseType(algorithm) == DSA);
|
return (baseType(algorithm) == BaseAlgorithm.DSA);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyPair generateKeyPair(int algorithm, int keysize, boolean useLargeExp)
|
public KeyPair generateKeyPair(int algorithm, int keysize, boolean useLargeExp)
|
||||||
@ -502,14 +504,14 @@ public class DnsKeyAlgorithm {
|
|||||||
mRSAKeyGenerator = KeyPairGenerator.getInstance("RSA");
|
mRSAKeyGenerator = KeyPairGenerator.getInstance("RSA");
|
||||||
}
|
}
|
||||||
|
|
||||||
RSAKeyGenParameterSpec rsa_spec;
|
RSAKeyGenParameterSpec rsaSpec;
|
||||||
if (useLargeExp) {
|
if (useLargeExp) {
|
||||||
rsa_spec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F4);
|
rsaSpec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F4);
|
||||||
} else {
|
} else {
|
||||||
rsa_spec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F0);
|
rsaSpec = new RSAKeyGenParameterSpec(keysize, RSAKeyGenParameterSpec.F0);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
mRSAKeyGenerator.initialize(rsa_spec);
|
mRSAKeyGenerator.initialize(rsaSpec);
|
||||||
} catch (InvalidAlgorithmParameterException e) {
|
} catch (InvalidAlgorithmParameterException e) {
|
||||||
// Fold the InvalidAlgorithmParameterException into our existing
|
// Fold the InvalidAlgorithmParameterException into our existing
|
||||||
// thrown exception. Ugly, but requires less code change.
|
// thrown exception. Ugly, but requires less code change.
|
||||||
@ -560,18 +562,9 @@ public class DnsKeyAlgorithm {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EDDSA: {
|
case EDDSA: {
|
||||||
if (mEdKeyGenerator == null) {
|
EdAlgEntry entry = (EdAlgEntry) getEntry(algorithm);
|
||||||
mEdKeyGenerator = KeyPairGenerator.getInstance("EdDSA");
|
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();
|
pair = mEdKeyGenerator.generateKeyPair();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,16 @@ import java.security.interfaces.DSAPrivateKey;
|
|||||||
import java.security.interfaces.DSAPublicKey;
|
import java.security.interfaces.DSAPublicKey;
|
||||||
import java.security.interfaces.ECPrivateKey;
|
import java.security.interfaces.ECPrivateKey;
|
||||||
import java.security.interfaces.ECPublicKey;
|
import java.security.interfaces.ECPublicKey;
|
||||||
|
import java.security.interfaces.EdECPrivateKey;
|
||||||
|
import java.security.interfaces.EdECPublicKey;
|
||||||
import java.security.interfaces.RSAPrivateCrtKey;
|
import java.security.interfaces.RSAPrivateCrtKey;
|
||||||
import java.security.spec.DSAPrivateKeySpec;
|
import java.security.spec.DSAPrivateKeySpec;
|
||||||
import java.security.spec.ECParameterSpec;
|
import java.security.spec.ECParameterSpec;
|
||||||
import java.security.spec.ECPrivateKeySpec;
|
import java.security.spec.ECPrivateKeySpec;
|
||||||
|
import java.security.spec.EdECPrivateKeySpec;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.security.spec.KeySpec;
|
import java.security.spec.KeySpec;
|
||||||
|
import java.security.spec.NamedParameterSpec;
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.security.spec.RSAPrivateCrtKeySpec;
|
import java.security.spec.RSAPrivateCrtKeySpec;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
@ -50,13 +54,6 @@ import org.xbill.DNS.DNSSEC.DNSSECException;
|
|||||||
import org.xbill.DNS.Name;
|
import org.xbill.DNS.Name;
|
||||||
import org.xbill.DNS.utils.base64;
|
import org.xbill.DNS.utils.base64;
|
||||||
|
|
||||||
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
|
|
||||||
// For now, just import the native EdDSA classes
|
|
||||||
import net.i2p.crypto.eddsa.EdDSAPublicKey;
|
|
||||||
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
|
|
||||||
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
|
|
||||||
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class handles conversions between JCA key formats and DNSSEC and BIND9
|
* This class handles conversions between JCA key formats and DNSSEC and BIND9
|
||||||
* key formats.
|
* key formats.
|
||||||
@ -87,7 +84,6 @@ public class DnsKeyConverter {
|
|||||||
|
|
||||||
// Because we have arbitrarily aliased algorithms, we need to possibly
|
// Because we have arbitrarily aliased algorithms, we need to possibly
|
||||||
// translate the aliased algorithm back to the actual algorithm.
|
// translate the aliased algorithm back to the actual algorithm.
|
||||||
|
|
||||||
int originalAlgorithm = mAlgorithms.originalAlgorithm(pKeyRecord.getAlgorithm());
|
int originalAlgorithm = mAlgorithms.originalAlgorithm(pKeyRecord.getAlgorithm());
|
||||||
|
|
||||||
if (originalAlgorithm <= 0)
|
if (originalAlgorithm <= 0)
|
||||||
@ -101,16 +97,6 @@ public class DnsKeyConverter {
|
|||||||
pKeyRecord.getKey());
|
pKeyRecord.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
// do not rely on DNSJava's method for EdDSA for now.
|
|
||||||
if (mAlgorithms.baseType(originalAlgorithm) == DnsKeyAlgorithm.EDDSA) {
|
|
||||||
try {
|
|
||||||
return parseEdDSADNSKEYRecord(pKeyRecord);
|
|
||||||
} catch (InvalidKeySpecException e) {
|
|
||||||
// just to be expedient, recast this as a NoSuchAlgorithmException.
|
|
||||||
throw new NoSuchAlgorithmException(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// This uses DNSJava's DNSSEC.toPublicKey() method.
|
// This uses DNSJava's DNSSEC.toPublicKey() method.
|
||||||
return pKeyRecord.getPublicKey();
|
return pKeyRecord.getPublicKey();
|
||||||
@ -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.
|
* Given a JCA public key and the ancillary data, generate a DNSKEY record.
|
||||||
*/
|
*/
|
||||||
public DNSKEYRecord generateDNSKEYRecord(Name name, int dclass, long ttl,
|
public DNSKEYRecord generateDNSKEYRecord(Name name, int dclass, long ttl,
|
||||||
int flags, int alg, PublicKey key) {
|
int flags, int alg, PublicKey key) {
|
||||||
try {
|
try {
|
||||||
if (mAlgorithms.baseType(alg) == DnsKeyAlgorithm.EDDSA) {
|
|
||||||
return generateEdDSADNSKEYRecord(name, dclass, ttl, flags, alg, key);
|
|
||||||
}
|
|
||||||
return new DNSKEYRecord(name, dclass, ttl, flags, DNSKEYRecord.Protocol.DNSSEC, alg,
|
return new DNSKEYRecord(name, dclass, ttl, flags, DNSKEYRecord.Protocol.DNSSEC, alg,
|
||||||
key);
|
key);
|
||||||
} catch (DNSSECException e) {
|
} catch (DNSSECException e) {
|
||||||
@ -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
|
// Private Key Specific Parsing routines
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -168,9 +129,9 @@ public class DnsKeyConverter {
|
|||||||
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(key);
|
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(key);
|
||||||
try {
|
try {
|
||||||
switch (mAlgorithms.baseType(algorithm)) {
|
switch (mAlgorithms.baseType(algorithm)) {
|
||||||
case DnsKeyAlgorithm.RSA:
|
case RSA:
|
||||||
return mRSAKeyFactory.generatePrivate(spec);
|
return mRSAKeyFactory.generatePrivate(spec);
|
||||||
case DnsKeyAlgorithm.DSA:
|
case DSA:
|
||||||
return mDSAKeyFactory.generatePrivate(spec);
|
return mDSAKeyFactory.generatePrivate(spec);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
@ -225,17 +186,17 @@ public class DnsKeyConverter {
|
|||||||
int alg = parseInt(val, -1);
|
int alg = parseInt(val, -1);
|
||||||
|
|
||||||
switch (mAlgorithms.baseType(alg)) {
|
switch (mAlgorithms.baseType(alg)) {
|
||||||
case DnsKeyAlgorithm.RSA:
|
case RSA:
|
||||||
return parsePrivateRSA(lines);
|
return parsePrivateRSA(lines);
|
||||||
case DnsKeyAlgorithm.DSA:
|
case DSA:
|
||||||
return parsePrivateDSA(lines);
|
return parsePrivateDSA(lines);
|
||||||
case DnsKeyAlgorithm.DH:
|
case DH:
|
||||||
return parsePrivateDH(lines);
|
return parsePrivateDH(lines);
|
||||||
case DnsKeyAlgorithm.ECC_GOST:
|
case ECC_GOST:
|
||||||
return parsePrivateECDSA(lines, alg);
|
return parsePrivateECDSA(lines, alg);
|
||||||
case DnsKeyAlgorithm.ECDSA:
|
case ECDSA:
|
||||||
return parsePrivateECDSA(lines, alg);
|
return parsePrivateECDSA(lines, alg);
|
||||||
case DnsKeyAlgorithm.EDDSA:
|
case EDDSA:
|
||||||
return parsePrivateEdDSA(lines, alg);
|
return parsePrivateEdDSA(lines, alg);
|
||||||
default:
|
default:
|
||||||
throw new IOException("unsupported private key algorithm: " + val);
|
throw new IOException("unsupported private key algorithm: " + val);
|
||||||
@ -272,12 +233,12 @@ public class DnsKeyConverter {
|
|||||||
private PrivateKey parsePrivateRSA(StringTokenizer lines)
|
private PrivateKey parsePrivateRSA(StringTokenizer lines)
|
||||||
throws NoSuchAlgorithmException {
|
throws NoSuchAlgorithmException {
|
||||||
BigInteger modulus = null;
|
BigInteger modulus = null;
|
||||||
BigInteger public_exponent = null;
|
BigInteger publicExponent = null;
|
||||||
BigInteger private_exponent = null;
|
BigInteger privateExponent = null;
|
||||||
BigInteger prime_p = null;
|
BigInteger primeP = null;
|
||||||
BigInteger prime_q = null;
|
BigInteger primeQ = null;
|
||||||
BigInteger prime_p_exponent = null;
|
BigInteger primePExponent = null;
|
||||||
BigInteger prime_q_exponent = null;
|
BigInteger primeQExponent = null;
|
||||||
BigInteger coefficient = null;
|
BigInteger coefficient = null;
|
||||||
|
|
||||||
while (lines.hasMoreTokens()) {
|
while (lines.hasMoreTokens()) {
|
||||||
@ -296,33 +257,28 @@ public class DnsKeyConverter {
|
|||||||
|
|
||||||
if (line.startsWith("Modulus: ")) {
|
if (line.startsWith("Modulus: ")) {
|
||||||
modulus = new BigInteger(1, data);
|
modulus = new BigInteger(1, data);
|
||||||
// printBigIntCompare(data, modulus);
|
|
||||||
} else if (line.startsWith("PublicExponent: ")) {
|
} else if (line.startsWith("PublicExponent: ")) {
|
||||||
public_exponent = new BigInteger(1, data);
|
publicExponent = new BigInteger(1, data);
|
||||||
// printBigIntCompare(data, public_exponent);
|
|
||||||
} else if (line.startsWith("PrivateExponent: ")) {
|
} else if (line.startsWith("PrivateExponent: ")) {
|
||||||
private_exponent = new BigInteger(1, data);
|
privateExponent = new BigInteger(1, data);
|
||||||
// printBigIntCompare(data, private_exponent);
|
|
||||||
} else if (line.startsWith("Prime1: ")) {
|
} else if (line.startsWith("Prime1: ")) {
|
||||||
prime_p = new BigInteger(1, data);
|
primeP = new BigInteger(1, data);
|
||||||
// printBigIntCompare(data, prime_p);
|
|
||||||
} else if (line.startsWith("Prime2: ")) {
|
} else if (line.startsWith("Prime2: ")) {
|
||||||
prime_q = new BigInteger(1, data);
|
primeQ = new BigInteger(1, data);
|
||||||
// printBigIntCompare(data, prime_q);
|
|
||||||
} else if (line.startsWith("Exponent1: ")) {
|
} else if (line.startsWith("Exponent1: ")) {
|
||||||
prime_p_exponent = new BigInteger(1, data);
|
primePExponent = new BigInteger(1, data);
|
||||||
} else if (line.startsWith("Exponent2: ")) {
|
} else if (line.startsWith("Exponent2: ")) {
|
||||||
prime_q_exponent = new BigInteger(1, data);
|
primeQExponent = new BigInteger(1, data);
|
||||||
} else if (line.startsWith("Coefficient: ")) {
|
} else if (line.startsWith("Coefficient: ")) {
|
||||||
coefficient = new BigInteger(1, data);
|
coefficient = new BigInteger(1, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
KeySpec spec = new RSAPrivateCrtKeySpec(modulus, public_exponent,
|
KeySpec spec = new RSAPrivateCrtKeySpec(modulus, publicExponent,
|
||||||
private_exponent, prime_p,
|
privateExponent, primeP,
|
||||||
prime_q, prime_p_exponent,
|
primeQ, primePExponent,
|
||||||
prime_q_exponent, coefficient);
|
primeQExponent, coefficient);
|
||||||
if (mRSAKeyFactory == null) {
|
if (mRSAKeyFactory == null) {
|
||||||
mRSAKeyFactory = KeyFactory.getInstance("RSA");
|
mRSAKeyFactory = KeyFactory.getInstance("RSA");
|
||||||
}
|
}
|
||||||
@ -466,13 +422,13 @@ public class DnsKeyConverter {
|
|||||||
if (mECKeyFactory == null) {
|
if (mECKeyFactory == null) {
|
||||||
mECKeyFactory = KeyFactory.getInstance("EC");
|
mECKeyFactory = KeyFactory.getInstance("EC");
|
||||||
}
|
}
|
||||||
ECParameterSpec ec_spec = mAlgorithms.getEllipticCurveParams(algorithm);
|
ECParameterSpec ecSpec = mAlgorithms.getEllipticCurveParams(algorithm);
|
||||||
if (ec_spec == null) {
|
if (ecSpec == null) {
|
||||||
throw new NoSuchAlgorithmException("DNSSEC algorithm " + algorithm +
|
throw new NoSuchAlgorithmException("DNSSEC algorithm " + algorithm +
|
||||||
" is not a recognized Elliptic Curve algorithm");
|
" is not a recognized Elliptic Curve algorithm");
|
||||||
}
|
}
|
||||||
|
|
||||||
KeySpec spec = new ECPrivateKeySpec(s, ec_spec);
|
KeySpec spec = new ECPrivateKeySpec(s, ecSpec);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return mECKeyFactory.generatePrivate(spec);
|
return mECKeyFactory.generatePrivate(spec);
|
||||||
@ -516,13 +472,13 @@ public class DnsKeyConverter {
|
|||||||
if (mEdKeyFactory == null) {
|
if (mEdKeyFactory == null) {
|
||||||
mEdKeyFactory = KeyFactory.getInstance("EdDSA");
|
mEdKeyFactory = KeyFactory.getInstance("EdDSA");
|
||||||
}
|
}
|
||||||
EdDSAParameterSpec ed_spec = mAlgorithms.getEdwardsCurveParams(algorithm);
|
NamedParameterSpec namedSpec = mAlgorithms.getEdwardsCurveSpec(algorithm);
|
||||||
if (ed_spec == null) {
|
if (namedSpec == null) {
|
||||||
throw new NoSuchAlgorithmException("DNSSEC algorithm " + algorithm +
|
throw new NoSuchAlgorithmException("DNSSEC algorithm " + algorithm +
|
||||||
" is not a recognized Edwards Curve algorithm");
|
" is not a recognized Edwards Curve algorithm");
|
||||||
}
|
}
|
||||||
|
|
||||||
KeySpec spec = new EdDSAPrivateKeySpec(seed, ed_spec);
|
EdECPrivateKeySpec spec = new EdECPrivateKeySpec(namedSpec, seed);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return mEdKeyFactory.generatePrivate(spec);
|
return mEdKeyFactory.generatePrivate(spec);
|
||||||
@ -545,8 +501,8 @@ public class DnsKeyConverter {
|
|||||||
return generatePrivateDH((DHPrivateKey) priv, (DHPublicKey) pub, alg);
|
return generatePrivateDH((DHPrivateKey) priv, (DHPublicKey) pub, alg);
|
||||||
} else if (priv instanceof ECPrivateKey && pub instanceof ECPublicKey) {
|
} else if (priv instanceof ECPrivateKey && pub instanceof ECPublicKey) {
|
||||||
return generatePrivateEC((ECPrivateKey) priv, (ECPublicKey) pub, alg);
|
return generatePrivateEC((ECPrivateKey) priv, (ECPublicKey) pub, alg);
|
||||||
} else if (priv instanceof EdDSAPrivateKey && pub instanceof EdDSAPublicKey) {
|
} else if (priv instanceof EdECPrivateKey && pub instanceof EdECPublicKey) {
|
||||||
return generatePrivateED((EdDSAPrivateKey) priv, (EdDSAPublicKey) pub, alg);
|
return generatePrivateED((EdECPrivateKey) priv, (EdECPublicKey) pub, alg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -556,16 +512,16 @@ public class DnsKeyConverter {
|
|||||||
* Convert from 'unsigned' big integer to original 'signed format' in Base64
|
* Convert from 'unsigned' big integer to original 'signed format' in Base64
|
||||||
*/
|
*/
|
||||||
private static String b64BigInt(BigInteger i) {
|
private static String b64BigInt(BigInteger i) {
|
||||||
byte[] orig_bytes = i.toByteArray();
|
byte[] origBytes = i.toByteArray();
|
||||||
|
|
||||||
if (orig_bytes[0] != 0 || orig_bytes.length == 1) {
|
if (origBytes[0] != 0 || origBytes.length == 1) {
|
||||||
return base64.toString(orig_bytes);
|
return base64.toString(origBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] signed_bytes = new byte[orig_bytes.length - 1];
|
byte[] signedBytes = new byte[origBytes.length - 1];
|
||||||
System.arraycopy(orig_bytes, 1, signed_bytes, 0, signed_bytes.length);
|
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
|
* Given an edwards curve key pair, and the actual algorithm (which will
|
||||||
* describe the curve used), return the BIND9-style text encoding.
|
* describe the curve used), return the BIND9-style text encoding.
|
||||||
*/
|
*/
|
||||||
private String generatePrivateED(EdDSAPrivateKey priv, EdDSAPublicKey pub, int alg) {
|
private String generatePrivateED(EdECPrivateKey priv, EdECPublicKey pub, int alg) {
|
||||||
StringWriter sw = new StringWriter();
|
StringWriter sw = new StringWriter();
|
||||||
PrintWriter out = new PrintWriter(sw);
|
PrintWriter out = new PrintWriter(sw);
|
||||||
|
|
||||||
@ -676,7 +632,8 @@ public class DnsKeyConverter {
|
|||||||
out.println("Algorithm: " + alg + " (" + mAlgorithms.algToString(alg)
|
out.println("Algorithm: " + alg + " (" + mAlgorithms.algToString(alg)
|
||||||
+ ")");
|
+ ")");
|
||||||
out.print("PrivateKey: ");
|
out.print("PrivateKey: ");
|
||||||
out.println(base64.toString(priv.getSeed()));
|
byte[] keyBytes = priv.getBytes().orElse("null".getBytes());
|
||||||
|
out.println(base64.toString(keyBytes));
|
||||||
|
|
||||||
return sw.toString();
|
return sw.toString();
|
||||||
}
|
}
|
||||||
|
@ -264,19 +264,23 @@ public class DnsKeyPair {
|
|||||||
* @throws NoSuchAlgorithmException
|
* @throws NoSuchAlgorithmException
|
||||||
*/
|
*/
|
||||||
public Signature getVerifier() {
|
public Signature getVerifier() {
|
||||||
if (mVerifier == null) {
|
if (mVerifier != null)
|
||||||
|
return mVerifier;
|
||||||
|
|
||||||
mVerifier = getSignature();
|
mVerifier = getSignature();
|
||||||
PublicKey pk = getPublic();
|
PublicKey pk = getPublic();
|
||||||
if (mVerifier != null && pk != null) {
|
|
||||||
|
if (mVerifier == null || pk == null) {
|
||||||
|
log.warning("Could not get a Signature object for this key pair" + this);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mVerifier.initVerify(pk);
|
mVerifier.initVerify(pk);
|
||||||
} catch (InvalidKeyException e) {
|
} catch (InvalidKeyException e) {
|
||||||
}
|
log.warning("Key pair cannot initialize with public key: " + this);
|
||||||
} else {
|
|
||||||
// do not return an uninitialized verifier
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return mVerifier;
|
return mVerifier;
|
||||||
}
|
}
|
||||||
@ -330,6 +334,7 @@ public class DnsKeyPair {
|
|||||||
// This is from a StackOverflow answer. There are number of bytes-to-hex
|
// This is from a StackOverflow answer. There are number of bytes-to-hex
|
||||||
// converters in the ecosystem, but this avoid extra dependencies
|
// converters in the ecosystem, but this avoid extra dependencies
|
||||||
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
|
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
|
||||||
|
|
||||||
public static String toHex(byte[] bytes) {
|
public static String toHex(byte[] bytes) {
|
||||||
byte[] hexChars = new byte[bytes.length * 2];
|
byte[] hexChars = new byte[bytes.length * 2];
|
||||||
for (int j = 0; j < bytes.length; j++) {
|
for (int j = 0; j < bytes.length; j++) {
|
||||||
|
@ -241,7 +241,7 @@ public class DnsSecVerifier {
|
|||||||
|
|
||||||
byte[] sig = sigrec.getSignature();
|
byte[] sig = sigrec.getSignature();
|
||||||
|
|
||||||
if (algs.baseType(sigrec.getAlgorithm()) == DnsKeyAlgorithm.DSA) {
|
if (algs.baseType(sigrec.getAlgorithm()) == DnsKeyAlgorithm.BaseAlgorithm.DSA) {
|
||||||
sig = SignUtils.convertDSASignature(sig);
|
sig = SignUtils.convertDSASignature(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,21 +68,14 @@ public class JCEDnsSecSigner {
|
|||||||
/**
|
/**
|
||||||
* Cryptographically generate a new DNSSEC key.
|
* Cryptographically generate a new DNSSEC key.
|
||||||
*
|
*
|
||||||
* @param owner
|
* @param owner the KEY RR's owner name.
|
||||||
* the KEY RR's owner name.
|
* @param ttl the KEY RR's TTL.
|
||||||
* @param ttl
|
* @param dclass the KEY RR's DNS class.
|
||||||
* the KEY RR's TTL.
|
* @param algorithm the DNSSEC algorithm (RSASHA258, RSASHA512,
|
||||||
* @param dclass
|
|
||||||
* the KEY RR's DNS class.
|
|
||||||
* @param algorithm
|
|
||||||
* the DNSSEC algorithm (RSASHA258, RSASHA512,
|
|
||||||
* ECDSAP256, etc.)
|
* ECDSAP256, etc.)
|
||||||
* @param flags
|
* @param flags any flags for the KEY RR.
|
||||||
* any flags for the KEY RR.
|
* @param keysize the size of the key to generate.
|
||||||
* @param keysize
|
* @param useLargeExponent if generating an RSA key, use the large exponent.
|
||||||
* the size of the key to generate.
|
|
||||||
* @param useLargeExponent
|
|
||||||
* if generating an RSA key, use the large exponent.
|
|
||||||
* @return a DnsKeyPair with the public and private keys populated.
|
* @return a DnsKeyPair with the public and private keys populated.
|
||||||
*/
|
*/
|
||||||
public DnsKeyPair generateKey(Name owner, long ttl, int dclass, int algorithm,
|
public DnsKeyPair generateKey(Name owner, long ttl, int dclass, int algorithm,
|
||||||
@ -113,29 +106,25 @@ public class JCEDnsSecSigner {
|
|||||||
/**
|
/**
|
||||||
* Sign an RRset.
|
* Sign an RRset.
|
||||||
*
|
*
|
||||||
* @param rrset
|
* @param rrset the RRset to sign -- any existing signatures are ignored.
|
||||||
* the RRset to sign -- any existing signatures are ignored.
|
* @param keypars a list of DnsKeyPair objects containing private keys.
|
||||||
* @param keypars
|
* @param start the inception time for the resulting RRSIG records.
|
||||||
* a list of DnsKeyPair objects containing private keys.
|
* @param expire the expiration time for the resulting RRSIG records.
|
||||||
* @param start
|
|
||||||
* the inception time for the resulting RRSIG records.
|
|
||||||
* @param expire
|
|
||||||
* the expiration time for the resulting RRSIG records.
|
|
||||||
* @return a list of RRSIGRecord objects.
|
* @return a list of RRSIGRecord objects.
|
||||||
*/
|
*/
|
||||||
public List<RRSIGRecord> signRRset(RRset rrset, List<DnsKeyPair> keypairs, Instant start,
|
public List<RRSIGRecord> signRRset(RRset rrset, List<DnsKeyPair> keypairs, Instant start,
|
||||||
Instant expire) throws IOException,
|
Instant expire) throws IOException,
|
||||||
GeneralSecurityException {
|
GeneralSecurityException {
|
||||||
if (rrset == null || keypairs == null)
|
if (rrset == null || keypairs == null)
|
||||||
return null;
|
return new ArrayList<>();
|
||||||
|
|
||||||
// default start to now, expire to start + 1 second.
|
// default start to now, expire to start + 1 second.
|
||||||
if (start == null)
|
if (start == null)
|
||||||
start = Instant.now();
|
start = Instant.now();
|
||||||
if (expire == null)
|
if (expire == null)
|
||||||
expire = start.plusSeconds(1);
|
expire = start.plusSeconds(1);
|
||||||
if (keypairs.size() == 0)
|
if (keypairs.isEmpty())
|
||||||
return null;
|
return new ArrayList<>();
|
||||||
|
|
||||||
if (mVerboseSigning) {
|
if (mVerboseSigning) {
|
||||||
log.info("Signing RRset:");
|
log.info("Signing RRset:");
|
||||||
@ -143,9 +132,9 @@ public class JCEDnsSecSigner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// first, pre-calculate the RRset bytes.
|
// first, pre-calculate the RRset bytes.
|
||||||
byte[] rrset_data = SignUtils.generateCanonicalRRsetData(rrset, 0, 0);
|
byte[] rrsetData = SignUtils.generateCanonicalRRsetData(rrset, 0, 0);
|
||||||
|
|
||||||
ArrayList<RRSIGRecord> sigs = new ArrayList<RRSIGRecord>(keypairs.size());
|
ArrayList<RRSIGRecord> sigs = new ArrayList<>(keypairs.size());
|
||||||
|
|
||||||
// for each keypair, sign the RRset.
|
// for each keypair, sign the RRset.
|
||||||
for (DnsKeyPair pair : keypairs) {
|
for (DnsKeyPair pair : keypairs) {
|
||||||
@ -155,13 +144,13 @@ public class JCEDnsSecSigner {
|
|||||||
|
|
||||||
RRSIGRecord presig = SignUtils.generatePreRRSIG(rrset, keyrec, start, expire,
|
RRSIGRecord presig = SignUtils.generatePreRRSIG(rrset, keyrec, start, expire,
|
||||||
rrset.getTTL());
|
rrset.getTTL());
|
||||||
byte[] sign_data = SignUtils.generateSigData(rrset_data, presig);
|
byte[] signData = SignUtils.generateSigData(rrsetData, presig);
|
||||||
|
|
||||||
if (mVerboseSigning) {
|
if (mVerboseSigning) {
|
||||||
log.info("Canonical pre-signature data to sign with key "
|
log.info("Canonical pre-signature data to sign with key "
|
||||||
+ keyrec.getName().toString() + "/" + keyrec.getAlgorithm() + "/"
|
+ keyrec.getName().toString() + "/" + keyrec.getAlgorithm() + "/"
|
||||||
+ keyrec.getFootprint() + ":");
|
+ keyrec.getFootprint() + ":");
|
||||||
log.info(hexdump.dump(null, sign_data));
|
log.info(hexdump.dump(null, signData));
|
||||||
}
|
}
|
||||||
|
|
||||||
Signature signer = pair.getSigner();
|
Signature signer = pair.getSigner();
|
||||||
@ -174,7 +163,7 @@ public class JCEDnsSecSigner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sign the data.
|
// sign the data.
|
||||||
signer.update(sign_data);
|
signer.update(signData);
|
||||||
byte[] sig = signer.sign();
|
byte[] sig = signer.sign();
|
||||||
|
|
||||||
if (mVerboseSigning) {
|
if (mVerboseSigning) {
|
||||||
@ -184,7 +173,7 @@ public class JCEDnsSecSigner {
|
|||||||
|
|
||||||
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
DnsKeyAlgorithm algs = DnsKeyAlgorithm.getInstance();
|
||||||
// Convert to RFC 2536 format, if necessary.
|
// Convert to RFC 2536 format, if necessary.
|
||||||
if (algs.baseType(pair.getDNSKEYAlgorithm()) == DnsKeyAlgorithm.DSA) {
|
if (algs.baseType(pair.getDNSKEYAlgorithm()) == DnsKeyAlgorithm.BaseAlgorithm.DSA) {
|
||||||
DSAPublicKey pk = (DSAPublicKey) pair.getPublic();
|
DSAPublicKey pk = (DSAPublicKey) pair.getPublic();
|
||||||
sig = SignUtils.convertDSASignature(pk.getParams(), sig);
|
sig = SignUtils.convertDSASignature(pk.getParams(), sig);
|
||||||
}
|
}
|
||||||
@ -206,12 +195,9 @@ public class JCEDnsSecSigner {
|
|||||||
/**
|
/**
|
||||||
* Create a completely self-signed DNSKEY RRset.
|
* Create a completely self-signed DNSKEY RRset.
|
||||||
*
|
*
|
||||||
* @param keypairs
|
* @param keypairs the public & private keypairs to use in the keyset.
|
||||||
* the public & private keypairs to use in the keyset.
|
* @param start the RRSIG inception time.
|
||||||
* @param start
|
* @param expire the RRSIG expiration time.
|
||||||
* the RRSIG inception time.
|
|
||||||
* @param expire
|
|
||||||
* the RRSIG expiration time.
|
|
||||||
* @return a signed RRset.
|
* @return a signed RRset.
|
||||||
*/
|
*/
|
||||||
public RRset makeKeySet(List<DnsKeyPair> keypairs, Instant start, Instant expire)
|
public RRset makeKeySet(List<DnsKeyPair> keypairs, Instant start, Instant expire)
|
||||||
@ -236,67 +222,55 @@ public class JCEDnsSecSigner {
|
|||||||
/**
|
/**
|
||||||
* Conditionally sign an RRset and add it to the toList.
|
* Conditionally sign an RRset and add it to the toList.
|
||||||
*
|
*
|
||||||
* @param toList
|
* @param toList the list to which we are adding the processed RRsets.
|
||||||
* the list to which we are adding the processed RRsets.
|
* @param zonename the zone apex name.
|
||||||
* @param zonename
|
* @param rrset the RRset under consideration.
|
||||||
* the zone apex name.
|
* @param kskpairs the List of KSKs..
|
||||||
* @param rrset
|
* @param zskpairs the List of zone keys.
|
||||||
* the RRset under consideration.
|
* @param start the RRSIG inception time.
|
||||||
* @param kskpairs
|
* @param expire the RRSIG expiration time.
|
||||||
* the List of KSKs..
|
* @param fullySignKeyset if true, sign the zone apex keyset with both KSKs
|
||||||
* @param zskpairs
|
* and ZSKs.
|
||||||
* the List of zone keys.
|
* @param lastCut the name of the last delegation point encountered.
|
||||||
* @param start
|
|
||||||
* the RRSIG inception time.
|
|
||||||
* @param expire
|
|
||||||
* the RRSIG expiration time.
|
|
||||||
* @param fullySignKeyset
|
|
||||||
* if true, sign the zone apex keyset with both KSKs and
|
|
||||||
* ZSKs.
|
|
||||||
* @param last_cut
|
|
||||||
* the name of the last delegation point encountered.
|
|
||||||
*
|
*
|
||||||
* @return the name of the new last_cut.
|
* @return the name of the new last_cut.
|
||||||
*/
|
*/
|
||||||
private Name addRRset(List<Record> toList, Name zonename, RRset rrset,
|
private Name addRRset(List<Record> toList, Name zonename, RRset rrset,
|
||||||
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs, Instant start,
|
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs, Instant start,
|
||||||
Instant expire, boolean fullySignKeyset, Name last_cut,
|
Instant expire, boolean fullySignKeyset, Name lastCut,
|
||||||
Name last_dname) throws IOException, GeneralSecurityException {
|
Name lastDname) throws IOException, GeneralSecurityException {
|
||||||
// add the records themselves
|
// add the records themselves
|
||||||
rrset.rrs().forEach(record -> {
|
rrset.rrs().forEach(toList::add);
|
||||||
toList.add(record);
|
|
||||||
});
|
|
||||||
|
|
||||||
int type = SignUtils.recordSecType(zonename, rrset.getName(), rrset.getType(),
|
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).
|
// we don't sign non-normal sets (delegations, glue, invalid).
|
||||||
if (type == SignUtils.RR_DELEGATION) {
|
if (type == SignUtils.RR_DELEGATION) {
|
||||||
return rrset.getName();
|
return rrset.getName();
|
||||||
}
|
}
|
||||||
if (type == SignUtils.RR_GLUE || type == SignUtils.RR_INVALID) {
|
if (type == SignUtils.RR_GLUE || type == SignUtils.RR_INVALID) {
|
||||||
return last_cut;
|
return lastCut;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for the zone apex keyset.
|
// 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
|
// if we have ksks, sign the keyset with them, otherwise we will just sign
|
||||||
// them with the zsks.
|
// them with the zsks.
|
||||||
if (kskpairs != null && kskpairs.size() > 0) {
|
|
||||||
List<RRSIGRecord> sigs = signRRset(rrset, kskpairs, start, expire);
|
List<RRSIGRecord> sigs = signRRset(rrset, kskpairs, start, expire);
|
||||||
toList.addAll(sigs);
|
toList.addAll(sigs);
|
||||||
|
|
||||||
// If we aren't going to sign with all the keys, bail out now.
|
// If we aren't going to sign with all the keys, bail out now.
|
||||||
if (!fullySignKeyset)
|
if (!fullySignKeyset)
|
||||||
return last_cut;
|
return lastCut;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, we are OK to sign this set.
|
// otherwise, we are OK to sign this set.
|
||||||
List<RRSIGRecord> sigs = signRRset(rrset, zskpairs, start, expire);
|
List<RRSIGRecord> sigs = signRRset(rrset, zskpairs, start, expire);
|
||||||
toList.addAll(sigs);
|
toList.addAll(sigs);
|
||||||
|
|
||||||
return last_cut;
|
return lastCut;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Various NSEC/NSEC3 generation modes
|
// 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
|
* Opt-Out, etc.) External users of this class are expected to use the
|
||||||
* appropriate public signZone* methods instead of this.
|
* appropriate public signZone* methods instead of this.
|
||||||
*
|
*
|
||||||
* @param zonename
|
* @param zonename The name of the zone
|
||||||
* The name of the zone
|
* @param records The records comprising the zone. They do not have to
|
||||||
* @param records
|
* be in any particular order, as this method will
|
||||||
* The records comprising the zone. They do not have to
|
* order them as necessary.
|
||||||
* be in any
|
* @param kskpairs The key pairs designated as "key signing keys"
|
||||||
* particular order, as this method will order them as
|
* @param zskpairs The key pairs designated as "zone signing keys"
|
||||||
* necessary.
|
* @param start The RRSIG inception time
|
||||||
* @param kskpairs
|
* @param expire The RRSIG expiration time
|
||||||
* The key pairs designated as "key signing keys"
|
* @param fullySignKeyset If true, all keys (ksk or zsk) will sign the DNSKEY
|
||||||
* @param zskpairs
|
* RRset. If false, only the ksks will sign it.
|
||||||
* The key pairs designated as "zone signing keys"
|
* @param dsDigestAlg The hash algorithm to use for generating DS records
|
||||||
* @param start
|
|
||||||
* The RRSIG inception time
|
|
||||||
* @param expire
|
|
||||||
* The RRSIG expiration time
|
|
||||||
* @param fullySignKeyset
|
|
||||||
* If true, all keys (ksk or zsk) will sign the DNSKEY
|
|
||||||
* RRset. If
|
|
||||||
* false, only the ksks will sign it.
|
|
||||||
* @param ds_digest_alg
|
|
||||||
* The hash algorithm to use for generating DS records
|
|
||||||
* (DSRecord.SHA1_DIGEST_ID, e.g.)
|
* (DSRecord.SHA1_DIGEST_ID, e.g.)
|
||||||
* @param mode
|
* @param mode The NSEC/NSEC3 generation mode: NSEC_MODE,
|
||||||
* The NSEC/NSEC3 generation mode: NSEC_MODE, NSEC3_MODE,
|
* NSEC3_MODE, NSEC3_OPTOUT_MODE, etc.
|
||||||
* NSEC3_OPTOUT_MODE, etc.
|
* @param includedNames When using an Opt-In/Opt-Out mode, the names listed
|
||||||
* @param includedNames
|
* here will be included in the NSEC/NSEC3 chain
|
||||||
* When using an Opt-In/Opt-Out mode, the names listed
|
* regardless
|
||||||
* here will be
|
* @param salt When using an NSEC3 mode, use this salt.
|
||||||
* included in the NSEC/NSEC3 chain regardless
|
* @param iterations When using an NSEC3 mode, use this number of
|
||||||
* @param salt
|
|
||||||
* When using an NSEC3 mode, use this salt.
|
|
||||||
* @param iterations
|
|
||||||
* When using an NSEC3 mode, use this number of
|
|
||||||
* iterations
|
* iterations
|
||||||
* @param beConservative
|
* @param beConservative If true, then only turn on the Opt-In flag when
|
||||||
* If true, then only turn on the Opt-In flag when there
|
* there are insecure delegations in the span.
|
||||||
* are insecure
|
* Currently this only works for NSEC_EXP_OPT_IN mode.
|
||||||
* delegations in the span. Currently this only works for
|
* @param nsec3paramttl The TTL to use for the generated NSEC3PARAM record.
|
||||||
* NSEC_EXP_OPT_IN mode.
|
* 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,
|
* @return an ordered list of {@link org.xbill.DNS.Record} objects,
|
||||||
* representing the signed zone.
|
* representing the signed zone.
|
||||||
*
|
*
|
||||||
@ -363,7 +319,7 @@ public class JCEDnsSecSigner {
|
|||||||
private List<Record> signZone(Name zonename, List<Record> records,
|
private List<Record> signZone(Name zonename, List<Record> records,
|
||||||
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs,
|
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs,
|
||||||
Instant start, Instant expire, boolean fullySignKeyset,
|
Instant start, Instant expire, boolean fullySignKeyset,
|
||||||
int ds_digest_alg, int mode, List<Name> includedNames,
|
int dsDigestAlg, int mode, List<Name> includedNames,
|
||||||
byte[] salt, int iterations, long nsec3paramttl,
|
byte[] salt, int iterations, long nsec3paramttl,
|
||||||
boolean beConservative) throws IOException,
|
boolean beConservative) throws IOException,
|
||||||
GeneralSecurityException {
|
GeneralSecurityException {
|
||||||
@ -380,7 +336,7 @@ public class JCEDnsSecSigner {
|
|||||||
|
|
||||||
// Generate DS records. This replaces any non-zone-apex DNSKEY RRs with DS
|
// Generate DS records. This replaces any non-zone-apex DNSKEY RRs with DS
|
||||||
// RRs.
|
// RRs.
|
||||||
SignUtils.generateDSRecords(zonename, records, ds_digest_alg);
|
SignUtils.generateDSRecords(zonename, records, dsDigestAlg);
|
||||||
|
|
||||||
// Generate the NSEC or NSEC3 records based on 'mode'
|
// Generate the NSEC or NSEC3 records based on 'mode'
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
@ -398,6 +354,8 @@ public class JCEDnsSecSigner {
|
|||||||
SignUtils.generateOptInNSECRecords(zonename, records, includedNames,
|
SignUtils.generateOptInNSECRecords(zonename, records, includedNames,
|
||||||
beConservative);
|
beConservative);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
throw new NoSuchAlgorithmException("Unknown NSEC/NSEC3 mode: " + mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-sort so we can assemble into rrsets.
|
// Re-sort so we can assemble into rrsets.
|
||||||
@ -405,9 +363,9 @@ public class JCEDnsSecSigner {
|
|||||||
|
|
||||||
// Assemble into RRsets and sign.
|
// Assemble into RRsets and sign.
|
||||||
RRset rrset = new RRset();
|
RRset rrset = new RRset();
|
||||||
ArrayList<Record> signed_records = new ArrayList<Record>();
|
ArrayList<Record> signedRecords = new ArrayList<>();
|
||||||
Name last_cut = null;
|
Name lastCut = null;
|
||||||
Name last_dname = null;
|
Name lastDname = null;
|
||||||
|
|
||||||
for (ListIterator<Record> i = records.listIterator(); i.hasNext();) {
|
for (ListIterator<Record> i = records.listIterator(); i.hasNext();) {
|
||||||
Record r = i.next();
|
Record r = i.next();
|
||||||
@ -430,48 +388,38 @@ public class JCEDnsSecSigner {
|
|||||||
|
|
||||||
// add the RRset to the list of signed_records, regardless of
|
// add the RRset to the list of signed_records, regardless of
|
||||||
// whether or not we actually end up signing the set.
|
// whether or not we actually end up signing the set.
|
||||||
last_cut = addRRset(signed_records, zonename, rrset, kskpairs, zskpairs, start,
|
lastCut = addRRset(signedRecords, zonename, rrset, kskpairs, zskpairs, start,
|
||||||
expire, fullySignKeyset, last_cut, last_dname);
|
expire, fullySignKeyset, lastCut, lastDname);
|
||||||
if (rrset.getType() == Type.DNAME)
|
if (rrset.getType() == Type.DNAME)
|
||||||
last_dname = rrset.getName();
|
lastDname = rrset.getName();
|
||||||
|
|
||||||
rrset.clear();
|
rrset.clear();
|
||||||
rrset.addRR(r);
|
rrset.addRR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the last RR set
|
// add the last RR set
|
||||||
addRRset(signed_records, zonename, rrset, kskpairs, zskpairs, start, expire,
|
addRRset(signedRecords, zonename, rrset, kskpairs, zskpairs, start, expire,
|
||||||
fullySignKeyset, last_cut, last_dname);
|
fullySignKeyset, lastCut, lastDname);
|
||||||
|
|
||||||
return signed_records;
|
return signedRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a zone, sign it using standard NSEC records.
|
* Given a zone, sign it using standard NSEC records.
|
||||||
*
|
*
|
||||||
* @param zonename
|
* @param zonename The name of the zone.
|
||||||
* The name of the zone.
|
* @param records The records comprising the zone. They do not have to
|
||||||
* @param records
|
* be in any particular order, as this method will
|
||||||
* The records comprising the zone. They do not have to
|
* order them as necessary.
|
||||||
* be in any
|
* @param kskpairs The key pairs that are designated as "key signing
|
||||||
* particular order, as this method will order them as
|
|
||||||
* necessary.
|
|
||||||
* @param kskpairs
|
|
||||||
* The key pairs that are designated as "key signing
|
|
||||||
* keys".
|
* keys".
|
||||||
* @param zskpairs
|
* @param zskpairs This key pairs that are designated as "zone signing
|
||||||
* This key pairs that are designated as "zone signing
|
|
||||||
* keys".
|
* keys".
|
||||||
* @param start
|
* @param start The RRSIG inception time.
|
||||||
* The RRSIG inception time.
|
* @param expire The RRSIG expiration time.
|
||||||
* @param expire
|
* @param fullySignKeyset Sign the zone apex keyset with all available keys
|
||||||
* The RRSIG expiration time.
|
* (instead of just the key signing keys).
|
||||||
* @param fullySignKeyset
|
* @param dsDigestAlg The digest algorithm to use when generating DS
|
||||||
* Sign the zone apex keyset with all available keys
|
|
||||||
* (instead of just
|
|
||||||
* the key signing keys).
|
|
||||||
* @param ds_digest_alg
|
|
||||||
* The digest algorithm to use when generating DS
|
|
||||||
* records.
|
* records.
|
||||||
*
|
*
|
||||||
* @return an ordered list of {@link org.xbill.DNS.Record} objects,
|
* @return an ordered list of {@link org.xbill.DNS.Record} objects,
|
||||||
@ -480,58 +428,42 @@ public class JCEDnsSecSigner {
|
|||||||
public List<Record> signZone(Name zonename, List<Record> records,
|
public List<Record> signZone(Name zonename, List<Record> records,
|
||||||
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs,
|
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs,
|
||||||
Instant start, Instant expire, boolean fullySignKeyset,
|
Instant start, Instant expire, boolean fullySignKeyset,
|
||||||
int ds_digest_alg) throws IOException,
|
int dsDigestAlg) throws IOException,
|
||||||
GeneralSecurityException {
|
GeneralSecurityException {
|
||||||
return signZone(zonename, records, kskpairs, zskpairs, start, expire,
|
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.
|
* Given a zone, sign it using NSEC3 records.
|
||||||
*
|
*
|
||||||
* @param signer
|
* @param signer A signer (utility) object used to actually sign
|
||||||
* A signer (utility) object used to actually sign stuff.
|
* stuff.
|
||||||
* @param zonename
|
* @param zonename The name of the zone being signed.
|
||||||
* The name of the zone being signed.
|
* @param records The records comprising the zone. They do not have to
|
||||||
* @param records
|
* be in any particular order, as this method will
|
||||||
* The records comprising the zone. They do not have to
|
* order them as necessary.
|
||||||
* be in any
|
* @param kskpairs The key pairs that are designated as "key signing
|
||||||
* particular order, as this method will order them as
|
|
||||||
* necessary.
|
|
||||||
* @param kskpairs
|
|
||||||
* The key pairs that are designated as "key signing
|
|
||||||
* keys".
|
* keys".
|
||||||
* @param zskpairs
|
* @param zskpairs This key pairs that are designated as "zone signing
|
||||||
* This key pairs that are designated as "zone signing
|
|
||||||
* keys".
|
* keys".
|
||||||
* @param start
|
* @param start The RRSIG inception time.
|
||||||
* The RRSIG inception time.
|
* @param expire The RRSIG expiration time.
|
||||||
* @param expire
|
* @param fullySignKeyset If true then the DNSKEY RRset will be signed by all
|
||||||
* The RRSIG expiration time.
|
* available keys, if false, only the key signing keys.
|
||||||
* @param fullySignKeyset
|
* @param useOptOut If true, insecure delegations will be omitted from
|
||||||
* If true then the DNSKEY RRset will be signed by all
|
* the NSEC3 chain, and all NSEC3 records will have the
|
||||||
* available
|
* Opt-Out flag set.
|
||||||
* keys, if false, only the key signing keys.
|
* @param includedNames A list of names to include in the NSEC3 chain
|
||||||
* @param useOptOut
|
|
||||||
* If true, insecure delegations will be omitted from the
|
|
||||||
* NSEC3
|
|
||||||
* chain, and all NSEC3 records will have the Opt-Out
|
|
||||||
* flag set.
|
|
||||||
* @param includedNames
|
|
||||||
* A list of names to include in the NSEC3 chain
|
|
||||||
* regardless.
|
* regardless.
|
||||||
* @param salt
|
* @param salt The salt to use for the NSEC3 hashing. null means no
|
||||||
* The salt to use for the NSEC3 hashing. null means no
|
|
||||||
* salt.
|
* salt.
|
||||||
* @param iterations
|
* @param iterations The number of iterations to use for the NSEC3
|
||||||
* The number of iterations to use for the NSEC3 hashing.
|
* hashing.
|
||||||
* @param ds_digest_alg
|
* @param dsDigestAlg The digest algorithm to use when generating DS
|
||||||
* The digest algorithm to use when generating DS
|
|
||||||
* records.
|
* records.
|
||||||
* @param nsec3paramttl
|
* @param nsec3paramttl The TTL to use for the generated NSEC3PARAM record.
|
||||||
* The TTL to use for the generated NSEC3PARAM record.
|
* Negative values will use the SOA TTL.
|
||||||
* Negative
|
|
||||||
* values will use the SOA TTL.
|
|
||||||
* @return an ordered list of {@link org.xbill.DNS.Record} objects,
|
* @return an ordered list of {@link org.xbill.DNS.Record} objects,
|
||||||
* representing the signed zone.
|
* representing the signed zone.
|
||||||
*
|
*
|
||||||
@ -542,16 +474,16 @@ public class JCEDnsSecSigner {
|
|||||||
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs,
|
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs,
|
||||||
Instant start, Instant expire, boolean fullySignKeyset,
|
Instant start, Instant expire, boolean fullySignKeyset,
|
||||||
boolean useOptOut, List<Name> includedNames,
|
boolean useOptOut, List<Name> includedNames,
|
||||||
byte[] salt, int iterations, int ds_digest_alg,
|
byte[] salt, int iterations, int dsDigestAlg,
|
||||||
long nsec3paramttl) throws IOException,
|
long nsec3paramttl) throws IOException,
|
||||||
GeneralSecurityException {
|
GeneralSecurityException {
|
||||||
if (useOptOut) {
|
if (useOptOut) {
|
||||||
return signZone(zonename, records, kskpairs, zskpairs, start, expire,
|
return signZone(zonename, records, kskpairs, zskpairs, start, expire,
|
||||||
fullySignKeyset, ds_digest_alg, NSEC3_OPTOUT_MODE, includedNames,
|
fullySignKeyset, dsDigestAlg, NSEC3_OPTOUT_MODE, includedNames,
|
||||||
salt, iterations, nsec3paramttl, false);
|
salt, iterations, nsec3paramttl, false);
|
||||||
} else {
|
} else {
|
||||||
return signZone(zonename, records, kskpairs, zskpairs, start, expire,
|
return signZone(zonename, records, kskpairs, zskpairs, start, expire,
|
||||||
fullySignKeyset, ds_digest_alg, NSEC3_MODE, null, salt, iterations,
|
fullySignKeyset, dsDigestAlg, NSEC3_MODE, null, salt, iterations,
|
||||||
nsec3paramttl, false);
|
nsec3paramttl, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -560,37 +492,25 @@ public class JCEDnsSecSigner {
|
|||||||
* Given a zone, sign it using experimental Opt-In NSEC records (see RFC
|
* Given a zone, sign it using experimental Opt-In NSEC records (see RFC
|
||||||
* 4956).
|
* 4956).
|
||||||
*
|
*
|
||||||
* @param zonename
|
* @param zonename the name of the zone.
|
||||||
* the name of the zone.
|
* @param records the records comprising the zone. They do not
|
||||||
* @param records
|
* have to be in any particular order, as this
|
||||||
* the records comprising the zone. They do not have
|
* method will order them as necessary.
|
||||||
* to be in any
|
* @param kskpairs the key pairs that are designated as "key
|
||||||
* particular order, as this method will order them
|
|
||||||
* as necessary.
|
|
||||||
* @param kskpairs
|
|
||||||
* the key pairs that are designated as "key signing
|
|
||||||
* keys".
|
|
||||||
* @param zskpairs
|
|
||||||
* this key pairs that are designated as "zone
|
|
||||||
* signing keys".
|
* signing keys".
|
||||||
* @param start
|
* @param zskpairs this key pairs that are designated as "zone
|
||||||
* the RRSIG inception time.
|
* signing keys".
|
||||||
* @param expire
|
* @param start the RRSIG inception time.
|
||||||
* the RRSIG expiration time.
|
* @param expire the RRSIG expiration time.
|
||||||
* @param useConservativeOptIn
|
* @param useConservativeOptIn if true, Opt-In NSEC records will only be
|
||||||
* if true, Opt-In NSEC records will only be
|
* generated if there are insecure, unsigned
|
||||||
* generated if there are
|
* delegations in the span.
|
||||||
* insecure, unsigned delegations in the span.
|
* @param fullySignKeyset sign the zone apex keyset with all available
|
||||||
* @param fullySignKeyset
|
|
||||||
* sign the zone apex keyset with all available
|
|
||||||
* keys.
|
* keys.
|
||||||
* @param ds_digest_alg
|
* @param dsDigestAlg The digest algorithm to use when generating DS
|
||||||
* The digest algorithm to use when generating DS
|
|
||||||
* records.
|
* records.
|
||||||
* @param NSECIncludeNames
|
* @param nsecIncludeNames names that are to be included in the NSEC chain
|
||||||
* names that are to be included in the NSEC chain
|
* regardless. This may be null.
|
||||||
* regardless. This
|
|
||||||
* may be null.
|
|
||||||
* @return an ordered list of {@link org.xbill.DNS.Record} objects,
|
* @return an ordered list of {@link org.xbill.DNS.Record} objects,
|
||||||
* representing the signed zone.
|
* representing the signed zone.
|
||||||
*/
|
*/
|
||||||
@ -598,12 +518,12 @@ public class JCEDnsSecSigner {
|
|||||||
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs,
|
List<DnsKeyPair> kskpairs, List<DnsKeyPair> zskpairs,
|
||||||
Instant start, Instant expire,
|
Instant start, Instant expire,
|
||||||
boolean useConservativeOptIn,
|
boolean useConservativeOptIn,
|
||||||
boolean fullySignKeyset, List<Name> NSECIncludeNames,
|
boolean fullySignKeyset, List<Name> nsecIncludeNames,
|
||||||
int ds_digest_alg) throws IOException,
|
int dsDigestAlg) throws IOException,
|
||||||
GeneralSecurityException {
|
GeneralSecurityException {
|
||||||
|
|
||||||
return signZone(zonename, records, kskpairs, zskpairs, start, expire,
|
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);
|
null, 0, 0, useConservativeOptIn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import org.xbill.DNS.Type;
|
|||||||
|
|
||||||
public class RecordComparator implements Comparator<Record> {
|
public class RecordComparator implements Comparator<Record> {
|
||||||
public RecordComparator() {
|
public RecordComparator() {
|
||||||
|
// nothing to initialize
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,15 +66,15 @@ public class RecordComparator implements Comparator<Record> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int compareRDATA(Record a, Record b) {
|
private int compareRDATA(Record a, Record b) {
|
||||||
byte[] a_rdata = a.rdataToWireCanonical();
|
byte[] aRdata = a.rdataToWireCanonical();
|
||||||
byte[] b_rdata = b.rdataToWireCanonical();
|
byte[] bRdata = b.rdataToWireCanonical();
|
||||||
|
|
||||||
for (int i = 0; i < a_rdata.length && i < b_rdata.length; i++) {
|
for (int i = 0; i < aRdata.length && i < bRdata.length; i++) {
|
||||||
int n = (a_rdata[i] & 0xFF) - (b_rdata[i] & 0xFF);
|
int n = (aRdata[i] & 0xFF) - (bRdata[i] & 0xFF);
|
||||||
if (n != 0)
|
if (n != 0)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
return (a_rdata.length - b_rdata.length);
|
return (aRdata.length - bRdata.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compare(Record a, Record b) {
|
public int compare(Record a, Record b) {
|
||||||
@ -88,27 +89,27 @@ public class RecordComparator implements Comparator<Record> {
|
|||||||
if (res != 0)
|
if (res != 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
int a_type = a.getType();
|
int aType = a.getType();
|
||||||
int b_type = b.getType();
|
int bType = b.getType();
|
||||||
int sig_type = 0;
|
int sigType = 0;
|
||||||
|
|
||||||
if (a_type == Type.RRSIG) {
|
if (aType == Type.RRSIG) {
|
||||||
a_type = ((RRSIGRecord) a).getTypeCovered();
|
aType = ((RRSIGRecord) a).getTypeCovered();
|
||||||
if (b_type != Type.RRSIG)
|
if (bType != Type.RRSIG)
|
||||||
sig_type = 1;
|
sigType = 1;
|
||||||
}
|
}
|
||||||
if (b_type == Type.RRSIG) {
|
if (bType == Type.RRSIG) {
|
||||||
b_type = ((RRSIGRecord) b).getTypeCovered();
|
bType = ((RRSIGRecord) b).getTypeCovered();
|
||||||
if (a.getType() != Type.RRSIG)
|
if (a.getType() != Type.RRSIG)
|
||||||
sig_type = -1;
|
sigType = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = compareTypes(a_type, b_type);
|
res = compareTypes(aType, bType);
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
if (sig_type != 0)
|
if (sigType != 0)
|
||||||
return sig_type;
|
return sigType;
|
||||||
|
|
||||||
return compareRDATA(a, b);
|
return compareRDATA(a, b);
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -37,7 +37,7 @@ public class TypeMap {
|
|||||||
private Set<Integer> typeSet;
|
private Set<Integer> typeSet;
|
||||||
|
|
||||||
public TypeMap() {
|
public TypeMap() {
|
||||||
this.typeSet = new HashSet<Integer>();
|
this.typeSet = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Add the given type to the typemap. */
|
/** Add the given type to the typemap. */
|
||||||
@ -78,20 +78,20 @@ public class TypeMap {
|
|||||||
TypeMap typemap = new TypeMap();
|
TypeMap typemap = new TypeMap();
|
||||||
|
|
||||||
int page;
|
int page;
|
||||||
int byte_length;
|
int byteLength;
|
||||||
|
|
||||||
while (m < map.length) {
|
while (m < map.length) {
|
||||||
page = map[m++];
|
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++) {
|
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);
|
typemap.set((page << 8) + (i * 8) + j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m += byte_length;
|
m += byteLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
return typemap;
|
return typemap;
|
||||||
@ -115,7 +115,7 @@ public class TypeMap {
|
|||||||
int[] types = getTypes();
|
int[] types = getTypes();
|
||||||
Arrays.sort(types);
|
Arrays.sort(types);
|
||||||
|
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
for (int i = 0; i < types.length; i++) {
|
for (int i = 0; i < types.length; i++) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
@ -129,16 +129,16 @@ public class TypeMap {
|
|||||||
protected static void mapToWire(DNSOutput out, int[] types, int base, int start, int end) {
|
protected static void mapToWire(DNSOutput out, int[] types, int base, int start, int end) {
|
||||||
// calculate the length of this map by looking at the largest
|
// calculate the length of this map by looking at the largest
|
||||||
// typecode in this section.
|
// typecode in this section.
|
||||||
int max_type = types[end - 1] & 0xFF;
|
int maxType = types[end - 1] & 0xFF;
|
||||||
int map_length = (max_type / 8) + 1;
|
int mapLength = (maxType / 8) + 1;
|
||||||
|
|
||||||
// write the map "header" -- the base and the length of the map.
|
// write the map "header" -- the base and the length of the map.
|
||||||
out.writeU8(base & 0xFF);
|
out.writeU8(base & 0xFF);
|
||||||
out.writeU8(map_length & 0xFF);
|
out.writeU8(mapLength & 0xFF);
|
||||||
|
|
||||||
// allocate a temporary scratch space for caculating the actual
|
// allocate a temporary scratch space for caculating the actual
|
||||||
// bitmap.
|
// bitmap.
|
||||||
byte[] map = new byte[map_length];
|
byte[] map = new byte[mapLength];
|
||||||
|
|
||||||
// for each type in our sub-array, set its corresponding bit in the map.
|
// for each type in our sub-array, set its corresponding bit in the map.
|
||||||
for (int i = start; i < end; i++) {
|
for (int i = start; i < end; i++) {
|
||||||
@ -179,7 +179,7 @@ public class TypeMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int[] getTypes() {
|
public int[] getTypes() {
|
||||||
Integer[] a = (Integer[]) typeSet.toArray(integerArray);
|
Integer[] a = typeSet.toArray(integerArray);
|
||||||
|
|
||||||
int[] res = new int[a.length];
|
int[] res = new int[a.length];
|
||||||
for (int i = 0; i < res.length; i++) {
|
for (int i = 0; i < res.length; i++) {
|
||||||
@ -189,8 +189,8 @@ public class TypeMap {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int[] fromWireToTypes(byte[] wire_fmt) {
|
public static int[] fromWireToTypes(byte[] wireFmt) {
|
||||||
return TypeMap.fromBytes(wire_fmt).getTypes();
|
return TypeMap.fromBytes(wireFmt).getTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] fromTypesToWire(int[] types) {
|
public static byte[] fromTypesToWire(int[] types) {
|
||||||
|
@ -39,6 +39,10 @@ import org.xbill.DNS.Type;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class ZoneUtils {
|
public class ZoneUtils {
|
||||||
|
|
||||||
|
private ZoneUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a zone file.
|
* Load a zone file.
|
||||||
*
|
*
|
||||||
@ -53,19 +57,10 @@ public class ZoneUtils {
|
|||||||
* if something goes wrong reading the zone file.
|
* if something goes wrong reading the zone file.
|
||||||
*/
|
*/
|
||||||
public static List<Record> readZoneFile(String zonefile, Name origin) throws IOException {
|
public static List<Record> readZoneFile(String zonefile, Name origin) throws IOException {
|
||||||
ArrayList<Record> records = new ArrayList<Record>();
|
ArrayList<Record> records = new ArrayList<>();
|
||||||
Master m;
|
try (Master m = zonefile.equals("-") ? new Master(System.in) : new Master(zonefile, origin)) {
|
||||||
try {
|
|
||||||
if (zonefile.equals("-")) {
|
|
||||||
m = new Master(System.in);
|
|
||||||
} else {
|
|
||||||
m = new Master(zonefile, origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
Record r = null;
|
Record r = null;
|
||||||
|
|
||||||
while ((r = m.nextRecord()) != null) {
|
while ((r = m.nextRecord()) != null) {
|
||||||
|
|
||||||
records.add(r);
|
records.add(r);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -120,7 +115,7 @@ public class ZoneUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static List<Record> findRRs(List<Record> records, Name name, int type) {
|
public static List<Record> findRRs(List<Record> records, Name name, int type) {
|
||||||
List<Record> res = new ArrayList<Record>();
|
List<Record> res = new ArrayList<>();
|
||||||
for (Record r : records) {
|
for (Record r : records) {
|
||||||
if (r.getName().equals(name) && r.getType() == type) {
|
if (r.getName().equals(name) && r.getType() == type) {
|
||||||
res.add(r);
|
res.add(r);
|
||||||
|
@ -88,10 +88,12 @@ public class ZoneVerifier {
|
|||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return super.equals(o);
|
return super.equals(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return super.hashCode();
|
return super.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean getMark() {
|
boolean getMark() {
|
||||||
return mIsMarked;
|
return mIsMarked;
|
||||||
}
|
}
|
||||||
@ -148,7 +150,8 @@ public class ZoneVerifier {
|
|||||||
/**
|
/**
|
||||||
* Add a record to the various maps.
|
* Add a record to the various maps.
|
||||||
*
|
*
|
||||||
* @return true if the RR was added, false if it wasn't (because it was a duplicate)
|
* @return true if the RR was added, false if it wasn't (because it was a
|
||||||
|
* duplicate)
|
||||||
*/
|
*/
|
||||||
private boolean addRR(Record r) {
|
private boolean addRR(Record r) {
|
||||||
Name n = r.getName();
|
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
|
* Given an unsorted list of records, load the node and rrset maps, as well as
|
||||||
* determine the NSEC3 parameters and signing type.
|
* determine the NSEC3 parameters and signing type.
|
||||||
*
|
*
|
||||||
* @param records
|
* @param records an unsorted list of {@link org.xbill.DNS.Record} objects.
|
||||||
* @return the number of errors encountered.
|
* @return the number of errors encountered.
|
||||||
*/
|
*/
|
||||||
private int calculateNodes(List<Record> records) {
|
private int calculateNodes(List<Record> records) {
|
||||||
@ -251,7 +254,7 @@ public class ZoneVerifier {
|
|||||||
* Given a name, typeset, and name of the last zone cut, determine the node
|
* Given a name, typeset, and name of the last zone cut, determine the node
|
||||||
* type.
|
* type.
|
||||||
*/
|
*/
|
||||||
private NodeType determineNodeType(Name n, Set<Integer> typeset, Name last_cut) {
|
private NodeType determineNodeType(Name n, Set<Integer> typeset, Name lastCut) {
|
||||||
// All RRs at the zone apex are normal
|
// All RRs at the zone apex are normal
|
||||||
if (n.equals(mZoneName))
|
if (n.equals(mZoneName))
|
||||||
return NodeType.NORMAL;
|
return NodeType.NORMAL;
|
||||||
@ -263,7 +266,7 @@ public class ZoneVerifier {
|
|||||||
}
|
}
|
||||||
// If the node is below a zone cut (either a delegation or DNAME), it is
|
// If the node is below a zone cut (either a delegation or DNAME), it is
|
||||||
// glue.
|
// glue.
|
||||||
if (last_cut != null && n.subdomain(last_cut) && !n.equals(last_cut)) {
|
if (lastCut != null && n.subdomain(lastCut) && !n.equals(lastCut)) {
|
||||||
return NodeType.GLUE;
|
return NodeType.GLUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,13 +297,13 @@ public class ZoneVerifier {
|
|||||||
*/
|
*/
|
||||||
private int processNodes() throws NoSuchAlgorithmException, TextParseException {
|
private int processNodes() throws NoSuchAlgorithmException, TextParseException {
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
Name last_cut = null;
|
Name lastCut = null;
|
||||||
|
|
||||||
for (Map.Entry<Name, Set<Integer>> entry : mNodeMap.entrySet()) {
|
for (Map.Entry<Name, Set<Integer>> entry : mNodeMap.entrySet()) {
|
||||||
Name n = entry.getKey();
|
Name n = entry.getKey();
|
||||||
Set<Integer> typeset = entry.getValue();
|
Set<Integer> typeset = entry.getValue();
|
||||||
|
|
||||||
NodeType ntype = determineNodeType(n, typeset, last_cut);
|
NodeType ntype = determineNodeType(n, typeset, lastCut);
|
||||||
log.finest("Node " + n + " is type " + ntype);
|
log.finest("Node " + n + " is type " + ntype);
|
||||||
|
|
||||||
// we can ignore glue/invalid RRs.
|
// we can ignore glue/invalid RRs.
|
||||||
@ -309,7 +312,7 @@ public class ZoneVerifier {
|
|||||||
|
|
||||||
// record the last zone cut if this node is a zone cut.
|
// record the last zone cut if this node is a zone cut.
|
||||||
if (ntype == NodeType.DELEGATION || typeset.contains(Type.DNAME)) {
|
if (ntype == NodeType.DELEGATION || typeset.contains(Type.DNAME)) {
|
||||||
last_cut = n;
|
lastCut = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check all of the RRsets that should be signed
|
// check all of the RRsets that should be signed
|
||||||
|
Loading…
Reference in New Issue
Block a user