20 Commits
0.13 ... v0.15

Author SHA1 Message Date
David Blacka
9004a33d51 Exit with non-zero with exception. Fix dnsjava lib.
It is unclear how we got the version of dnsjava that was checked in.
The same version build from the jdnssec-dnsjava repo was different.
This fixes the "missing CAA" support issue.
2019-02-26 14:26:18 +00:00
David Blacka
0aca329f85 Remove verisignlabs.com website for now
The verisignlabs.com website is non-functional.  Everything is actually here on github.com, though.
2019-01-30 11:37:34 -05:00
David Blacka
507dad3580 Update changelog with release 2018-11-16 15:54:09 +00:00
David Blacka
7d27694d9a Some DNSKeyAlgorithm class cleanup 2018-11-16 13:57:16 +00:00
David Blacka
62b5b0ad23 Updates for gradle; changelog 2018-07-23 19:17:23 +00:00
David Blacka
c37f436e72 Merge branch 'alg-15-support' of https://github.com/pallaviaras/jdnssec-tools into pallaviaras-alg-15-support 2018-07-15 16:57:59 +00:00
David Blacka
781e775b3b Use the actual private key for ed25519 2018-07-15 16:56:15 +00:00
Pallavi
d0e85431c5 Added support for gradle and restructured the source code directory from src to src/main/java directory 2018-07-15 10:59:40 -04:00
David Blacka
55a139db82 Allow for epoch start/expire times; add verboseSigning to jdnssec-signrrset 2018-07-15 14:57:41 +00:00
David Blacka
b291bb430b Use correct encoding for the alg 15 DNSKEYRecord 2018-07-15 12:17:12 +00:00
David Blacka
a9353b3af3 Now able to generated alg 15 keypairs
They _look_ correct, but may not be.
2018-07-15 00:54:10 +00:00
David Blacka
7706b73d8c Start of alg 15/16 support 2018-07-14 22:06:49 +00:00
252c44a155 Merge pull request #6 from chkal/jdk7
Set javac options for source and target to JDK7
2018-03-10 14:26:27 -05:00
Christian Kaltepoth
a7743fa18c Set javac options for source and target to JDK7 2018-02-28 08:47:40 +01:00
4853426d6c Merge pull request #5 from PowerDNS/failure-exit
exit(1) if the zone had errors
2017-06-23 09:55:52 -04:00
de2216f259 Merge pull request #4 from PowerDNS/ecdsa-pad
fix leading zero padding in ECDSA sig conversion
2017-06-23 09:55:28 -04:00
Peter van Dijk
b19bc5ffa3 exit(1) if the zone had errors 2017-06-22 14:34:14 +02:00
Kees Monshouwer
517975ef93 update ChangeLog 2017-06-22 14:32:20 +02:00
Kees Monshouwer
ca2a932485 fix multiple leading zeros padding in ECDSA sig conversion 2017-06-22 14:32:14 +02:00
Peter van Dijk
171594a92d fix leading zero padding in ECDSA sig conversion 2017-02-28 12:24:00 +01:00
43 changed files with 666 additions and 74 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
build build
.classpath .classpath
.project .project
.gradle
jdnssec-tools*.tar.gz jdnssec-tools*.tar.gz
docs docs

View File

@@ -1,3 +1,30 @@
2019-02-26 David Blacka <davidb@verisign.com>
* Released version 0.15
* Ensure when a command line tool throws an exception it exits
with a non-zero exit code.
* Update local dnsjava jar to match actual build for
jdnssec-dnsjava.
2018-11-16 David Blacka <davidb@verisign.com>
* Released version 0.14
2018-07-15 Pallavi Aras
* Add Gradle build support. Adjust ant to use same paths.
2018-07-15 David Blacka <davidb@versigin.com
* Add algorithm 15 support. This included adding a public domain
EdDSA library to the distribution.
* Add minor feature to specify signature inception and expiration
times as UNIX epoch time values.
2017-06-22 Peter van Dijk <peter.van.dijk@powerdns.com>, Kees Monshouwer <mind04@monshouwer.eu>
* Fix leading zero(s) padding in ECDSA sig conversion
2017-01-06 David Blacka <davidb@verisign.com> 2017-01-06 David Blacka <davidb@verisign.com>
* Released version 0.13 * Released version 0.13

View File

