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:
David Blacka 2024-03-30 22:21:32 -04:00 committed by GitHub
parent 6118ae718e
commit 2876649a4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 1008 additions and 1574 deletions

6
.gitattributes vendored
View File

@ -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

View File

@ -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')
}

View File

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

View File

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

Binary file not shown.

View File

@ -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
View File

@ -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
View File

@ -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

Binary file not shown.

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,7 +34,6 @@ import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.spec.ECFieldFp;
@ -43,6 +42,7 @@ import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.NamedParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.Arrays;
import java.util.HashMap;
@ -51,12 +51,6 @@ import java.util.logging.Logger;
import org.xbill.DNS.DNSSEC;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
// for now, we need to import the EdDSA parameter spec classes
// because they have no generic form in java.security.spec.*
// sadly, this will currently fail if you don't have the lib.
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
/**
* This class handles translating DNS signing algorithm identifiers into various
* usable java implementations.
@ -72,21 +66,24 @@ public class DnsKeyAlgorithm {
// Our base algorithm numbers. This is a normalization of the DNSSEC
// algorithms (which are really signature algorithms). Thus RSASHA1,
// RSASHA256, etc. all boil down to 'RSA' here.
public static final int UNKNOWN = -1;
public static final int RSA = 1;
public static final int DH = 2;
public static final int DSA = 3;
public static final int ECC_GOST = 4;
public static final int ECDSA = 5;
public static final int EDDSA = 6;
// RSASHA256, etc. all boil down to 'RSA' here. Similarly, ECDSAP256SHA256 and
// ECDSAP384SHA384 both become 'ECDSA'.
public enum BaseAlgorithm {
UNKNOWN,
RSA,
DH,
DSA,
ECC_GOST,
ECDSA,
EDDSA;
}
private static class AlgEntry {
public int dnssecAlgorithm;
public String sigName;
public int baseType;
public BaseAlgorithm baseType;
public AlgEntry(int algorithm, String sigName, int baseType) {
public AlgEntry(int algorithm, String sigName, BaseAlgorithm baseType) {
this.dnssecAlgorithm = algorithm;
this.sigName = sigName;
this.baseType = baseType;
@ -96,18 +93,20 @@ public class DnsKeyAlgorithm {
private static class ECAlgEntry extends AlgEntry {
public ECParameterSpec ecSpec;
public ECAlgEntry(int algorithm, String sigName, int baseType, ECParameterSpec spec) {
public ECAlgEntry(int algorithm, String sigName, BaseAlgorithm baseType, ECParameterSpec spec) {
super(algorithm, sigName, baseType);
this.ecSpec = spec;
}
}
private static class EdAlgEntry extends AlgEntry {
public EdDSAParameterSpec edSpec;
public String curveName;
public NamedParameterSpec paramSpec;
public EdAlgEntry(int algorithm, String sigName, int baseType, EdDSAParameterSpec spec) {