@@ -1,6 +1,5 @@
# jdnssec-tools # jdnssec-tools
* http://www.verisignlabs.com/jdnssec-tools/
* https://github.com/dblacka/jdnssec-tools/wiki * https://github.com/dblacka/jdnssec-tools/wiki
Author: David Blacka (davidb@verisign.com) Author: David Blacka (davidb@verisign.com)
@@ -36,6 +35,11 @@ Building from source:
4. You can build the distribution tarballs with 'ant dist'. You can run the tools directly from the build area (without building the jdnssec-tools.jar file) by using the ./bin/_jdnssec_* wrappers. 4. You can build the distribution tarballs with 'ant dist'. You can run the tools directly from the build area (without building the jdnssec-tools.jar file) by using the ./bin/_jdnssec_* wrappers.
5. Build the project using gradle
./gradlew clean
./gradlew assemble -i
jar file gets generated in build/libs
The source for this project is available in git on github: https://github.com/dblacka/jdnssec-tools The source for this project is available in git on github: https://github.com/dblacka/jdnssec-tools

View File

@@ -1 +1 @@
version=0.13 version=0.15

View File

@@ -9,7 +9,7 @@ if [ $ulimit_max != "unlimited" ]; then
fi fi
# set the classpath # set the classpath
for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/lib/*.jar; do for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/libs/*.jar; do
CLASSPATH="$CLASSPATH":"$i" CLASSPATH="$CLASSPATH":"$i"
done done
export CLASSPATH export CLASSPATH

View File

@@ -9,7 +9,7 @@ if [ $ulimit_max != "unlimited" ]; then
fi fi
# set the classpath # set the classpath
for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/lib/*.jar; do for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/libs/*.jar; do
CLASSPATH="$CLASSPATH":"$i" CLASSPATH="$CLASSPATH":"$i"
done done
export CLASSPATH export CLASSPATH

View File

@@ -4,7 +4,7 @@ thisdir=`dirname $0`
basedir=`cd $thisdir/..; pwd` basedir=`cd $thisdir/..; pwd`
# set the classpath # set the classpath
for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/lib/*.jar; do for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/libs/*.jar; do
CLASSPATH="$CLASSPATH":"$i" CLASSPATH="$CLASSPATH":"$i"
done done
export CLASSPATH export CLASSPATH

View File

@@ -4,7 +4,7 @@ thisdir=`dirname $0`
basedir=`cd $thisdir/..; pwd` basedir=`cd $thisdir/..; pwd`
# set the classpath # set the classpath
for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/lib/*.jar; do for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/libs/*.jar; do
CLASSPATH="$CLASSPATH":"$i" CLASSPATH="$CLASSPATH":"$i"
done done
export CLASSPATH export CLASSPATH

View File

@@ -9,7 +9,7 @@ if [ $ulimit_max != "unlimited" ]; then
fi fi
# set the classpath # set the classpath
for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/lib/*.jar; do for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/libs/*.jar; do
CLASSPATH="$CLASSPATH":"$i" CLASSPATH="$CLASSPATH":"$i"
done done
export CLASSPATH export CLASSPATH

View File

@@ -9,7 +9,7 @@ if [ $ulimit_max != "unlimited" ]; then
fi fi
# set the classpath # set the classpath
for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/lib/*.jar; do for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/libs/*.jar; do
CLASSPATH="$CLASSPATH":"$i" CLASSPATH="$CLASSPATH":"$i"
done done
export CLASSPATH export CLASSPATH

View File

@@ -9,7 +9,7 @@ if [ $ulimit_max != "unlimited" ]; then
fi fi
# set the classpath # set the classpath
for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/lib/*.jar; do for i in $basedir/lib/*.jar $basedir/lib/*.zip $basedir/build/libs/*.jar; do
CLASSPATH="$CLASSPATH":"$i" CLASSPATH="$CLASSPATH":"$i"
done done
export CLASSPATH export CLASSPATH

25
build.gradle Normal file
View File

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

View File

@@ -19,8 +19,8 @@
<property name="build.dir" value="build" /> <property name="build.dir" value="build" />
<property name="build.dest" value="${build.dir}/classes" /> <property name="build.dest" value="${build.dir}/classes" />
<property name="build.lib.dest" value="${build.dir}/lib" /> <property name="build.lib.dest" value="${build.dir}/libs" />
<property name="build.src" value="src" /> <property name="build.src" value="src/main/java" />
<property name="packages" value="com.verisignlabs.dnssec.*" /> <property name="packages" value="com.verisignlabs.dnssec.*" />
<property name="doc.dir" value="docs" /> <property name="doc.dir" value="docs" />
@@ -46,7 +46,9 @@
classpathref="project.classpath" classpathref="project.classpath"
deprecation="true" deprecation="true"
includeantruntime="false" includeantruntime="false"
includes="com/verisignlabs/dnssec/" /> includes="com/verisignlabs/dnssec/"
source="1.7"
target="1.7" />
</target> </target>
<target name="sectools-jar" depends="usage,sectools"> <target name="sectools-jar" depends="usage,sectools">

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

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Sat Nov 25 16:14:38 PST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip

164
gradlew vendored Executable file
View File

@@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## 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=""
# 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, switch paths to Windows format before running java
if $cygwin ; 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=$((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
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,90 @@
@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
@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=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@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 init
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 init
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
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
: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 %CMD_LINE_ARGS%
: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/eddsa-0.3.0.jar Normal file

Binary file not shown.

View File

@@ -65,7 +65,7 @@ public abstract class CLBase
/** /**
* The base constructor. This will setup the command line options. * The base constructor. This will setup the command line options.
* *
* @param usage * @param usage
* The command line usage string (e.g., * The command line usage string (e.g.,
* "jdnssec-foo [..options..] zonefile") * "jdnssec-foo [..options..] zonefile")
@@ -106,7 +106,7 @@ public abstract class CLBase
/** /**
* This is an overridable method for subclasses to add their own command * This is an overridable method for subclasses to add their own command
* line options. * line options.
* *
* @param opts * @param opts
* the options object to add (via OptionBuilder, typically) new * the options object to add (via OptionBuilder, typically) new
* options to. * options to.
@@ -121,7 +121,7 @@ public abstract class CLBase
* Subclasses generally override processOptions() rather than this method. * Subclasses generally override processOptions() rather than this method.
* This method create the parsing objects and processes the standard * This method create the parsing objects and processes the standard
* options. * options.
* *
* @param args * @param args
* The command line arguments. * The command line arguments.
* @throws ParseException * @throws ParseException
@@ -188,7 +188,7 @@ public abstract class CLBase
/** /**
* Process additional tool-specific options. Subclasses generally override * Process additional tool-specific options. Subclasses generally override
* this. * this.
* *
* @param cli * @param cli
* The {@link CommandLine} object containing the parsed command * The {@link CommandLine} object containing the parsed command
* line state. * line state.
@@ -247,9 +247,22 @@ public abstract class CLBase
} }
} }
public static long parseLong(String s, long def)
{
try
{
long v = Long.parseLong(s);
return v;
}
catch (NumberFormatException e)
{
return def;
}
}
/** /**
* Calculate a date/time from a command line time/offset duration string. * Calculate a date/time from a command line time/offset duration string.
* *
* @param start * @param start
* the start time to calculate offsets from. * the start time to calculate offsets from.
* @param duration * @param duration
@@ -272,6 +285,11 @@ public abstract class CLBase
long offset = (long) parseInt(duration.substring(1), 0) * 1000; long offset = (long) parseInt(duration.substring(1), 0) * 1000;
return new Date(start.getTime() + offset); return new Date(start.getTime() + offset);
} }
if (duration.length() <= 10)
{
long epoch = parseLong(duration, 0) * 1000;
return new Date(epoch);
}
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyyMMddHHmmss"); SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyyMMddHHmmss");
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT")); dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT"));
@@ -320,6 +338,7 @@ public abstract class CLBase
catch (Exception e) catch (Exception e)
{ {
e.printStackTrace(); e.printStackTrace();
System.exit(1);
} }
} }
} }

View File

@@ -42,7 +42,7 @@ import com.verisignlabs.dnssec.security.*;
* RRset. Note that it will sign any RRset with any private key without * RRset. Note that it will sign any RRset with any private key without
* consideration of whether or not the RRset *should* be signed in the context * consideration of whether or not the RRset *should* be signed in the context
* of a zone. * of a zone.
* *
* @author David Blacka * @author David Blacka
*/ */
public class SignRRset extends CLBase public class SignRRset extends CLBase
@@ -61,6 +61,7 @@ public class SignRRset extends CLBase
public String inputfile = null; public String inputfile = null;
public String outputfile = null; public String outputfile = null;
public boolean verifySigs = false; public boolean verifySigs = false;
public boolean verboseSigning = false;
public CLIState() public CLIState()
{ {
@@ -74,6 +75,7 @@ public class SignRRset extends CLBase
{ {
// boolean options // boolean options
opts.addOption("a", "verify", false, "verify generated signatures>"); opts.addOption("a", "verify", false, "verify generated signatures>");
opts.addOption("V", "verbose-signing", false, "Display verbose signing activity.");
OptionBuilder.hasArg(); OptionBuilder.hasArg();
OptionBuilder.withArgName("dir"); OptionBuilder.withArgName("dir");
@@ -104,6 +106,7 @@ public class SignRRset extends CLBase
String optstr = null; String optstr = null;
if (cli.hasOption('a')) verifySigs = true; if (cli.hasOption('a')) verifySigs = true;
if (cli.hasOption('V')) verboseSigning = true;
if ((optstr = cli.getOptionValue('D')) != null) if ((optstr = cli.getOptionValue('D')) != null)
{ {
@@ -155,7 +158,7 @@ public class SignRRset extends CLBase
/** /**
* Verify the generated signatures. * Verify the generated signatures.
* *
* @param zonename * @param zonename
* the origin name of the zone. * the origin name of the zone.
* @param records * @param records
@@ -198,7 +201,7 @@ 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 keys * a string array containing the base names or paths of the keys
* to be loaded. * to be loaded.
@@ -310,7 +313,7 @@ public class SignRRset extends CLBase
state.outputfile = state.inputfile + ".signed"; state.outputfile = state.inputfile + ".signed";
} }
JCEDnsSecSigner signer = new JCEDnsSecSigner(); JCEDnsSecSigner signer = new JCEDnsSecSigner(state.verboseSigning);
List<RRSIGRecord> sigs = signer.signRRset(rrset, keypairs, state.start, state.expire); List<RRSIGRecord> sigs = signer.signRRset(rrset, keypairs, state.start, state.expire);
for (RRSIGRecord s : sigs) for (RRSIGRecord s : sigs)
@@ -355,7 +358,7 @@ public class SignRRset extends CLBase
{ {
SignRRset tool = new SignRRset(); SignRRset tool = new SignRRset();
tool.state = new CLIState(); tool.state = new CLIState();
tool.run(tool.state, args); tool.run(tool.state, args);
} }
} }

View File

@@ -147,13 +147,13 @@ public class VerifyZone extends CLBase
if (errors > 0) if (errors > 0)
{ {
System.out.println("zone did not verify."); System.out.println("zone did not verify.");
System.exit(1);
} }
else else
{ {
System.out.println("zone verified."); System.out.println("zone verified.");
System.exit(0);
} }
System.exit(0);
} }
public static void main(String[] args) public static void main(String[] args)

View File

@@ -1,11 +1,11 @@
/* /*
* $Id$ * $Id$
* *
* Copyright (c) 2006 VeriSign. All rights reserved. * Copyright (c) 2006 VeriSign. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in * this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of * binary form must reproduce the above copyright notice, this list of
@@ -13,7 +13,7 @@
* materials provided with the distribution. 3. The name of the author may not * materials provided with the distribution. 3. The name of the author may not
* be used to endorse or promote products derived from this software without * be used to endorse or promote products derived from this software without
* specific prior written permission. * specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
@@ -24,7 +24,7 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
*/ */
package com.verisignlabs.dnssec.security; package com.verisignlabs.dnssec.security;
@@ -39,15 +39,20 @@ import java.util.logging.Logger;
import org.xbill.DNS.DNSSEC; import org.xbill.DNS.DNSSEC;
// 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.*;
/** /**
* 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.
* *
* Besides centralizing the logic surrounding matching a DNSKEY algorithm * Besides centralizing the logic surrounding matching a DNSKEY algorithm
* identifier with various crypto implementations, it also handles algorithm * identifier with various crypto implementations, it also handles algorithm
* aliasing -- that is, defining a new algorithm identifier to be equivalent to * aliasing -- that is, defining a new algorithm identifier to be equivalent to
* an existing identifier. * an existing identifier.
* *
* @author David Blacka (orig) * @author David Blacka (orig)
* @author $Author: davidb $ (latest) * @author $Author: davidb $ (latest)
* @version $Revision: 2098 $ * @version $Revision: 2098 $
@@ -64,6 +69,7 @@ public class DnsKeyAlgorithm
public static final int DSA = 3; public static final int DSA = 3;
public static final int ECC_GOST = 4; public static final int ECC_GOST = 4;
public static final int ECDSA = 5; public static final int ECDSA = 5;
public static final int EDDSA = 6;
private static class AlgEntry private static class AlgEntry
{ {
@@ -90,6 +96,17 @@ public class DnsKeyAlgorithm
} }
} }
private static class EdAlgEntry extends AlgEntry
{
public EdDSAParameterSpec ed_spec;
public EdAlgEntry(int algorithm, String sigName, int baseType, EdDSAParameterSpec spec)
{
super(algorithm, sigName, baseType);
this.ed_spec = spec;
}
}
/** /**
* This is a mapping of algorithm identifier to Entry. The Entry contains the * This is a mapping of algorithm identifier to Entry. The Entry contains the
* data needed to map the algorithm to the various crypto implementations. * data needed to map the algorithm to the various crypto implementations.
@@ -113,6 +130,8 @@ public class DnsKeyAlgorithm
private KeyPairGenerator mECGOSTKeyGenerator; private KeyPairGenerator mECGOSTKeyGenerator;
/** This is a cached key pair generator for ECDSA_P256 keys. */ /** This is a cached key pair generator for ECDSA_P256 keys. */
private KeyPairGenerator mECKeyGenerator; private KeyPairGenerator mECKeyGenerator;
/** This is a cached key pair generator for EdDSA keys. */
private KeyPairGenerator mEdKeyGenerator;
private Logger log = Logger.getLogger(this.getClass().toString()); private Logger log = Logger.getLogger(this.getClass().toString());
@@ -132,6 +151,17 @@ public class DnsKeyAlgorithm
} }
catch (ReflectiveOperationException e) { } catch (ReflectiveOperationException e) { }
// Attempt to add the EdDSA-Java provider.
try
{
Class<?> eddsa_provider_class = Class.forName("net.i2p.crypto.eddsa.EdDSASecurityProvider");
Provider eddsa_provider = (Provider) eddsa_provider_class.newInstance();
Security.addProvider(eddsa_provider);
}
catch (ReflectiveOperationException e) {
log.warning("Unable to load EdDSA provider");
}
initialize(); initialize();
} }
@@ -170,7 +200,7 @@ public class DnsKeyAlgorithm
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. // 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", ECC_GOST, null);
@@ -184,6 +214,13 @@ public class DnsKeyAlgorithm
addAlgorithm(DNSSEC.Algorithm.ECDSAP384SHA384, "SHA384withECDSA", ECDSA, "secp384r1"); addAlgorithm(DNSSEC.Algorithm.ECDSAP384SHA384, "SHA384withECDSA", ECDSA, "secp384r1");
addMnemonic("ECDSAP384SHA384", DNSSEC.Algorithm.ECDSAP384SHA384); addMnemonic("ECDSAP384SHA384", DNSSEC.Algorithm.ECDSAP384SHA384);
addMnemonic("ECDSA-P384", DNSSEC.Algorithm.ECDSAP384SHA384); addMnemonic("ECDSA-P384", DNSSEC.Algorithm.ECDSAP384SHA384);
// EdDSA is not supported by either the Java 1.8 Sun crypto
// provider or bouncycastle. It is added by the Ed25519-Java
// library. We don't have a corresponding constant in
// org.xbill.DNS.DNSSEC yet, though.
addAlgorithm(15, "NONEwithEdDSA", EDDSA, "Ed25519");
addMnemonic("ED25519", 15);
} }
private void addAlgorithm(int algorithm, String sigName, int baseType) private void addAlgorithm(int algorithm, String sigName, int baseType)
@@ -193,19 +230,43 @@ public class DnsKeyAlgorithm
private void addAlgorithm(int algorithm, String sigName, int baseType, String curveName) private void addAlgorithm(int algorithm, String sigName, int baseType, String curveName)
{ {
ECParameterSpec ec_spec = ECSpecFromAlgorithm(algorithm); if (baseType == ECDSA)
if (ec_spec == null) ec_spec = ECSpecFromName(curveName); {
if (ec_spec == null) return; ECParameterSpec ec_spec = ECSpecFromAlgorithm(algorithm);
// Check to see if we can get a Signature object for this algorithm. if (ec_spec == null) ec_spec = ECSpecFromName(curveName);
try { if (ec_spec == null) return;
Signature.getInstance(sigName);
} catch (NoSuchAlgorithmException e) { // Check to see if we can get a Signature object for this algorithm.
// If not, do not add the algorithm. try {
return; Signature.getInstance(sigName);
} catch (NoSuchAlgorithmException e) {
// for now, let's find out
log.severe("could not get signature for " + sigName + ": " + e.getMessage());
// If not, do not add the algorithm.
return;
}
ECAlgEntry entry = new ECAlgEntry(algorithm, sigName, baseType, ec_spec);
mAlgorithmMap.put(algorithm, entry);
}
else if (baseType == EDDSA)
{
EdDSAParameterSpec ed_spec = EdDSASpecFromName(curveName);
if (ed_spec == null) return;
// Check to see if we can get a Signature object for this algorithm.
try {
Signature.getInstance(sigName);
} catch (NoSuchAlgorithmException e) {
// for now, let's find out
log.severe("could not get signature for " + sigName + ": " + e.getMessage());
// If not, do not add the algorithm.
return;
}
EdAlgEntry entry = new EdAlgEntry(algorithm, sigName, baseType, ed_spec);
mAlgorithmMap.put(algorithm, entry);
} }
ECAlgEntry entry = new ECAlgEntry(algorithm, sigName, baseType, ec_spec);
mAlgorithmMap.put(algorithm, entry);
} }
private void addMnemonic(String m, int alg) private void addMnemonic(String m, int alg)
@@ -230,7 +291,7 @@ public class DnsKeyAlgorithm
if (!mAlgorithmMap.containsKey(original_algorithm)) if (!mAlgorithmMap.containsKey(original_algorithm))
{ {
log.warning("Unable to alias algorith " + alias log.warning("Unable to alias algorithm " + alias
+ " to unknown algorithm identifier " + original_algorithm); + " to unknown algorithm identifier " + original_algorithm);
return; return;
} }
@@ -273,7 +334,7 @@ public class DnsKeyAlgorithm
} }
} }
// Fetch the curve parameters from a named curve. // Fetch the curve parameters from a named ECDSA curve.
private ECParameterSpec ECSpecFromName(String stdName) private ECParameterSpec ECSpecFromName(String stdName)
{ {
try try
@@ -292,6 +353,24 @@ public class DnsKeyAlgorithm
return null; return null;
} }
// Fetch the curve parameters from a named EdDSA curve.
private EdDSAParameterSpec EdDSASpecFromName(String stdName)
{
try
{
EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(stdName);
if (spec != null) return spec;
throw new InvalidParameterSpecException("Edwards Curve " + stdName + " not found.");
}
// catch (NoSuchAlgorithmException e) {
// log.info("Edwards Curve not supported by any crypto provider: " + e.getMessage());
// }
catch (InvalidParameterSpecException e) {
log.info("Edwards Curve " + stdName + " not supported");
}
return null;
}
public String[] supportedAlgMnemonics() public String[] supportedAlgMnemonics()
{ {
Set<Integer> keyset = mAlgorithmMap.keySet(); Set<Integer> keyset = mAlgorithmMap.keySet();
@@ -306,6 +385,7 @@ public class DnsKeyAlgorithm
return result; return result;
} }
/** /**
* Return a Signature object for the specified DNSSEC algorithm. * Return a Signature object for the specified DNSSEC algorithm.
* @param algorithm The DNSSEC algorithm (by number). * @param algorithm The DNSSEC algorithm (by number).
@@ -350,10 +430,28 @@ public class DnsKeyAlgorithm
return ec_entry.ec_spec; return ec_entry.ec_spec;
} }
/** Given one of the EdDSA algorithms (Ed25519, Ed448) return the
* elliptic curve parameters.
*
* @param algorithm
* The DNSSEC algorithm number.
* @return The stored EdDSAParameterSpec for that algorithm, or
* null if not a recognized/supported EdDSA algorithm.
*/
public EdDSAParameterSpec getEdwardsCurveParams(int algorithm)
{
AlgEntry entry = getEntry(algorithm);
if (entry == null) return null;
if (!(entry instanceof EdAlgEntry)) return null;
EdAlgEntry ed_entry = (EdAlgEntry) entry;
return ed_entry.ed_spec;
}
/** /**
* 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
@@ -368,7 +466,7 @@ public class DnsKeyAlgorithm
/** /**
* Test if a given algorithm is supported. * Test if a given algorithm is supported.
* *
* @param algorithm The DNSSEC algorithm number. * @param algorithm The DNSSEC algorithm number.
* @return true if the algorithm is a recognized and supported algorithm or alias. * @return true if the algorithm is a recognized and supported algorithm or alias.
*/ */
@@ -381,7 +479,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
@@ -396,7 +494,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
@@ -507,8 +605,29 @@ public class DnsKeyAlgorithm
pair = mECKeyGenerator.generateKeyPair(); pair = mECKeyGenerator.generateKeyPair();
break; break;
} }
default: case EDDSA:
throw new NoSuchAlgorithmException("Alg " + algorithm); {
if (mEdKeyGenerator == null)
{
mEdKeyGenerator = KeyPairGenerator.getInstance("EdDSA");
}
EdDSAParameterSpec ed_spec = getEdwardsCurveParams(algorithm);
try
{
mEdKeyGenerator.initialize(ed_spec, new SecureRandom());
}
catch (InvalidAlgorithmParameterException e)
{
// Fold the InvalidAlgorithmParameterException into our existing
// thrown exception. Ugly, but requires less code change.
throw new NoSuchAlgorithmException("invalid key parameter spec");
}
pair = mEdKeyGenerator.generateKeyPair();
break;
}
default:
throw new NoSuchAlgorithmException("Alg " + algorithm);
} }
return pair; return pair;

View File

@@ -36,6 +36,11 @@ import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.DHPrivateKeySpec; import javax.crypto.spec.DHPrivateKeySpec;
// For now, just import the native EdDSA classes
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.spec.*;
import org.xbill.DNS.DNSKEYRecord; import org.xbill.DNS.DNSKEYRecord;
import org.xbill.DNS.DNSSEC; import org.xbill.DNS.DNSSEC;
import org.xbill.DNS.DNSSEC.DNSSECException; import org.xbill.DNS.DNSSEC.DNSSECException;
@@ -45,7 +50,7 @@ import org.xbill.DNS.utils.base64;
/** /**
* 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.
* *
* @author David Blacka (original) * @author David Blacka (original)
* @author $Author$ (latest) * @author $Author$ (latest)
* @version $Revision$ * @version $Revision$
@@ -56,16 +61,17 @@ public class DnsKeyConverter
private KeyFactory mDSAKeyFactory; private KeyFactory mDSAKeyFactory;
private KeyFactory mDHKeyFactory; private KeyFactory mDHKeyFactory;
private KeyFactory mECKeyFactory; private KeyFactory mECKeyFactory;
private KeyFactory mEdKeyFactory;
private DnsKeyAlgorithm mAlgorithms; private DnsKeyAlgorithm mAlgorithms;
public DnsKeyConverter() public DnsKeyConverter()
{ {
mAlgorithms = DnsKeyAlgorithm.getInstance(); mAlgorithms = DnsKeyAlgorithm.getInstance();
} }
/** /**
* Given a DNS KEY record, return the JCA public key * Given a DNS KEY record, return the JCA public key
* *
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
*/ */
public PublicKey parseDNSKEYRecord(DNSKEYRecord pKeyRecord) public PublicKey parseDNSKEYRecord(DNSKEYRecord pKeyRecord)
@@ -89,8 +95,20 @@ 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.
return pKeyRecord.getPublicKey(); return pKeyRecord.getPublicKey();
} }
catch (DNSSECException e) catch (DNSSECException e)
@@ -99,6 +117,20 @@ 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.
*/ */
@@ -107,6 +139,9 @@ public class DnsKeyConverter
{ {
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);
} }
@@ -117,6 +152,15 @@ 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
/** /**
@@ -204,6 +248,8 @@ public class DnsKeyConverter
return parsePrivateECDSA(lines, alg); return parsePrivateECDSA(lines, alg);
case DnsKeyAlgorithm.ECDSA: case DnsKeyAlgorithm.ECDSA:
return parsePrivateECDSA(lines, alg); return parsePrivateECDSA(lines, alg);
case DnsKeyAlgorithm.EDDSA:
return parsePrivateEdDSA(lines, alg);
default: default:
throw new IOException("unsupported private key algorithm: " + val); throw new IOException("unsupported private key algorithm: " + val);
} }
@@ -230,7 +276,7 @@ public class DnsKeyConverter
/** /**
* Given the rest of the RSA BIND9 string format private key, parse and * Given the rest of the RSA BIND9 string format private key, parse and
* translate into a JCA private key * translate into a JCA private key
* *
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
* if the RSA algorithm is not available. * if the RSA algorithm is not available.
*/ */
@@ -319,7 +365,7 @@ public class DnsKeyConverter
/** /**
* Given the remaining lines in a BIND9 style DH private key, parse the key * Given the remaining lines in a BIND9 style DH private key, parse the key
* info and translate it into a JCA private key. * info and translate it into a JCA private key.
* *
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
* if the DH algorithm is not available. * if the DH algorithm is not available.
*/ */
@@ -375,7 +421,7 @@ public class DnsKeyConverter
/** /**
* Given the remaining lines in a BIND9 style DSA private key, parse the key * Given the remaining lines in a BIND9 style DSA private key, parse the key
* info and translate it into a JCA private key. * info and translate it into a JCA private key.
* *
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
* if the DSA algorithm is not available. * if the DSA algorithm is not available.
*/ */
@@ -487,6 +533,60 @@ public class DnsKeyConverter
} }
} }
/**
* Given the remaining lines in a BIND9-style ECDSA private key, parse the key
* info and translate it into a JCA private key object.
* @param lines The remaining lines in a private key file (after
* @throws NoSuchAlgorithmException
* If elliptic curve is not available.
*/
private PrivateKey parsePrivateEdDSA(StringTokenizer lines, int algorithm)
throws NoSuchAlgorithmException
{
byte[] seed = null;
while (lines.hasMoreTokens())
{
String line = lines.nextToken();
if (line == null) continue;
if (line.startsWith("#")) continue;
String val = value(line);
if (val == null) continue;
byte[] data = base64.fromString(val);
if (line.startsWith("PrivateKey: "))
{
seed = data;
}
}
if (mEdKeyFactory == null)
{
mEdKeyFactory = KeyFactory.getInstance("EdDSA");
}
EdDSAParameterSpec ed_spec = mAlgorithms.getEdwardsCurveParams(algorithm);
if (ed_spec == null)
{
throw new NoSuchAlgorithmException("DNSSEC algorithm " + algorithm +
" is not a recognized Edwards Curve algorithm");
}
KeySpec spec = new EdDSAPrivateKeySpec(seed, ed_spec);
try
{
return mEdKeyFactory.generatePrivate(spec);
}
catch (InvalidKeySpecException e)
{
e.printStackTrace();
return null;
}
}
/** /**
* Given a private key and public key, generate the BIND9 style private key * Given a private key and public key, generate the BIND9 style private key
* format. * format.
@@ -509,6 +609,11 @@ public class DnsKeyConverter
{ {
return generatePrivateEC((ECPrivateKey) priv, (ECPublicKey) pub, alg); return generatePrivateEC((ECPrivateKey) priv, (ECPublicKey) pub, alg);
} }
else if (priv instanceof EdDSAPrivateKey && pub instanceof EdDSAPublicKey)
{
return generatePrivateED((EdDSAPrivateKey) priv, (EdDSAPublicKey) pub, alg);
}
return null; return null;
} }
@@ -630,4 +735,22 @@ public class DnsKeyConverter
return sw.toString(); return sw.toString();
} }
/**
* Given an edwards curve key pair, and the actual algorithm (which will
* describe the curve used), return the BIND9-style text encoding.
*/
private String generatePrivateED(EdDSAPrivateKey priv, EdDSAPublicKey pub, int alg)
{
StringWriter sw = new StringWriter();
PrintWriter out = new PrintWriter(sw);
out.println("Private-key-format: v1.2");
out.println("Algorithm: " + alg + " (" + mAlgorithms.algToString(alg)
+ ")");
out.print("PrivateKey: ");
out.println(base64.toString(priv.getSeed()));
return sw.toString();
}
} }

View File

@@ -38,11 +38,11 @@ import org.xbill.DNS.utils.hexdump;
/** /**
* This class contains routines for signing DNS zones. * This class contains routines for signing DNS zones.
* *
* In particular, it contains both an ability to sign an individual RRset and * In particular, it contains both an ability to sign an individual RRset and
* the ability to sign an entire zone. It primarily glues together the more * the ability to sign an entire zone. It primarily glues together the more
* basic primitives found in {@link SignUtils}. * basic primitives found in {@link SignUtils}.
* *
* @author David Blacka (original) * @author David Blacka (original)
* @author $Author$ * @author $Author$
* @version $Revision$ * @version $Revision$
@@ -69,7 +69,7 @@ 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 * @param ttl
@@ -114,7 +114,7 @@ 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 * @param keypars
@@ -211,7 +211,7 @@ 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 * @param start
@@ -244,7 +244,7 @@ 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 * @param zonename
@@ -263,7 +263,7 @@ public class JCEDnsSecSigner
* if true, sign the zone apex keyset with both KSKs and ZSKs. * if true, sign the zone apex keyset with both KSKs and ZSKs.
* @param last_cut * @param last_cut
* the name of the last delegation point encountered. * the name of the last delegation point encountered.
* *
* @return the name of the new last_cut. * @return the name of the new last_cut.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -324,7 +324,7 @@ public class JCEDnsSecSigner
* signing variants (NSEC with or without Opt-In, NSEC3 with or without * signing variants (NSEC with or without Opt-In, NSEC3 with or without
* 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 * @param records
@@ -363,7 +363,7 @@ public class JCEDnsSecSigner
* values will use the SOA TTL. * 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.
* *
* @throws IOException * @throws IOException
* @throws GeneralSecurityException * @throws GeneralSecurityException
*/ */
@@ -459,7 +459,7 @@ public class JCEDnsSecSigner
/** /**
* 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 * @param records
@@ -478,7 +478,7 @@ public class JCEDnsSecSigner
* the key signing keys). * the key signing keys).
* @param ds_digest_alg * @param ds_digest_alg
* The digest algorithm to use when generating DS records. * The digest algorithm to use when generating DS records.
* *
* @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.
*/ */
@@ -494,7 +494,7 @@ public class JCEDnsSecSigner
/** /**
* 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 stuff. * A signer (utility) object used to actually sign stuff.
* @param zonename * @param zonename
@@ -529,7 +529,7 @@ public class JCEDnsSecSigner
* values will use the SOA TTL. * 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.
* *
* @throws IOException * @throws IOException
* @throws GeneralSecurityException * @throws GeneralSecurityException
*/ */
@@ -558,7 +558,7 @@ 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 * @param records

View File

@@ -526,10 +526,19 @@ public class SignUtils
s_src_pos = (byte) (r_src_pos + r_src_len); s_pad = 0; s_src_pos = (byte) (r_src_pos + r_src_len); s_pad = 0;
len = (byte) (6 + r_src_len + s_src_len); len = (byte) (6 + r_src_len + s_src_len);
if (signature[r_src_pos] < 0) { // leading zeroes are forbidden
r_pad = 1; len++; while (signature[r_src_pos] == 0 && r_src_len > 0) {
r_src_pos++; r_src_len--; len--;
} }
if (signature[s_src_pos] < 0) { while (signature[s_src_pos] == 0 && s_src_len > 0) {
s_src_pos++; s_src_len--; len--;
}
// except when they are mandatory
if (r_src_len > 0 && signature[r_src_pos] < 0) {
r_pad = 1; len++;
}
if (s_src_len > 0 && signature[s_src_pos] < 0) {
s_pad = 1; len++; s_pad = 1; len++;
} }
byte[] sig = new byte[len]; byte[] sig = new byte[len];