diff --git a/.gitignore b/.gitignore
index 63910de..b926917 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
.DS_Store
-coniks_common/src/org/coniks/coniks_common/*.class
-coniks_common/src/com/google/protobuf/*.java
-coniks_server/src/org/coniks/coniks_server/*.class
-coniks_test_client/src/org/coniks/coniks_test_client/*.class
+target
+bin
+logs
diff --git a/.travis.yml b/.travis.yml
index f6f589d..53ca23e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,12 @@ env:
global:
secure: B5ZEHKFRa11V7e9JZwr4vGFSdo1lvnbxijd00mm41qbvwT5YFSMZhEQLRVlDmxhsqcc6guC84Q49LsY3/4rlzspHe8fkByY2sQUM3aXuK13/lJJT8CeDXxYAicWMPBLvybpt3ML1wXcbskQzv5C7oNLgkeMwvpd2zw5pYMV2dHwRhRkfsYgH7hzlVgCOMnPLHfPiDgjuQK6KJUr1qlO4Y9vmFsCiCi94fLHIxu+MsvFy3XRnnlTERTGQCeBD2GGHTH5wjiwTL0GHdKX/ntpODyWZAnbYs8OYsLuCq7QQHJDk4uBVCnMIj1zt6lwxa0iiz+uuvxnL6msSeF/BkIWG/yxRkBjdVtdJL0WBEIDmfzeEugdNFke1I2dsH68Fe+R2syUwIjJ654HSoLZ/xL9Dbnxo8wmix2cO46ictXN3WVNrWwB4KUV5N+aGW/hB0KRqSsO2iUmXqweifJz7qfWm20Y//pgtMtVTnZVTneiSCPucY1QWQmiOgC0jcseV+oIbpFjbYArxGhhPhqJqAWYhJeR/7uX872zMwPqpyHRF3y1XQ+C2xI9IWC2SqjinCsgUnZei1pu7A4Qd34Isd8uCICrLMu8JPe98+Dc+jksGrH/SgOcDI/pffnD2rk/ablNU7JY8yE2t5me9B6SAxOEOyle60i5WiRHcM+pZukBwvwU=
-script: mvn test
+script:
+ # TODO check style
+ - mvn test
notifications:
+ # Email notifications are disabled to not annoy anybody.
+ # See http://about.travis-ci.org/docs/user/build-configuration/ to learn more
+ # about configuring notification recipients and more.
email: false
diff --git a/README.md b/README.md
index e0a0933..7031ef1 100644
--- a/README.md
+++ b/README.md
@@ -9,10 +9,10 @@ http://coniks.org
CONIKS is a key management system that provides transparency and privacy for end-user public keys. CONIKS protects end-to-end encrypted communications against malicious or compromised communication providers and surveillance by storing users' encryption keys in tamper-evident and publicly auditable key directories on the server side. This allows messaging clients to verify the identity of users automatically, and prevents malicious/compromised servers from hijacking secure communications without getting caught.
##Java Library
-This software package serves as a Java library for the CONIKS system and includes reference implementations for the CONIKS server and client. The basic [CONIKS server](https://github.com/coniks-sys/coniks-java/tree/master/coniks_server) and simple [CONIKS test client](https://github.com/coniks-sys/coniks-java/tree/master/coniks_test_client) demonstrate the functionality of the system and the CONIKS protocols, so anyone interested in deploying CONIKS in their secure messaging system can then use this software package as a reference when implementing the service. This package also contains the [common message format definitions](https://github.com/coniks-sys/coniks-java/tree/master/coniks_common) that CONIKS servers and clients use to communicate.
+This software package serves as a Java library for the CONIKS system and includes reference implementations for the CONIKS server and client. The basic [CONIKS server](https://github.com/coniks-sys/coniks-java/tree/master/coniks_server) and simple [CONIKS test client](https://github.com/coniks-sys/coniks-java/tree/master/coniks_test_client) demonstrate the functionality of the system and the CONIKS protocols, so anyone interested in deploying CONIKS in their secure messaging system can then use this software package as a reference when implementing the service. This package also contains the [common message format definitions](https://github.com/coniks-sys/coniks-java/tree/master/coniks_common) that CONIKS servers and clients use to communicate.
## Disclaimer
-Please keep in mind that this CONIKS reference implementation is under active development. The repository may contain experimental features that aren't fully tested. We recommend using a [tagged release](https://github.com/coniks-sys/coniks-java/releases).
+Please keep in mind that this CONIKS Java implementation is under active development. The repository may contain experimental features that aren't fully tested. We recommend using a [tagged release](https://github.com/coniks-sys/coniks-java/releases).
##Documentation
[Read the package's Java API (javadoc)](https://coniks-sys.github.io/coniks-java/)
diff --git a/coniks_common/README.md b/coniks_common/README.md
index b6aa7e5..eaa616c 100644
--- a/coniks_common/README.md
+++ b/coniks_common/README.md
@@ -23,7 +23,7 @@ The coniks_common build is managed using Maven. (Instructions for building witho
These instructions will install the ``coniks_common`` Maven artifact.
## Disclaimer
-Please keep in mind that this CONIKS reference implementation is under active development. The repository may contain experimental features that aren't fully tested. We recommend using a [tagged release](https://github.com/coniks-sys/coniks-java/releases).
+Please keep in mind that this CONIKS Java implementation is under active development. The repository may contain experimental features that aren't fully tested. We recommend using a [tagged release](https://github.com/coniks-sys/coniks-java/releases).
##Documentation
[Read the common files' Java API (javadoc)](https://coniks-sys.github.io/coniks-java/org/coniks/coniks_common/package-summary.html)
diff --git a/coniks_common/pom.xml b/coniks_common/pom.xml
index 401a9b8..9838439 100644
--- a/coniks_common/pom.xml
+++ b/coniks_common/pom.xml
@@ -5,24 +5,19 @@
org.coniksconiks-java
- 1.2-SNAPSHOT
+ 1.3-SNAPSHOTorg.coniks.coniks_commonconiks_common
+ 1.3-SNAPSHOTjar
- 1.2-SNAPSHOT
- coniks_common
+
+ CONIKS [Common]http://coniks.org
+ Common message spec and encoding library for CONIKS.
-
- junit
- junit
- 3.8.1
- test
-
-
com.google.protobufprotobuf-java
diff --git a/coniks_server/README.md b/coniks_server/README.md
index 1b3db1f..909f35a 100644
--- a/coniks_server/README.md
+++ b/coniks_server/README.md
@@ -11,18 +11,24 @@ The coniks_server build is managed using Maven. (Instructions for building witho
1) Install Apache Maven, if you don't have it. Visit the [Maven downloads page](https://maven.apache.org/download.cgi) for details.
2) Install the library into your Maven repository:
+
```$ mvn install```
3) If you don't use Maven to manage your own build, you can build a .jar file to use:
+
```$ mvn package```
These instructions will install the ``coniks_server`` Maven artifact.
+The build configuration for coniks_server assembles all dependencies,
+and includes them in the generated .jar file, so you can run the server
+only using the coniks_server .jar file.
##Using the Server
-The CONIKS server has two operating modes: Test Mode and Full Operation.
-Running the server in test mode allows you to still test all CONIKS protocols and operations,
-but requires less setup as you can simply use the default configuration in the included *config* file.
+The CONIKS server has two operating modes: Test Mode and Full Operation.
+Running the server in test mode allows you to still test all CONIKS
+protocols and operations, but requires less setup as you can simply use
+the default configuration in the included *config* file.
**Note:** You must be running the test client in the same operating mode.
### Setup
@@ -32,21 +38,20 @@ Run the following command, using the default settings if setting up test mode:
```
keytool -genkeypair -alias -keyalg RSA -validity 365 -keystore
```
-Follow the prompts and enter suitable information. Make sure to enter legitimate information if running
-in full operation mode. Notice that the key pair is set to expire within 365 days here, but you may
-change this setting when running this command.
-- Full operation mode only: Generate self-signed certificates for SSL/TLS communication,
-if you don't already have certs for your server:
-Make sure the alias and the keystore used in this step match the values used when generating the
-signing key pair in the previous step.
+Follow the prompts and enter suitable information. Make sure to enter
+legitimate information if running
+in full operation mode. Notice that the key pair is set to expire within 365 days here, but you may change this setting when running this command.
+- Full operation mode only: Generate self-signed certificates for SSL/TLS
+communication, if you don't already have certs for your server:
+Make sure the alias and the keystore used in this step match the values used when generating the signing key pair in the previous step.
```
keytool -export -alias -keystore -rfc -file .cer
keytool -import -alias -file .cer -keystore
```
- Set all of the configurations in the config file:
-Defaults are already set, except for the absolute path to the keystore generated in the
-previous step along with its password. You'll have to set these using the format
-described below.
+Defaults are already set, except for the absolute path to the
+keystore generated in the previous step along with its password.
+You'll have to set these using the format described below.
You may write your own config file, but it must follow the following format:
```
(must be the same in the CONIKS client config)
@@ -58,19 +63,20 @@ You may write your own config file, but it must follow the following format:
/ (not used in test mode)
(not used for test mode)
```
-Especially if you're running in full operating mode, make sure the config file is only readable
-by the users allowed to run the CONIKS server to protect your keystore password.
+Especially if you're running in full operating mode, make sure the
+config file is only readable by the users allowed to run the CONIKS
+server to protect your keystore password.
- Set all of the configs in the run script *coniks_server.sh*:
Defaults are already set, but you may change the following variables:
-```CLASS_DEST``` if you used a different classpath when building the server.
+```CLASS_DEST``` if you've changed configurations such as the artifactID or version in the server's pom.xml file before building.
```CONIKS_SERVERCONFIG``` if you're using a different config file
```CONIKS_SERVERLOGS``` to store the server logs somewhere other than a *logs* directory
###Running
-We provide a run script for the CONIKS server *coniks_server.sh*, which allows you to run the server in
-full operation mode and test mode.
+We provide a run script for the CONIKS server *coniks_server.sh*,
+which allows you to run the server in full operation mode and test mode.
-The run script supports four commands:
+The run script supports four commands:
- ```start```: start the server in full operation mode (runs in background).
- ```test```: start the server in test mode (runs in foreground).
- ```stop```: stop the server.
@@ -80,7 +86,7 @@ For example, to start the server in full operation mode, use
Analogously to test and stop the server, and remove the logs.
## Disclaimer
-Please keep in mind that this CONIKS reference implementation is under active development. The repository may contain experimental features that aren't fully tested. We recommend using a [tagged release](https://github.com/coniks-sys/coniks-java/releases).
+Please keep in mind that this CONIKS Java implementation is under active development. The repository may contain experimental features that aren't fully tested. We recommend using a [tagged release](https://github.com/coniks-sys/coniks-java/releases).
##Documentation
[Read the server's Java API (javadoc)](https://coniks-sys.github.io/coniks-java/org/coniks/coniks_server/package-summary.html)
diff --git a/coniks_server/coniks_server.sh b/coniks_server/coniks_server.sh
index 38a4dd7..2ed1a3f 100755
--- a/coniks_server/coniks_server.sh
+++ b/coniks_server/coniks_server.sh
@@ -4,37 +4,38 @@
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
+# modification, are permitted provided that the following conditions are
# met:
-# * Redistributions of source code must retain the above copyright
+# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Princeton University nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
-# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
## Runs or stops a CONIKS server instance
# Set all the configs here
-CLASS_DEST="bin" #change this if you built the server somewhere else
+# mvn builds our jar with dependencies
+CLASS_DEST="./target/coniks_server-1.3-SNAPSHOT.jar"
CLASSPATH="-cp $CLASS_DEST"
SERVER_BIN="org.coniks.coniks_server.ConiksServer"
CONIKS_SERVERCONFIG="config" #change this if using a different config file
@@ -100,7 +101,7 @@ elif [ "$CMD" = "stop" ]; then
fi
echo "Stopping the CONIKS server."
-
+
kill `cat $CONIKS_SERVERLOGS/pid` >/dev/null
rm -f $CONIKS_SERVERLOGS/pid
@@ -112,7 +113,7 @@ elif [ "$CMD" = "clean" ]; then
# write to one of the logs
if [ `ps ax | grep -c $SERVER_BIN` -gt 1 ]; then
echo "Stopping the CONIKS server."
-
+
kill `cat $CONIKS_SERVERLOGS/pid` >/dev/null
rm -f $CONIKS_SERVERLOGS/pid
fi
diff --git a/coniks_server/pom.xml b/coniks_server/pom.xml
index 0b9bd16..8f4e9d3 100644
--- a/coniks_server/pom.xml
+++ b/coniks_server/pom.xml
@@ -5,28 +5,31 @@
org.coniksconiks-java
- 1.2-SNAPSHOT
+ 1.3-SNAPSHOTorg.coniks.coniks_serverconiks_server
+ 1.3-SNAPSHOTjar
- 1.2-SNAPSHOT
- coniks_server
+
+ CONIKS [Reference Server]http://coniks.org
+ CONIKS server library and reference implementation.
+
- junit
- junit
- 3.8.1
- test
+ org.coniks.coniks_common
+ coniks_common
+ 1.3-SNAPSHOT
+ compile
- org.coniks.coniks_common
- coniks_common
- 1.2-SNAPSHOT
+ org.coniks.crypto
+ coniks-crypto
+ 1.3-SNAPSHOTcompile
@@ -48,4 +51,26 @@
UTF-8
+
+
+
+
+ maven-assembly-plugin
+
+
+ package
+
+ single
+
+
+
+
+
+ jar-with-dependencies
+
+ false
+
+
+
+
diff --git a/coniks_server/src/main/java/org/coniks/coniks_server/ConiksServer.java b/coniks_server/src/main/java/org/coniks/coniks_server/ConiksServer.java
index 969c32f..550ac64 100644
--- a/coniks_server/src/main/java/org/coniks/coniks_server/ConiksServer.java
+++ b/coniks_server/src/main/java/org/coniks/coniks_server/ConiksServer.java
@@ -1,38 +1,40 @@
/*
Copyright (c) 2015-16, Princeton University.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
+ modification, are permitted provided that the following conditions are
met:
- * Redistributions of source code must retain the above copyright
+ * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
distribution.
* Neither the name of Princeton University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
package org.coniks.coniks_server;
+// coniks-java imports
+import org.coniks.crypto.Util;
import org.coniks.coniks_common.MsgType;
import org.coniks.coniks_common.C2SProtos.Registration;
import org.coniks.coniks_common.C2SProtos.CommitmentReq;
@@ -88,27 +90,27 @@ public class ConiksServer{
private static long initEpoch;
- /** Initialize the directory: get the latest root node from the
+ /** Initialize the directory: get the latest root node from the
* database (if using one) and update the directory internally (i.e. build the hash tree)
* Because users are stored in lexicographic order, we can simply load them all at once.
* N.B. Designed for few restarts in mind.
*/
private static RootNode initDirectory(){
- PriorityQueue> initUsers =
- new PriorityQueue>(
- 16384, new ServerUtils.PrefixComparator());
+ PriorityQueue> initUsers =
+ new PriorityQueue>(
+ 16384, new ServerUtils.PrefixComparator());
// At this point, if we're using a DB, we want to check if we already have
// a commitment history stored in the DB
// if so, retrieve the latest commitment and root node stored in the DB
-
+
RootNode initRoot = TreeBuilder.copyExtendTree(null, initUsers);
-
+
initUsers.clear();
return initRoot;
}
-
+
/** Configures the server and begins listening for
* incoming connections from CONIKS clients.
*
@@ -116,7 +118,7 @@ private static RootNode initDirectory(){
* {@code ./coniks_server.sh }
*/
public static void main(String[] args){
-
+
if (args.length != NUM_ARGS) {
System.out.println("Need "+(NUM_ARGS-1)+" arguments: CONIKS_SERVERCONFIG, and CONIKS_SERVERLOGS");
System.out.println("The run script may expect these to be passed as env vars, make sure to export these before running the run script again.");
@@ -134,7 +136,7 @@ public static void main(String[] args){
if (!configFile.exists() || !logDir.isDirectory()) {
throw new FileNotFoundException();
}
-
+
String opMode = args[2];
if (opMode.equalsIgnoreCase("full")) {
isFullOp = true;
@@ -155,12 +157,12 @@ else if (opMode.equalsIgnoreCase("test")) {
System.out.println("The path you entered for CONIKS_SERVERCONFIG or CONIKS_SERVERLOGS doesn't exist.");
System.exit(-1);
}
-
+
// false indicates an error, so exit
if (!ServerConfig.readServerConfig(configFile, isFullOp)) {
System.exit(-1);
}
-
+
// set some more configs
initEpoch = ServerConfig.getStartupTime();
MsgHandlerLogger.setup(logPath+"/msg-handler-%g");
@@ -191,30 +193,30 @@ else if (opMode.equalsIgnoreCase("test")) {
}
// init the history
- if (!ServerHistory.initHistory(initRoot, initEpoch, 0,
- new byte[ServerUtils.HASH_SIZE_BYTES])) {
+ if (!ServerHistory.initHistory(initRoot, initEpoch, 0,
+ new byte[Util.HASH_SIZE_BYTES])) {
ServerUtils.printStatusMsg(true, "Error initializing the history");
System.exit(-1);
}
-
+
EpochTimerTask epochSnapshotTaker = new EpochTimerTask();
-
- ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
- scheduler.scheduleWithFixedDelay(epochSnapshotTaker,
- ServerConfig.getEpochInterval(),
- ServerConfig.getEpochInterval(),
- TimeUnit.MILLISECONDS);
+
+ ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+ scheduler.scheduleWithFixedDelay(epochSnapshotTaker,
+ ServerConfig.getEpochInterval(),
+ ServerConfig.getEpochInterval(),
+ TimeUnit.MILLISECONDS);
ServerMessaging.listenForRequests(isFullOp);
-
+
}
-
+
/** Implements a TimerTask that updates the STR history every epoch.
*/
private static class EpochTimerTask implements Runnable {
public void run() {
- TimerLogger.log("Timer task started.");
+ TimerLogger.log("Timer task started.");
RootNode nextRoot = DirectoryOps.updateDirectory();
// check that we got a good first tree
@@ -253,7 +255,7 @@ public void run() {
ServerUtils.printStatusMsg(false, "Directory update successful. Next epoch: "+nextEpoch);
}
}
-
+
}
-
+
}
diff --git a/coniks_server/src/main/java/org/coniks/coniks_server/KeyChange.java b/coniks_server/src/main/java/org/coniks/coniks_server/KeyChange.java
index 29f0138..7b9941e 100644
--- a/coniks_server/src/main/java/org/coniks/coniks_server/KeyChange.java
+++ b/coniks_server/src/main/java/org/coniks/coniks_server/KeyChange.java
@@ -36,9 +36,13 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
import java.security.interfaces.DSAPublicKey;
import java.util.Arrays;
+// coniks-java imports
+import org.coniks.crypto.*;
+
/** Implements a key change operation.
*
*@author Michael Rochlin
+ *@author Marcela S. Melara (melara@cs.princeton.edu)
*/
public class KeyChange extends Operation {
private String newKeyData;
@@ -97,10 +101,21 @@ public boolean canChangeInfo(UserLeafNode uln) {
ServerLogger.error("Tried to make unsigned KeyChange but wasn't allowed");
return false;
}
- if (!uln.allowsUnsignedKeychange()
- && !SignatureOps.verifySigFromDSA(msg, sig, uln.getChangeKey())) {
- ServerLogger.error("Requires that key changes be signed, but the signature was invalid");
- return false;
+ if (!uln.allowsUnsignedKeychange()) {
+
+ boolean res = false;
+
+ try {
+ res = Signing.dsaVerify(uln.getChangeKey(), msg, sig);
+ }
+ catch (Exception e) {
+ ServerLogger.error("[KeyChange] "+e.getMessage());
+ }
+
+ if(!res) {
+ ServerLogger.error("Requires that key changes be signed, but the signature was invalid");
+ return false;
+ }
}
return true;
}
diff --git a/coniks_server/src/main/java/org/coniks/coniks_server/KeyOps.java b/coniks_server/src/main/java/org/coniks/coniks_server/KeyOps.java
index 446d91a..f1b0cfd 100644
--- a/coniks_server/src/main/java/org/coniks/coniks_server/KeyOps.java
+++ b/coniks_server/src/main/java/org/coniks/coniks_server/KeyOps.java
@@ -1,33 +1,33 @@
/*
Copyright (c) 2015-16, Princeton University.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
+ modification, are permitted provided that the following conditions are
met:
- * Redistributions of source code must retain the above copyright
+ * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
distribution.
* Neither the name of Princeton University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
@@ -45,7 +45,7 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
import org.coniks.coniks_common.C2SProtos.DSAPublicKeyProto;
-/** Implements all encryption-key related operations that a
+/** Implements all encryption-key related operations that a
* CONIKS server must perform.
* Current encryption/signing algorithm used: RSA with SHA-256.
*
@@ -70,14 +70,14 @@ public static RSAPrivateKey loadSigningKey(){
// get user password and file input stream
char[] ks_password = ServerConfig.getKeystorePassword().toCharArray();
-
+
FileInputStream fis = null;
-
+
fis = new FileInputStream(ServerConfig.getKeystorePath());
ks.load(fis, ks_password);
if(ks.isKeyEntry(ServerConfig.getName())){
- KeyStore.ProtectionParameter protParam =
+ KeyStore.ProtectionParameter protParam =
new KeyStore.PasswordProtection(ks_password);
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
@@ -92,13 +92,13 @@ public static RSAPrivateKey loadSigningKey(){
}
catch(IOException e){
TimerLogger.error("KeyOps:loadSigningKey: Problem loading the keystore");
- }
+ }
catch(NoSuchAlgorithmException e){
TimerLogger.error("KeyOps:loadSigningKey: Problem with integrity check algorithm");
}
catch(CertificateException e){
TimerLogger.error("KeyOps:loadSigningKey: Problem with the cert(s) in keystore");
- }
+ }
catch(KeyStoreException e){
TimerLogger.error("KeyOps:loadSigningKey: Problem getting Keystore instance");
}
@@ -111,7 +111,7 @@ public static RSAPrivateKey loadSigningKey(){
/** Load the given server {@code keyOwner}'s public key from the truststore
* indicated in this server's configuration {@code config}.
*
- *@return The {@code keyOwner}'s public RSA key, or {@code null} in
+ *@return The {@code keyOwner}'s public RSA key, or {@code null} in
* the case of an Exception.
*/
public static RSAPublicKey loadPublicKey(String keyOwner){
@@ -122,20 +122,24 @@ public static RSAPublicKey loadPublicKey(String keyOwner){
try{
ks = KeyStore.getInstance(KeyStore.getDefaultType());
- char[] ts_password = ServerConfig.getTruststorePassword().toCharArray();
-
+ char[] ts_password =
+ ServerConfig.getTruststorePassword().toCharArray();
+
FileInputStream fis = null;
-
+
fis = new FileInputStream(ServerConfig.getTruststorePath());
ks.load(fis, ts_password);
if(ks.isKeyEntry(keyOwner)){
- KeyStore.ProtectionParameter protParam =
+ KeyStore.ProtectionParameter protParam =
new KeyStore.PasswordProtection(ts_password);
- KeyStore.TrustedCertificateEntry pkEntry = (KeyStore.TrustedCertificateEntry)
+ KeyStore.TrustedCertificateEntry pkEntry =
+ (KeyStore.TrustedCertificateEntry)
ks.getEntry(keyOwner, protParam);
- publicKey = (RSAPublicKey)pkEntry.getTrustedCertificate().getPublicKey();
+
+ publicKey =
+ (RSAPublicKey)pkEntry.getTrustedCertificate().getPublicKey();
}
else{
throw new CertificateException();
@@ -145,13 +149,13 @@ public static RSAPublicKey loadPublicKey(String keyOwner){
}
catch(IOException e){
ServerLogger.error("KeyOps:loadPublicKey: Problem loading the keystore");
- }
+ }
catch(NoSuchAlgorithmException e){
ServerLogger.error("KeyOps:loadPublicKey: Problem with integrity check algorithm");
}
catch(CertificateException e){
ServerLogger.error("KeyOps:loadPublicKey: Problem with the cert(s) in keystore");
- }
+ }
catch(KeyStoreException e){
ServerLogger.error("KeyOps:loadPublicKey: Problem getting Keystore instance");
}
@@ -165,9 +169,13 @@ public static RSAPublicKey loadPublicKey(String keyOwner){
* {@code g} and {@code y} parameters.
*
*@return the DSAPublicKey, or {@code null} in case of an error.
+ *@deprecated Replaced with {@link org.coniks.crypto.Keys#getDSAPublicFromParams(BigInteger, BigInteger, BigInteger, BigInteger)}.
*/
- public static DSAPublicKey makeDSAPublicKeyFromParams(BigInteger p, BigInteger q,
- BigInteger g, BigInteger y) {
+ @Deprecated
+ public static DSAPublicKey makeDSAPublicKeyFromParams(BigInteger p,
+ BigInteger q,
+ BigInteger g,
+ BigInteger y) {
try {
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
KeySpec publicKeySpec = new DSAPublicKeySpec(y, p, q, g);
@@ -187,7 +195,8 @@ public static DSAPublicKey makeDSAPublicKeyFromParams(BigInteger p, BigInteger q
/** Converts a {@link DSAPublicKeyProto} to a {@link DSAPublicKey}.
*
- *@param pkProto the DSA public key protobuf to convert into a DSAPublicKey.
+ *@param pkProto the DSA public key protobuf to convert into a
+ * DSAPublicKey.
*@return the DSAPublicKey, or {@code null} in case of an error.
*/
public static DSAPublicKey makeDSAPublicKeyFromProto(DSAPublicKeyProto pkProto) {
diff --git a/coniks_server/src/main/java/org/coniks/coniks_server/RequestHandler.java b/coniks_server/src/main/java/org/coniks/coniks_server/RequestHandler.java
index b9d646a..b2e02c9 100644
--- a/coniks_server/src/main/java/org/coniks/coniks_server/RequestHandler.java
+++ b/coniks_server/src/main/java/org/coniks/coniks_server/RequestHandler.java
@@ -45,6 +45,9 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
import com.google.protobuf.AbstractMessage;
import com.google.protobuf.ByteString;
+// coniks-java imports
+import org.coniks.crypto.*;
+
import org.coniks.coniks_common.MsgType;
import org.coniks.coniks_common.C2SProtos.Registration;
import org.coniks.coniks_common.C2SProtos.CommitmentReq;
@@ -302,7 +305,18 @@ private synchronized void handleSignedULNChangeProto(SignedULNChangeReq signedRe
byte[] reqMsg = changeReq.toByteArray();
byte[] sig = signedReq.getSig().toByteArray();
- if (!SignatureOps.verifySigFromDSA(reqMsg, sig, publicChangeKey)) {
+
+ boolean res = false;
+
+ try {
+ res = Signing.dsaVerify(publicChangeKey, reqMsg, sig);
+ }
+ // let's catch the panic here and log it
+ catch (Exception e) {
+ ServerLogger.error("[RequestHandler] "+e.getMessage());
+ }
+
+ if (!res) {
MsgHandlerLogger.log("Failed to verify message");
MsgHandlerLogger.log("Failed sig said\n" + Arrays.toString(sig));
ServerMessaging.sendSimpleResponseProto(ServerErr.SIGNED_CHANGE_VERIF_ERR, clientSocket);
diff --git a/coniks_server/src/main/java/org/coniks/coniks_server/ServerMessaging.java b/coniks_server/src/main/java/org/coniks/coniks_server/ServerMessaging.java
index a9a41b8..70f5138 100644
--- a/coniks_server/src/main/java/org/coniks/coniks_server/ServerMessaging.java
+++ b/coniks_server/src/main/java/org/coniks/coniks_server/ServerMessaging.java
@@ -1,33 +1,33 @@
/*
Copyright (c) 2015-16, Princeton University.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
+ modification, are permitted provided that the following conditions are
met:
- * Redistributions of source code must retain the above copyright
+ * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
distribution.
* Neither the name of Princeton University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
@@ -37,12 +37,15 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
import java.net.*;
import java.io.*;
import java.util.ArrayList;
+import java.security.NoSuchAlgorithmException;
import com.google.protobuf.AbstractMessage;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import org.javatuples.*;
+// coniks-java imports
+import org.coniks.crypto.Util;
import org.coniks.coniks_common.*;
import org.coniks.coniks_common.C2SProtos.*;
import org.coniks.coniks_common.UtilProtos.*;
@@ -55,20 +58,20 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*/
public class ServerMessaging {
- /** Sends a simple server response protobuf based on the
+ /** Sends a simple server response protobuf based on the
* result (often an error) of a client request.
*
- *@param reqResult the result of the request
+ *@param reqResult the result of the request
*@param socket the client socket to which to send the message
*/
public static synchronized void sendSimpleResponseProto(int reqResult, Socket socket){
MsgHandlerLogger.log("Sending simple server response... ");
-
+
ServerResp respMsg = buildServerRespMsg(reqResult);
- sendMsgProto(MsgType.SERVER_RESP, respMsg, socket);
+ sendMsgProto(MsgType.SERVER_RESP, respMsg, socket);
}
-
+
/** Sends the signed tree root protobuf returned for a client's signed tree root request.
*
*@param str the signed tree root to send
@@ -76,12 +79,12 @@ public static synchronized void sendSimpleResponseProto(int reqResult, Socket so
*/
public static synchronized void sendCommitmentProto(SignedTreeRoot str, Socket socket){
MsgHandlerLogger.log("Sending commitment response... ");
-
+
Commitment comm = buildCommitmentMsg(str);
-
+
sendMsgProto(MsgType.COMMITMENT, comm, socket);
}
-
+
/** Sends a basic registration response protobuf for a new name-to-key mapping
* registration.
*@param regEpoch the epoch at which the mapping will be registered in the directory
@@ -91,11 +94,11 @@ public static synchronized void sendCommitmentProto(SignedTreeRoot str, Socket s
public static synchronized void sendRegistrationRespProto(long regEpoch, int epochInterval,
Socket socket){
MsgHandlerLogger.log("Sending registration response... ");
-
+
RegistrationResp regResp = buildRegistrationRespMsg(regEpoch, epochInterval);
sendMsgProto(MsgType.REGISTRATION_RESP, regResp, socket);
}
-
+
/** Sends the authentication path protobuf returned for a client's key lookup.
*
*@param uln the key directory entry for which to send the authentication path
@@ -104,11 +107,11 @@ public static synchronized void sendRegistrationRespProto(long regEpoch, int epo
*/
public static synchronized void sendAuthPathProto(UserLeafNode uln, RootNode root, Socket socket){
MsgHandlerLogger.log("Sending authentication path response... ");
-
+
AuthPath authPath = buildAuthPathMsg(uln, root);
sendMsgProto(MsgType.AUTH_PATH, authPath, socket);
}
-
+
/** Sends any protobuf message {@code msg} of type {@code msgType}
* to the given socket.
*/
@@ -132,10 +135,10 @@ private static synchronized void sendMsgProto (int msgType, AbstractMessage msg,
CommonMessaging.close(dout);
}
- }
+ }
/* Message building functions */
-
+
// create the simple server response message
private static synchronized ServerResp buildServerRespMsg(int respType){
ServerResp.Builder respMsg = ServerResp.newBuilder();
@@ -157,20 +160,28 @@ private static synchronized ServerResp buildServerRespMsg(int respType){
break;
default:
respMsg.setMessage(ServerResp.Message.SERVER_ERR);
- break;
+ break;
}
return respMsg.build();
}
-
+
// create the commitment response message
- private static synchronized Commitment buildCommitmentMsg(SignedTreeRoot str){
-
+ private static synchronized Commitment buildCommitmentMsg(SignedTreeRoot str){
+
Commitment.Builder commMsg = Commitment.newBuilder();
byte[] rootBytes = ServerUtils.getRootNodeBytes(str.getRoot());
- byte[] rootHashBytes = ServerUtils.hash(rootBytes);
-
- Hash.Builder rootHash = Hash.newBuilder();
- if(rootHashBytes.length != ServerUtils.HASH_SIZE_BYTES){
+ byte[] rootHashBytes = null;
+
+ try {
+ rootHashBytes = Util.digest(rootBytes);
+ }
+ catch(NoSuchAlgorithmException e) {
+ ServerLogger.error("[ServerMessagging] "+e.getMessage());
+ return null;
+ }
+
+ Hash.Builder rootHash = Hash.newBuilder();
+ if(rootHashBytes.length != Util.HASH_SIZE_BYTES){
MsgHandlerLogger.error("Bad length of root hash: "+rootHashBytes.length);
return null;
}
@@ -181,18 +192,18 @@ private static synchronized Commitment buildCommitmentMsg(SignedTreeRoot str){
commMsg.setSignature(ByteString.copyFrom(str.getSignature()));
return commMsg.build();
}
-
+
// create the registration response message
- private static synchronized RegistrationResp buildRegistrationRespMsg(long initEpoch, int epochInterval){
-
+ private static synchronized RegistrationResp buildRegistrationRespMsg(long initEpoch, int epochInterval){
+
RegistrationResp.Builder regRespMsg = RegistrationResp.newBuilder();
regRespMsg.setInitEpoch(initEpoch);
regRespMsg.setEpochInterval(epochInterval);
return regRespMsg.build();
}
-
+
// create the commitment response message
- private static synchronized AuthPath buildAuthPathMsg(UserLeafNode uln, RootNode root){
+ private static synchronized AuthPath buildAuthPathMsg(UserLeafNode uln, RootNode root){
return TransparencyOps.generateAuthPathProto(uln, root);
}
@@ -205,17 +216,17 @@ private static synchronized AuthPath buildAuthPathMsg(UserLeafNode uln, RootNode
* indicated by the client.
*/
public static synchronized AbstractMessage receiveMsgProto(Socket socket) {
-
+
DataInputStream din = null;
try {
din = new DataInputStream(socket.getInputStream());
-
+
// get the message type of the message and read in the stream
int msgType = din.readUnsignedByte();
-
+
if (msgType == MsgType.REGISTRATION){
Registration reg = Registration.parseDelimitedFrom(din);
-
+
if(!reg.hasBlob() || !reg.hasChangeKey() || !reg.hasAllowsUnsignedKeychange()
|| !reg.hasAllowsPublicLookup()) {
MsgHandlerLogger.log("Malformed registration message");
@@ -226,8 +237,8 @@ public static synchronized AbstractMessage receiveMsgProto(Socket socket) {
}
else if (msgType == MsgType.KEY_LOOKUP) {
KeyLookup lookup = KeyLookup.parseDelimitedFrom(din);
-
- if(!lookup.hasName() || !lookup.hasEpoch() ||
+
+ if(!lookup.hasName() || !lookup.hasEpoch() ||
lookup.getEpoch() <= 0){
MsgHandlerLogger.log("Malformed key lookup");
}
@@ -237,7 +248,7 @@ else if (msgType == MsgType.KEY_LOOKUP) {
}
else if (msgType == MsgType.COMMITMENT_REQ) {
CommitmentReq commReq = CommitmentReq.parseDelimitedFrom(din);
-
+
if (!commReq.hasType() || !commReq.hasEpoch() || commReq.getEpoch() <= 0) {
MsgHandlerLogger.log("Malformed commitment request message");
}
@@ -274,27 +285,27 @@ else if (msgType == MsgType.SIGNED_ULNCHANGE_REQ) {
catch (IOException e) {
MsgHandlerLogger.error("receiving data from client");
}
-
+
// unexpected message type from the client
return null;
}
/* Functions for handling the lower-level communication with the client */
- /** Listens for incoming requests. Uses an SSL connection if the server is running in
+ /** Listens for incoming requests. Uses an SSL connection if the server is running in
* full operating mode.
*
- *@param isFullOp indicates whether the client is operating in full mode
+ *@param isFullOp indicates whether the client is operating in full mode
* or in testing mode
*/
public static void listenForRequests (boolean isFullOp) {
ServerSocket s = null;
-
+
try{
if (isFullOp) {
- SSLServerSocketFactory sslSrvFact =
+ SSLServerSocketFactory sslSrvFact =
(SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
s =(SSLServerSocket)sslSrvFact.createServerSocket(ServerConfig.getPort());
}
@@ -302,18 +313,18 @@ public static void listenForRequests (boolean isFullOp) {
s = new ServerSocket(ServerConfig.getPort());
System.out.println("Listening for connections on port "+ServerConfig.getPort()+"...");
- }
+ }
MsgHandlerLogger.log("Listening for connections on port "+ServerConfig.getPort()+"...");
-
+
// loop to listen for requests
while(true){
Socket c = s.accept(); // closing done by thread
-
+
MsgHandlerLogger.log("Server accepted new connection.");
RequestHandler th;
-
+
if (isFullOp) {
th = new RequestHandler((SSLSocket)c);
}
@@ -322,13 +333,13 @@ public static void listenForRequests (boolean isFullOp) {
}
th.start();
-
+
}
}
catch(IOException e){
MsgHandlerLogger.error("hello: "+e.getMessage());
}
-
+
}
-
+
}
diff --git a/coniks_server/src/main/java/org/coniks/coniks_server/ServerUtils.java b/coniks_server/src/main/java/org/coniks/coniks_server/ServerUtils.java
index 8eb7ef7..68fb9d9 100644
--- a/coniks_server/src/main/java/org/coniks/coniks_server/ServerUtils.java
+++ b/coniks_server/src/main/java/org/coniks/coniks_server/ServerUtils.java
@@ -1,33 +1,33 @@
/*
Copyright (c) 2015-16, Princeton University.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
+ modification, are permitted provided that the following conditions are
met:
- * Redistributions of source code must retain the above copyright
+ * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
distribution.
* Neither the name of Princeton University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
@@ -61,17 +61,26 @@ public class ServerUtils{
/** The size of the Merkle tree hashes in bits.
* Current hashing algorithm: SHA-256
+ *
+ *@deprecated Moved to {@link org.coniks.crypto.Util}.
*/
- public static final int HASH_SIZE_BITS = 256;
+ @Deprecated
+ public static final int HASH_SIZE_BITS = 256;
/** The size of the Merkle tree hashes in bytes.
* Current hashing algorithm: SHA-256
+ *
+ *@deprecated Moved to {@link org.coniks.crypto.Util}.
*/
+ @Deprecated
public static final int HASH_SIZE_BYTES = HASH_SIZE_BITS/8;
-
+
/** The size of the CONIKS server's STR signatures in bytes.
* Server signature scheme: RSAwithSHA256.
+ *
+ *@deprecated Moved to {@link org.coniks.crypto.Signing}.
*/
+ @Deprecated
public static final int SIG_SIZE_BYTES = 256;
/** The maximum number of bytes logged per log file.
@@ -84,7 +93,7 @@ public class ServerUtils{
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
- /** Prints server status and error messages.
+ /** Prints server status and error messages.
* Used primarily for testing mode.
*
*@param isErr indicates whether this is an error message
@@ -103,25 +112,27 @@ public static void printStatusMsg (boolean isErr, String msg) {
* Current hashing algorithm: SHA-256.
*
*@return The hash as a {@code byte[]} or null in case of an error.
+ *@deprecated Replaced with {@link org.coniks.crypto.Util#digest(byte[])}
*/
+ @Deprecated
public static byte[] hash(byte[] input){
- try{
- MessageDigest md = MessageDigest.getInstance("SHA-256");
-
- byte[] digest = md.digest(input);
+ try{
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
+
+ byte[] digest = md.digest(input);
- return digest;
+ return digest;
- }
- catch(NoSuchAlgorithmException e){
- ServerLogger.error("SHA-256 is not a valid algorithm for some reason");
- }
+ }
+ catch(NoSuchAlgorithmException e){
+ ServerLogger.error("SHA-256 is not a valid algorithm for some reason");
+ }
- return null; // should never get here
+ return null; // should never get here
}
- /** Generates the cryptographic hash of the {@code left}
+ /** Generates the cryptographic hash of the {@code left}
* and {@code right} subtree hashes of a Merkle tree node.
* This is really just a wrapper around {@link ServerUtils#hash(byte[])}.
*
@@ -129,27 +140,27 @@ public static byte[] hash(byte[] input){
*/
public static byte[] hashChildren(byte[] left, byte[] right){
- byte[] childrenBytes = new byte[left.length+right.length];
-
- ByteBuffer arr = ByteBuffer.wrap(childrenBytes);
- arr.put(left);
- arr.put(right);
+ byte[] childrenBytes = new byte[left.length+right.length];
- byte[] children = arr.array();
+ ByteBuffer arr = ByteBuffer.wrap(childrenBytes);
+ arr.put(left);
+ arr.put(right);
- try{
- MessageDigest md = MessageDigest.getInstance("SHA-256");
-
- byte[] digest = md.digest(children);
+ byte[] children = arr.array();
- return digest;
+ try{
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
- }
- catch(NoSuchAlgorithmException e){
- TimerLogger.error("SHA-256 is not a valid algorithm for some reason");
- }
+ byte[] digest = md.digest(children);
- return null; // should never get here
+ return digest;
+
+ }
+ catch(NoSuchAlgorithmException e){
+ TimerLogger.error("SHA-256 is not a valid algorithm for some reason");
+ }
+
+ return null; // should never get here
}
@@ -179,12 +190,12 @@ public static byte[] strToBytes (String str) {
* index using a verifiable unpredicctable function (VUF).
* Current VUF algorithm: SHA-256.
*
- *@return The {@code byte[]} representation of the
+ *@return The {@code byte[]} representation of the
* lookup index.
*/
public static byte[] unameToIndex (String uname){
- byte[] b = strToBytes(uname);
- return ServerUtils.hash(b);
+ byte[] b = strToBytes(uname);
+ return ServerUtils.hash(b);
}
/** Converts a long {@code val} into an array of bytes.
@@ -193,7 +204,7 @@ public static byte[] unameToIndex (String uname){
*/
public static byte[] longToBytes(long val) {
byte[] byteArr = new byte[8];
-
+
for(int i = 0; i < 8; i++) {
byte nextByte = (byte)((val >> i*8) & 0xff);
byteArr[i] = nextByte;
@@ -202,16 +213,16 @@ public static byte[] longToBytes(long val) {
return byteArr;
}
- /** Finds the byte in the byte array {@code arr}
+ /** Finds the byte in the byte array {@code arr}
* at offset {@code offset}, and determines whether it is 1 or 0.
*
*@return true if the nth bit is 1, false otherwise.
*/
public static boolean getNthBit(byte[] arr, int offset){
- int arrayOffset = offset / 8;
- int bitOfByte = offset % 8;
- int maskedBit = arr[arrayOffset] & (1 << (7 - bitOfByte));
- return (maskedBit != 0);
+ int arrayOffset = offset / 8;
+ int bitOfByte = offset % 8;
+ int maskedBit = arr[arrayOffset] & (1 << (7 - bitOfByte));
+ return (maskedBit != 0);
}
/** Gets the 16-bit prefix of a byte array {@code arr}.
@@ -220,7 +231,7 @@ public static boolean getNthBit(byte[] arr, int offset){
* of the array is less than 2 bytes.
*/
public static byte[] getPrefixBytes(byte[] arr){
- byte[] out = new byte[2];
+ byte[] out = new byte[2];
if (arr.length < 2) {
out[0] = 0;
@@ -230,7 +241,7 @@ public static byte[] getPrefixBytes(byte[] arr){
out[0] = arr[0];
out[1] = arr[1];
}
- return out;
+ return out;
}
/** Compares two byte buffers for byte-by-byte equality.
@@ -242,14 +253,14 @@ public static boolean compareByteBuffers(byte[] buf1, byte[] buf2){
return false;
}
- for(int i = 0; i < buf1.length; i++){
- if(buf1[i] != buf2[i]){
- return false;
- }
- }
- return true;
+ for(int i = 0; i < buf1.length; i++){
+ if(buf1[i] != buf2[i]){
+ return false;
+ }
+ }
+ return true;
}
-
+
/** Converts an RSAPublicKey {@code pub} to a hashable array of bytes.
* This function is currently unused.
@@ -257,16 +268,16 @@ public static boolean compareByteBuffers(byte[] buf1, byte[] buf2){
*@return The {@code byte[]} containing the serialized RSAPublicKey.
*/
public static byte[] convertRSAPubKey(RSAPublicKey pub){
- byte[] exp = pub.getPublicExponent().toByteArray();
- byte[] mod = pub.getModulus().toByteArray();
+ byte[] exp = pub.getPublicExponent().toByteArray();
+ byte[] mod = pub.getModulus().toByteArray();
- byte[] pubKey = new byte[exp.length+mod.length];
+ byte[] pubKey = new byte[exp.length+mod.length];
- ByteBuffer arr = ByteBuffer.wrap(pubKey);
- arr.put(exp);
- arr.put(mod);
+ ByteBuffer arr = ByteBuffer.wrap(pubKey);
+ arr.put(exp);
+ arr.put(mod);
- return arr.array();
+ return arr.array();
}
/** Converts an DSAPublicKey {@code pub} to a hashable array of bytes.
@@ -275,20 +286,20 @@ public static byte[] convertRSAPubKey(RSAPublicKey pub){
*@return The {@code byte[]} containing the serialized DSAPublicKey.
*/
public static byte[] convertDSAPubKey(DSAPublicKey pub){
- byte[] g = pub.getParams().getG().toByteArray();
+ byte[] g = pub.getParams().getG().toByteArray();
byte[] p = pub.getParams().getP().toByteArray();
byte[] q = pub.getParams().getQ().toByteArray();
byte[] y = pub.getY().toByteArray();
- byte[] pubKey = new byte[g.length+p.length+q.length+y.length];
+ byte[] pubKey = new byte[g.length+p.length+q.length+y.length];
- ByteBuffer arr = ByteBuffer.wrap(pubKey);
- arr.put(g);
+ ByteBuffer arr = ByteBuffer.wrap(pubKey);
+ arr.put(g);
arr.put(p);
arr.put(q);
- arr.put(y);
+ arr.put(y);
- return arr.array();
+ return arr.array();
}
// TODO: use real dsa keys
@@ -298,24 +309,24 @@ public static byte[] convertDSAPubKey(DSAPublicKey pub){
*/
public static byte[] getUserLeafNodeBytes(UserLeafNode uln){
byte[] pubKey = strToBytes(uln.getPublicKey());
- byte[] usr = strToBytes(uln.getUsername());
+ byte[] usr = strToBytes(uln.getUsername());
byte[] ck = convertDSAPubKey(uln.getChangeKey());
byte[] ep_add = longToBytes(uln.getEpochAdded());
byte[] auk = new byte[]{(byte)(uln.allowsUnsignedKeychange() ? 0x01 : 0x00)};
byte[] apl = new byte[]{(byte)(uln.allowsPublicLookups() ? 0x01 : 0x00)};
- byte[] leafBytes = new byte[pubKey.length+usr.length+ck.length+ep_add.length+auk.length+
+ byte[] leafBytes = new byte[pubKey.length+usr.length+ck.length+ep_add.length+auk.length+
apl.length];
-
- ByteBuffer arr = ByteBuffer.wrap(leafBytes);
- arr.put(usr);
- arr.put(pubKey);
+
+ ByteBuffer arr = ByteBuffer.wrap(leafBytes);
+ arr.put(usr);
+ arr.put(pubKey);
arr.put(ck);
- arr.put(ep_add);
- arr.put(auk);
+ arr.put(ep_add);
+ arr.put(auk);
arr.put(apl);
- return arr.array();
+ return arr.array();
}
/** Converts a {@link InteriorNode} {@code in} to a hashable array of bytes.
@@ -323,16 +334,16 @@ public static byte[] getUserLeafNodeBytes(UserLeafNode uln){
*@return The {@code byte[]} containing the serialized InteriorNode.
*/
public static byte[] getInteriorNodeBytes(InteriorNode in){
- byte[] left = in.getLeftHash();
- byte[] right = in.getRightHash();
+ byte[] left = in.getLeftHash();
+ byte[] right = in.getRightHash();
- byte[] nodeBytes = new byte[left.length+right.length];
-
- ByteBuffer arr = ByteBuffer.wrap(nodeBytes);
- arr.put(left);
- arr.put(right);
+ byte[] nodeBytes = new byte[left.length+right.length];
- return arr.array();
+ ByteBuffer arr = ByteBuffer.wrap(nodeBytes);
+ arr.put(left);
+ arr.put(right);
+
+ return arr.array();
}
/** Converts a {@link RootNode} {@code rn} to a hashable array of bytes.
@@ -340,20 +351,20 @@ public static byte[] getInteriorNodeBytes(InteriorNode in){
*@return The {@code byte[]} containing the serialized RootNode.
*/
public static byte[] getRootNodeBytes(RootNode rn){
- byte[] left = rn.getLeftHash();
- byte[] right = rn.getRightHash();
+ byte[] left = rn.getLeftHash();
+ byte[] right = rn.getRightHash();
+
+ byte[] rootBytes = new byte[left.length+right.length];
- byte[] rootBytes = new byte[left.length+right.length];
-
- ByteBuffer arr = ByteBuffer.wrap(rootBytes);
- arr.put(left);
- arr.put(right);
+ ByteBuffer arr = ByteBuffer.wrap(rootBytes);
+ arr.put(left);
+ arr.put(right);
- return arr.array();
+ return arr.array();
}
/** Takes the components of a signed tree root: root node, current epoch,
- * previous epoch, hash of previous STR, and serializes them into
+ * previous epoch, hash of previous STR, and serializes them into
* a byte[] that can be used to generate the STR's digital signature.
*
*@return The {@code byte[]} containing the serialized STR components.
@@ -371,19 +382,19 @@ public static byte[] getSTRBytesForSig(RootNode rn, long ep, long prevEp,
byte[] epBytes = longToBytes(ep);
byte[] prevEpBytes = longToBytes(prevEp);
- byte[] strBytes = new byte[rootBytes.length+epBytes.length+prevEpBytes.length+
+ byte[] strBytes = new byte[rootBytes.length+epBytes.length+prevEpBytes.length+
prevStrHash.length];
-
- ByteBuffer arr = ByteBuffer.wrap(strBytes);
- arr.put(rootBytes);
- arr.put(epBytes);
+
+ ByteBuffer arr = ByteBuffer.wrap(strBytes);
+ arr.put(rootBytes);
+ arr.put(epBytes);
arr.put(prevEpBytes);
arr.put(prevStrHash);
- return arr.array();
+ return arr.array();
}
-
+
/** Converts a {@link SignedTreeRoot} {@code str} to a hashable array of bytes
*
*@return The {@code byte[]} containing the serialized STR components.
@@ -402,17 +413,17 @@ public static byte[] getSTRBytes(SignedTreeRoot str) {
byte[] prevStrHash = str.getPrevSTRHash();
byte[] sig = str.getSignature();
- byte[] strBytes = new byte[rootBytes.length+epBytes.length+prevEpBytes.length+
+ byte[] strBytes = new byte[rootBytes.length+epBytes.length+prevEpBytes.length+
prevStrHash.length+sig.length];
-
- ByteBuffer arr = ByteBuffer.wrap(strBytes);
- arr.put(rootBytes);
- arr.put(epBytes);
+
+ ByteBuffer arr = ByteBuffer.wrap(strBytes);
+ arr.put(rootBytes);
+ arr.put(epBytes);
arr.put(prevEpBytes);
arr.put(prevStrHash);
arr.put(sig);
- return arr.array();
+ return arr.array();
}
@@ -423,8 +434,8 @@ public static byte[] getSTRBytes(SignedTreeRoot str) {
*@author Marcela S. Melara (melara@cs.princeton.edu)
*@author Michael Rochlin
*/
- public static class PrefixComparator implements Comparator> {
-
+ public static class PrefixComparator implements Comparator> {
+
/** Compares the first 24 bits of two data binding lookup indeces.
*
*@return 0 if they are equal, 1 if the lookup index of {@code p1} is greater, and
@@ -434,21 +445,21 @@ public static class PrefixComparator implements Comparator p1, Triplet p2) {
- byte[] buf1 = p1.getValue0();
- byte[] buf2 = p2.getValue0();
-
- if (buf1.length < 3 || buf2.length < 3) {
- throw new RuntimeException("bad byte array length");
- }
-
- for(int i = 0; i < 3; i++){
- if(buf1[i] > buf2[i]){
- return 1;
- }else if (buf1[i] < buf2[i]){
- return -1;
- }
- }
-
+ byte[] buf1 = p1.getValue0();
+ byte[] buf2 = p2.getValue0();
+
+ if (buf1.length < 3 || buf2.length < 3) {
+ throw new RuntimeException("bad byte array length");
+ }
+
+ for(int i = 0; i < 3; i++){
+ if(buf1[i] > buf2[i]){
+ return 1;
+ }else if (buf1[i] < buf2[i]){
+ return -1;
+ }
+ }
+
// registrations must always happen before ulnChanges
// earlier ulnChanges must always happen before later ones
Operation op1 = p1.getValue2();
@@ -462,9 +473,9 @@ public int compare(Triplet p1, Triplet ((KeyChange)op2).getCounter()) ? 1 : -1;
}
-
- return 0;
- }
+
+ return 0;
+ }
}
} //ends ServerUtils class
diff --git a/coniks_server/src/main/java/org/coniks/coniks_server/SignatureOps.java b/coniks_server/src/main/java/org/coniks/coniks_server/SignatureOps.java
index eb4662c..5b9c24e 100644
--- a/coniks_server/src/main/java/org/coniks/coniks_server/SignatureOps.java
+++ b/coniks_server/src/main/java/org/coniks/coniks_server/SignatureOps.java
@@ -1,33 +1,33 @@
/*
Copyright (c) 2015-16, Princeton University.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
+ modification, are permitted provided that the following conditions are
met:
- * Redistributions of source code must retain the above copyright
+ * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
distribution.
* Neither the name of Princeton University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
@@ -58,71 +58,80 @@ public class SignatureOps{
* of the {@code input}.
*@throws A RuntimeException if there is a problem with the private key
* loaded from the server's keystore.
+ *@deprecated Replaced with {@link org.coniks.crypto.Signing#rsaSign(RSAPublicKey, byte[])}.
*/
+ @Deprecated
public static byte[] sign(byte[] input) {
RSAPrivateKey MY_PRIV_KEY = KeyOps.loadSigningKey();
- byte[] signed = null;
+ byte[] signed = null;
if(MY_PRIV_KEY == null){
- throw new RuntimeException("borked pk?");
+ throw new RuntimeException("borked pk?");
}
-
- try{
- Signature signer = Signature.getInstance("SHA256withRSA");
- signer.initSign(MY_PRIV_KEY, new SecureRandom());
+
+ try{
+ Signature signer = Signature.getInstance("SHA256withRSA");
+ signer.initSign(MY_PRIV_KEY, new SecureRandom());
signer.update(input);
-
- signed = signer.sign();
- return signed;
- }
- catch(NoSuchAlgorithmException e){
- TimerLogger.error("RSA is invalid for some reason.");
- }
- catch(InvalidKeyException e){
- TimerLogger.error("The given key is invalid.");
- }
+
+ signed = signer.sign();
+ return signed;
+ }
+ catch(NoSuchAlgorithmException e){
+ TimerLogger.error("RSA is invalid for some reason.");
+ }
+ catch(InvalidKeyException e){
+ TimerLogger.error("The given key is invalid.");
+ }
catch(SignatureException e){
- TimerLogger.error("The format of the sig input is invalid.");
- }
-
- return signed;
+ TimerLogger.error("The format of the sig input is invalid.");
+ }
+
+ return signed;
}
- /** Verify a given server {@code keyOwner}'s digital signature {@code signature}
- * on the message {@code msg}.
+ /** Verify a given server {@code keyOwner}'s digital signature
+ * {@code signature} on the message {@code msg}.
*
- *@return {@code true} if the signature on the message is valid, {@code false}
- * otherwise.
+ *@return {@code true} if the signature on the message is valid,
+ * {@code false} otherwise.
+ *@deprecated Replaced with {@link org.coniks.crypto.Signing#rsaVerify(RSAPublicKey, byte[], byte[])}.
*/
- public static boolean verifySig(byte[] msg, byte[] signature, String keyOwner){
+ @Deprecated
+ public static boolean verifySig(byte[] msg, byte[] signature,
+ String keyOwner){
RSAPublicKey pubKey = KeyOps.loadPublicKey(keyOwner);
- try{
-
- Signature verifier = Signature.getInstance("SHA256withRSA");
- verifier.initVerify(pubKey);
- verifier.update(msg);
-
- return verifier.verify(signature);
- }
- catch(NoSuchAlgorithmException e){
- TimerLogger.error("SHA256withRSA is invalid for some reason.");
- }
- catch(InvalidKeyException e){
- TimerLogger.error("The given key is invalid.");
- }
- catch(SignatureException e){
- TimerLogger.error("The format of the input is invalid: "+e.getMessage());
- }
-
- return false;
+ try{
+
+ Signature verifier = Signature.getInstance("SHA256withRSA");
+ verifier.initVerify(pubKey);
+ verifier.update(msg);
+
+ return verifier.verify(signature);
+ }
+ catch(NoSuchAlgorithmException e){
+ TimerLogger.error("SHA256withRSA is invalid for some reason.");
+ }
+ catch(InvalidKeyException e){
+ TimerLogger.error("The given key is invalid.");
+ }
+ catch(SignatureException e){
+ TimerLogger.error("The format of the input is invalid: "+e.getMessage());
+ }
+
+ return false;
}
- /** Verify {@code msg} with {@code sig} using {@code pk} */
+ /** Verify {@code msg} with {@code sig} using {@code pk}
+ *
+ *@deprecated Replaced with {@link org.coniks.crypto.Signing#dsaVerify(DSAPublicKey, byte[], byte[])}.
+ */
+ @Deprecated
public static boolean verifySigFromDSA(byte[] msg, byte[] sig, PublicKey pk) {
try {
Signature verifyalg = Signature.getInstance("DSA");
diff --git a/coniks_server/src/main/java/org/coniks/coniks_server/TransparencyOps.java b/coniks_server/src/main/java/org/coniks/coniks_server/TransparencyOps.java
index 00a8663..84fcbd6 100644
--- a/coniks_server/src/main/java/org/coniks/coniks_server/TransparencyOps.java
+++ b/coniks_server/src/main/java/org/coniks/coniks_server/TransparencyOps.java
@@ -1,39 +1,43 @@
/*
Copyright (c) 2015-16, Princeton University.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
+ modification, are permitted provided that the following conditions are
met:
- * Redistributions of source code must retain the above copyright
+ * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
distribution.
* Neither the name of Princeton University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
package org.coniks.coniks_server;
import com.google.protobuf.ByteString;
+
+// coniks-java imports
+import org.coniks.crypto.Signing;
+import org.coniks.crypto.Util;
import org.coniks.coniks_common.C2SProtos.AuthPath;
import org.coniks.coniks_common.C2SProtos.*;
import org.coniks.coniks_common.UtilProtos.Hash;
@@ -43,16 +47,15 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
import java.util.TreeMap;
import java.util.PriorityQueue;
import java.security.*;
-import java.security.interfaces.RSAPublicKey;
-import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.*;
import java.nio.ByteBuffer;
import org.javatuples.*;
-/** Implements all transparency-related operations done by a
+/** Implements all transparency-related operations done by a
* CONIKS server.
* These allow a CONIKS client to perform the consistency checks.
- *
+ *
*@author Marcela S. Melara (melara@cs.princeton.edu)
*@author Aaron Blankstein
*@author Michael Rochlin
@@ -67,13 +70,22 @@ public class TransparencyOps{
*/
public static SignedTreeRoot generateSTR(RootNode root, long ep,
long prevEp, byte[] prevStrHash) {
-
+
byte[] strBytesPreSig = ServerUtils.getSTRBytesForSig(root, ep, prevEp,
prevStrHash);
- byte[] sig = SignatureOps.sign(strBytesPreSig);
-
- return new SignedTreeRoot(root, ep, prevEp, prevStrHash, sig, null);
+ RSAPrivateKey key = KeyOps.loadSigningKey();
+
+ byte[] sig = null;
+ try {
+ sig = Signing.rsaSign(key, strBytesPreSig);
+ }
+ catch (Exception e) {
+ ServerLogger.error("[RequestHandler] "+e.getMessage());
+ return null;
+ }
+
+ return new SignedTreeRoot(root, ep, prevEp, prevStrHash, sig, null);
}
/** Generates the STR from the root node {@code root} for the epoch
@@ -88,24 +100,41 @@ public static synchronized SignedTreeRoot generateNextSTR(RootNode root, long ep
// generate the hash of the current STR to include is in the next
// STR as the previous STR hash
- byte[] prevStrHash = ServerUtils.hash(ServerUtils.getSTRBytes(ServerHistory.getCurSTR()));
+ byte[] prevStrHash = null;
+
+ try {
+ prevStrHash = Util.digest(ServerUtils.getSTRBytes(ServerHistory.getCurSTR()));
+ }
+ catch(NoSuchAlgorithmException e) {
+ ServerLogger.error("[TransparencyOps] "+e.getMessage());
+ return null;
+ }
byte[] strBytesPreSig = ServerUtils.getSTRBytesForSig(root, ep, prevEpoch,
prevStrHash);
- byte[] sig = SignatureOps.sign(strBytesPreSig);
-
- return new SignedTreeRoot(root, ep, prevEpoch, prevStrHash, sig, ServerHistory.getCurSTR());
+ RSAPrivateKey key = KeyOps.loadSigningKey();
+
+ byte[] sig = null;
+ try {
+ sig = Signing.rsaSign(key, strBytesPreSig);
+ }
+ catch (Exception e) {
+ ServerLogger.error("[TransparencyOps] "+e.getMessage());
+ return null;
+ }
+
+ return new SignedTreeRoot(root, ep, prevEpoch, prevStrHash, sig, ServerHistory.getCurSTR());
}
-
- /** Generates the authentication path protobuf message from the
+
+ /** Generates the authentication path protobuf message from the
* root node {@code root} to the user leaf node {@code uln}.
*
- *@return The {@link org.coniks.coniks_common.C2SProtos.AuthPath}
+ *@return The {@link org.coniks.coniks_common.C2SProtos.AuthPath}
* protobuf message or {@code null} upon failure.
*/
public static AuthPath generateAuthPathProto(UserLeafNode uln, RootNode root){
-
+
AuthPath.Builder authPath = AuthPath.newBuilder();
//first take care of setting the UserLeafNode
@@ -136,18 +165,18 @@ public static AuthPath generateAuthPathProto(UserLeafNode uln, RootNode root){
// book-keeping for interior nodes
int numInteriors = 0;
- ArrayList interiorList = new ArrayList();
-
+ ArrayList interiorList = new ArrayList();
+
// get the prefix from the key
-
- byte[] lookupIndex = ServerUtils.unameToIndex(uln.getUsername());
- byte[] prefix = ServerUtils.getPrefixBytes(lookupIndex);
+ byte[] lookupIndex = ServerUtils.unameToIndex(uln.getUsername());
+
+ byte[] prefix = ServerUtils.getPrefixBytes(lookupIndex);
String prefixStr = ServerUtils.bytesToHex(prefix);
// not worth doing this recursively
int curOffset = 0;
- TreeNode runner = root;
+ TreeNode runner = root;
while (!(runner instanceof UserLeafNode)) {
@@ -155,18 +184,18 @@ public static AuthPath generateAuthPathProto(UserLeafNode uln, RootNode root){
// true = right
boolean direction = ServerUtils.getNthBit(lookupIndex, curOffset);
- byte[] prunedChildHash = new byte[ServerUtils.HASH_SIZE_BYTES];
+ byte[] prunedChildHash = new byte[Util.HASH_SIZE_BYTES];
- if (runner == null){
- ServerLogger.error("Null runner" + curOffset);
- }
+ if (runner == null){
+ ServerLogger.error("Null runner" + curOffset);
+ }
if (runner instanceof RootNode) {
RootNode curNodeR = (RootNode) runner;
AuthPath.RootNode.Builder rootBuilder = AuthPath.RootNode.newBuilder();
-
+
if(!direction){
prunedChildHash = curNodeR.getRightHash();
rootBuilder.setPrunedchild(AuthPath.PrunedChild.RIGHT);
@@ -179,36 +208,36 @@ public static AuthPath generateAuthPathProto(UserLeafNode uln, RootNode root){
}
Hash.Builder subtree = Hash.newBuilder();
- if(prunedChildHash.length != ServerUtils.HASH_SIZE_BYTES){
+ if(prunedChildHash.length != Util.HASH_SIZE_BYTES){
ServerLogger.error("Bad length of pruned child hash: "+prunedChildHash.length);
return null;
}
subtree.setLen(prunedChildHash.length);
subtree.setHash(ByteString.copyFrom(prunedChildHash));
rootBuilder.setSubtree(subtree.build());
-
+
authPath.setRoot(rootBuilder.build());
-
+
curOffset++;
}
else {
InteriorNode curNodeI = (InteriorNode) runner;
-
+
AuthPath.InteriorNode.Builder inBuilder = AuthPath.InteriorNode.newBuilder();
-
+
if(!direction){
prunedChildHash = curNodeI.getRightHash();
inBuilder.setPrunedchild(AuthPath.PrunedChild.RIGHT);
runner = curNodeI.getLeft();
- }
+ }
else {
prunedChildHash = curNodeI.getLeftHash();
inBuilder.setPrunedchild(AuthPath.PrunedChild.LEFT);
runner = curNodeI.getRight();
}
Hash.Builder subtree = Hash.newBuilder();
- if(prunedChildHash.length != ServerUtils.HASH_SIZE_BYTES){
+ if(prunedChildHash.length != Util.HASH_SIZE_BYTES){
ServerLogger.error("Bad length of pruned child hash: "+prunedChildHash.length);
return null;
}
@@ -216,22 +245,22 @@ public static AuthPath generateAuthPathProto(UserLeafNode uln, RootNode root){
subtree.setHash(ByteString.copyFrom(prunedChildHash));
inBuilder.setSubtree(subtree.build());
interiorList.add(0, inBuilder.build());
-
- if (runner == null){
- ServerLogger.error("such sadness...");
- }
+
+ if (runner == null){
+ ServerLogger.error("such sadness...");
+ }
curOffset++;
numInteriors++;
}
-
+
}
ulnBuilder.setIntlevels(numInteriors);
authPath.setLeaf(ulnBuilder.build());
authPath.addAllInterior(interiorList);
-
+
return authPath.build();
}
-
+
}
diff --git a/coniks_server/src/main/java/org/coniks/coniks_server/TreeBuilder.java b/coniks_server/src/main/java/org/coniks/coniks_server/TreeBuilder.java
index bd14682..65899d2 100644
--- a/coniks_server/src/main/java/org/coniks/coniks_server/TreeBuilder.java
+++ b/coniks_server/src/main/java/org/coniks/coniks_server/TreeBuilder.java
@@ -1,33 +1,33 @@
/*
Copyright (c) 2015-16, Princeton University.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
+ modification, are permitted provided that the following conditions are
met:
- * Redistributions of source code must retain the above copyright
+ * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
distribution.
* Neither the name of Princeton University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
@@ -35,13 +35,17 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
import java.util.PriorityQueue;
import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPublicKey;
+// coniks-java imports
+import org.coniks.crypto.Util;
+
import org.javatuples.*;
/** Implements all operations necessary for building a CONIKS
- * Merkle prefix tree on the server.
+ * Merkle prefix tree on the server.
* Current hashing algorithm used: SHA-256.
*
*@author Marcela S. Melara (melara@cs.princeton.edu)
@@ -49,29 +53,29 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*@author Michael Rochlin
*/
public class TreeBuilder{
-
+
private static int lastLevel;
-
+
// inserts a new user leaf node into the tree
private static void insertNode(byte[] key, UserLeafNode toAdd, RootNode root, Operation op){
int curOffset = 0;
// This code would be a lot more natural
// if our tries were byte-branching rather than bit-branching, but whatevs.
-
+
toAdd.level = 0;
TreeNode curNode = root;
-
+
curNode.setName("root");
int counter = 1;
-
+
insertLoop:
while(true){
int arrayOffset = curOffset / 8;
int bitOfByte = curOffset % 8;
// 0 is left-most byte in string
- // 0 of left-most byte is the *left-most* bit of that byte.
+ // 0 of left-most byte is the *left-most* bit of that byte.
toAdd.level++;
-
+
if( curNode instanceof UserLeafNode ){
// reached a "bottom" of the tree.
// add a new interior node and push the previous leaf down
@@ -79,11 +83,11 @@ private static void insertNode(byte[] key, UserLeafNode toAdd, RootNode root, Op
if (curNode.parent == null){
throw new UnsupportedOperationException("parent is null!!");
}
-
+
// TODO: Does this need to be moved?
InteriorNode newInt = new InteriorNode(curNode.parent,
curNode.level);
-
+
UserLeafNode curNodeUL = (UserLeafNode) curNode;
if (curNodeUL.username.equals( toAdd.username )) {
if (op instanceof Register) {
@@ -106,11 +110,11 @@ else if (op instanceof KeyChange) {
throw new UnsupportedOperationException("Weird operation happened. Make sure you've added this functionality");
}
}
-
+
if (!(op instanceof Register)) {
throw new UnsupportedOperationException("Failed to make key-change!");
}
-
+
byte[] curNodeKey = ServerUtils.unameToIndex(curNodeUL.username);
curNodeUL.setIndex(curNodeKey);
// This is what's happening below:
@@ -118,7 +122,7 @@ else if (op instanceof KeyChange) {
int maskedBit = curNodeKey[arrayOffset] & (1 << (7 - bitOfByte));
// direction here is going to be false = left,
// true = right
-
+
boolean direction = (maskedBit != 0);
if (direction){
newInt.right = curNodeUL;
@@ -127,7 +131,7 @@ else if (op instanceof KeyChange) {
}
curNode.level++;
curNode.parent = newInt;
-
+
if (newInt.parent.left == curNode) {
newInt.parent.left = newInt;
}
@@ -135,16 +139,16 @@ else if (op instanceof KeyChange) {
newInt.parent.right = newInt;
}
curNode = newInt;
- toAdd.level--;
- }
+ toAdd.level--;
+ }
else {
InteriorNode curNodeI = (InteriorNode) curNode;
int maskedBit = key[arrayOffset] & (1 << (7 - bitOfByte));
// direction here is going to be false = left,
// true = right
-
+
boolean direction = (maskedBit != 0);
-
+
if(direction){
// mark right tree as needing hash recompute
curNodeI.rightHash = null;
@@ -175,47 +179,49 @@ else if (op instanceof KeyChange) {
lastLevel = toAdd.level;
}
}
-
+
// Compute the hashes of the left and right subtrees
// of the Merkle tree root
// Wrapper for innerComputeHash
- private static void computeHashes(RootNode root){
+ private static void computeHashes(RootNode root)
+ throws NoSuchAlgorithmException {
if (root.leftHash == null){
- root.leftHash = innerComputeHash(root.left);
+ root.leftHash = innerComputeHash(root.left);
}
if (root.rightHash == null){
root.rightHash = innerComputeHash(root.right);
}
}
-
+
// this recursively computes the hash of the subtree specified
// by curNode
- private static byte[] innerComputeHash(TreeNode curNode){
- if(curNode == null) {
- return ServerUtils.hash(new byte[ServerUtils.HASH_SIZE_BYTES]);
- }
-
- if(curNode instanceof InteriorNode){
- InteriorNode curNodeI = (InteriorNode) curNode;
- if(curNodeI.leftHash == null){
- // compute left-side hash
- curNodeI.leftHash = innerComputeHash(curNode.left);
- }
- if(curNodeI.rightHash == null){
- // compute right-side hash
- curNodeI.rightHash = innerComputeHash(curNode.right);
- }
-
- return ServerUtils.hash(ServerUtils.getInteriorNodeBytes(curNodeI));
- }
+ private static byte[] innerComputeHash(TreeNode curNode)
+ throws NoSuchAlgorithmException {
+ if(curNode == null) {
+ return Util.digest(new byte[Util.HASH_SIZE_BYTES]);
+ }
+
+ if(curNode instanceof InteriorNode){
+ InteriorNode curNodeI = (InteriorNode) curNode;
+ if(curNodeI.leftHash == null){
+ // compute left-side hash
+ curNodeI.leftHash = innerComputeHash(curNode.left);
+ }
+ if(curNodeI.rightHash == null){
+ // compute right-side hash
+ curNodeI.rightHash = innerComputeHash(curNode.right);
+ }
+
+ return Util.digest(ServerUtils.getInteriorNodeBytes(curNodeI));
+ }
else{
- // assertion: must be user leaf node.
- UserLeafNode curNodeU = (UserLeafNode) curNode;
- return ServerUtils.hash(ServerUtils.getUserLeafNodeBytes(curNodeU));
- }
+ // assertion: must be user leaf node.
+ UserLeafNode curNodeU = (UserLeafNode) curNode;
+ return Util.digest(ServerUtils.getUserLeafNodeBytes(curNodeU));
+ }
}
-
- /** Clones a Merkle prefix tree {@code prevRoot} and
+
+ /** Clones a Merkle prefix tree {@code prevRoot} and
* extends it with any new nodes in {@code pendingQ}.
*
*@return The {@link RootNode} for the next epoch's Merkle tree.
@@ -229,52 +235,62 @@ public static RootNode copyExtendTree(RootNode prevRoot,
}else{
newRoot = new RootNode(null, null, 0);
}
-
+
if(pendingQ == null) {
ServerLogger.error("Trying to extend using null pending queue");
return null;
}
- return extendTree(pendingQ, newRoot);
+
+ RootNode r = null;
+
+ try {
+ r = extendTree(pendingQ, newRoot);
+ }
+ catch(NoSuchAlgorithmException e) {
+ ServerLogger.error("Trying to extend using null pending queue");
+ }
+ return r;
}
-
- /** Inserts any new nodes in {@code pendingQ} ordered by the 24-bit prefix
- * of their lookup index into the Merkle tree, and recomputes all necessary
- * hashes.
+
+ /** Inserts any new nodes in {@code pendingQ} ordered by the 24-bit
+ * prefix of their lookup index into the Merkle tree, and recomputes
+ * all necessary hashes.
*
*@return The {@link RootNode} of the extended Merkle tree.
*/
- private static RootNode extendTree(
- PriorityQueue> pendingQ,
- RootNode root) {
-
+ private static RootNode extendTree(PriorityQueue> pendingQ,
+ RootNode root)
+ throws NoSuchAlgorithmException {
+
RootNode newRoot = root;
-
+
byte[] prefix = null;
-
+
int toInsert = pendingQ.size();
-
+
Triplet p = pendingQ.poll();
while(p != null){
// while we're handing the same prefix,
// insert as normal
byte[] index = p.getValue0();
prefix = ServerUtils.getPrefixBytes(index);
-
+
UserLeafNode toAdd = p.getValue1();
Operation op = p.getValue2();
-
+
insertNode(index, toAdd, newRoot, op);
-
+
p = pendingQ.poll();
-
+
toInsert--;
-
+
}
-
+
// recompute hashes
computeHashes(newRoot);
-
+
return newRoot;
}
-
+
}
diff --git a/coniks_test_client/README.md b/coniks_test_client/README.md
index 613b7ae..49bf051 100644
--- a/coniks_test_client/README.md
+++ b/coniks_test_client/README.md
@@ -17,12 +17,16 @@ The coniks_test_client build is managed using Maven. (Instructions for building
```$ mvn package```
These instructions will install the ``coniks_test_client`` Maven artifact.
+The build configuration for coniks_test_client assembles all dependencies,
+and includes them in the generated .jar file, so you can run the server
+only using the coniks_test_client .jar file.
##Using the Test Client
-The CONIKS test client has two operating modes: Test Mode and Full Operation.
-Running the client in test mode allows you to still test all CONIKS protocols and operations,
-but requires less setup as you can simply use the default configuration in the included *config* file.
+The CONIKS test client has two operating modes: Test Mode and Full Operation.
+Running the client in test mode allows you to still test all CONIKS
+protocols and operations, but requires less setup as you can simply use
+the default configuration in the included *config* file.
**Note:** You must be running the server in the same operating mode.
### Setup
@@ -34,8 +38,8 @@ keytool -import -alias -file -keystore ```: start the client in full operation mode, connecting it to the given server.
- ```test ```: start the client in test mode, connecting it to the given server.
- ```clean```: remove all logs written by the client.
@@ -66,7 +70,7 @@ perform the operation and the first dummy user for which to run the operation. D
identified by numbers, so user "5" is the 5th dummy user.
The test client will prompt you until you no longer want to continue.
-Supported operations:
+Supported operations:
- ```REGISTER```: register a new name-to-public key mapping with the CONIKS server.
- ```LOOKUP```: look up a public key, and verify the cryptographic proof of inclusion if the user exists.
- ```SIGNED```: change the public key registered for an existing name and authorize this change via a digital signature.
@@ -81,7 +85,7 @@ Some examples:
- POLICY 1 18: changes the key change policy for user 18.
## Disclaimer
-Please keep in mind that this CONIKS reference implementation is under active development. The repository may contain experimental features that aren't fully tested. We recommend using a [tagged release](https://github.com/coniks-sys/coniks-java/releases).
+Please keep in mind that this CONIKS Java implementation is under active development. The repository may contain experimental features that aren't fully tested. We recommend using a [tagged release](https://github.com/coniks-sys/coniks-java/releases).
##Documentation
[Read the test client's Java API (javadoc)](https://coniks-sys.github.io/coniks-java/org/coniks/coniks_test_client/package-summary.html)
diff --git a/coniks_test_client/coniks_test_client.sh b/coniks_test_client/coniks_test_client.sh
index ac36cb3..9507c01 100755
--- a/coniks_test_client/coniks_test_client.sh
+++ b/coniks_test_client/coniks_test_client.sh
@@ -4,37 +4,38 @@
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
+# modification, are permitted provided that the following conditions are
# met:
-# * Redistributions of source code must retain the above copyright
+# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Princeton University nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
-# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
## Runs or a CONIKS test client instance
# Set all the configs here
-CLASS_DEST="bin" #change this if you built the server somewhere else
+# mvn builds our jar with dependencies
+CLASS_DEST="./target/coniks_test_client-1.3-SNAPSHOT.jar"
CLASSPATH="-cp $CLASS_DEST"
CLIENT_BIN="org.coniks.coniks_test_client.TestClient"
CONIKS_CLIENTCONFIG="config"
diff --git a/coniks_test_client/pom.xml b/coniks_test_client/pom.xml
index e535fa8..a36d01a 100644
--- a/coniks_test_client/pom.xml
+++ b/coniks_test_client/pom.xml
@@ -5,28 +5,31 @@
org.coniksconiks-java
- 1.2-SNAPSHOT
+ 1.3-SNAPSHOTorg.coniks.coniks_test_clientconiks_test_client
+ 1.3-SNAPSHOTjar
- 1.2-SNAPSHOT
- coniks_test_client
+
+ CONIKS [Test Client]http://coniks.org
+ CONIKS client library and reference implementation.
+
- junit
- junit
- 3.8.1
- test
+ org.coniks.coniks_common
+ coniks_common
+ 1.3-SNAPSHOT
+ compile
- org.coniks.coniks_common
- coniks_common
- 1.2-SNAPSHOT
+ org.coniks.crypto
+ coniks-crypto
+ 1.3-SNAPSHOTcompile
@@ -48,4 +51,26 @@
UTF-8
+
+
+
+
+ maven-assembly-plugin
+
+
+ package
+
+ single
+
+
+
+
+
+ jar-with-dependencies
+
+ false
+
+
+
+
diff --git a/coniks_test_client/src/main/java/org/coniks/coniks_test_client/ClientUtils.java b/coniks_test_client/src/main/java/org/coniks/coniks_test_client/ClientUtils.java
index cccafe2..a91ad40 100644
--- a/coniks_test_client/src/main/java/org/coniks/coniks_test_client/ClientUtils.java
+++ b/coniks_test_client/src/main/java/org/coniks/coniks_test_client/ClientUtils.java
@@ -1,33 +1,33 @@
/*
Copyright (c) 2015-16, Princeton University.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
+ modification, are permitted provided that the following conditions are
met:
- * Redistributions of source code must retain the above copyright
+ * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
distribution.
* Neither the name of Princeton University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
@@ -65,17 +65,26 @@ public class ClientUtils{
/** The size of the Merkle tree hashes in bits.
* Current hashing algorithm: SHA-256
+ *
+ *@deprecated Moved to {@link org.coniks.crypto.Util}.
*/
- public static final int HASH_SIZE_BITS = 256;
+ @Deprecated
+ public static final int HASH_SIZE_BITS = 256;
/** The size of the Merkle tree hashes in bytes.
* Current hashing algorithm: SHA-256
+ *
+ *@deprecated Moved to {@link org.coniks.crypto.Util}.
*/
+ @Deprecated
public static final int HASH_SIZE_BYTES = HASH_SIZE_BITS/8;
-
+
/** The size of the CONIKS server's STR signatures in bytes.
* Expected server signature scheme: RSAwithSHA256.
+ *
+ *@deprecated Moved to {@link org.coniks.crypto.Signing}.
*/
+ @Deprecated
public static final int SIG_SIZE_BYTES = 256;
/** The maximum number of bytes logged per log file.
@@ -97,25 +106,27 @@ public class ClientUtils{
* Current hashing algorithm: SHA-256.
*
*@return The hash as a {@code byte[]} or null in case of an error.
+ *@deprecated Replaced with {@link org.coniks.crypto.Util#digest(byte[])}
*/
+ @Deprecated
public static byte[] hash(byte[] input){
- try{
- MessageDigest md = MessageDigest.getInstance("SHA-256");
-
- byte[] digest = md.digest(input);
+ try{
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
+
+ byte[] digest = md.digest(input);
- return digest;
+ return digest;
- }
- catch(NoSuchAlgorithmException e){
- ClientLogger.error("SHA-256 is not a valid algorithm for some reason");
- }
+ }
+ catch(NoSuchAlgorithmException e){
+ ClientLogger.error("SHA-256 is not a valid algorithm for some reason");
+ }
- return null; // should never get here
+ return null; // should never get here
}
- /** Generates the cryptographic hash of the {@code left}
+ /** Generates the cryptographic hash of the {@code left}
* and {@code right} subtree hashes of a Merkle tree node.
* This is really just a wrapper around {@link ClientUtils#hash(byte[])}.
*
@@ -123,27 +134,27 @@ public static byte[] hash(byte[] input){
*/
public static byte[] hashChildren(byte[] left, byte[] right){
- byte[] childrenBytes = new byte[left.length+right.length];
-
- ByteBuffer arr = ByteBuffer.wrap(childrenBytes);
- arr.put(left);
- arr.put(right);
+ byte[] childrenBytes = new byte[left.length+right.length];
+
+ ByteBuffer arr = ByteBuffer.wrap(childrenBytes);
+ arr.put(left);
+ arr.put(right);
- byte[] children = arr.array();
+ byte[] children = arr.array();
- try{
- MessageDigest md = MessageDigest.getInstance("SHA-256");
-
- byte[] digest = md.digest(children);
+ try{
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
- return digest;
+ byte[] digest = md.digest(children);
- }
- catch(NoSuchAlgorithmException e){
- ClientLogger.error("SHA-256 is not a valid algorithm for some reason");
- }
+ return digest;
+
+ }
+ catch(NoSuchAlgorithmException e){
+ ClientLogger.error("SHA-256 is not a valid algorithm for some reason");
+ }
- return null; // should never get here
+ return null; // should never get here
}
@@ -173,12 +184,12 @@ public static byte[] strToBytes (String str) {
* index using a verifiable unpredicctable function (VUF).
* Current VUF algorithm: SHA-256.
*
- *@return The {@code byte[]} representation of the
+ *@return The {@code byte[]} representation of the
* lookup index.
*/
public static byte[] unameToIndex (String username){
- byte[] b = strToBytes(username);
- return ClientUtils.hash(b);
+ byte[] b = strToBytes(username);
+ return ClientUtils.hash(b);
}
/** Converts a long {@code val} into an array of bytes.
@@ -187,7 +198,7 @@ public static byte[] unameToIndex (String username){
*/
public static byte[] longToBytes(long val) {
byte[] byteArr = new byte[8];
-
+
for(int i = 0; i < 8; i++) {
byte nextByte = (byte)((val >> i*8) & 0xff);
byteArr[i] = nextByte;
@@ -196,25 +207,25 @@ public static byte[] longToBytes(long val) {
return byteArr;
}
- /** Finds the byte in the byte array {@code arr}
+ /** Finds the byte in the byte array {@code arr}
* at offset {@code offset}, and determines whether it is 1 or 0.
*
*@return true if the nth bit is 1, false otherwise.
*/
public static boolean getNthBit(byte[] arr, int offset){
- int arrayOffset = offset / 8;
- int bitOfByte = offset % 8;
- int maskedBit = arr[arrayOffset] & (1 << (7 - bitOfByte));
- return (maskedBit != 0);
+ int arrayOffset = offset / 8;
+ int bitOfByte = offset % 8;
+ int maskedBit = arr[arrayOffset] & (1 << (7 - bitOfByte));
+ return (maskedBit != 0);
}
-
+
/** Gets the 16-bit prefix of a byte array {@code arr}.
*
*@return the first 16 bits of {@code arr} or all zeros if the length
* of the array is less than 2 bytes.
*/
public static byte[] getPrefixBytes(byte[] arr){
- byte[] out = new byte[2];
+ byte[] out = new byte[2];
if (arr.length < 2) {
out[0] = 0;
@@ -224,9 +235,9 @@ public static byte[] getPrefixBytes(byte[] arr){
out[0] = arr[0];
out[1] = arr[1];
}
- return out;
+ return out;
}
-
+
/** Compares two byte buffers for byte-by-byte equality.
*
@@ -237,17 +248,17 @@ public static boolean compareByteBuffers(byte[] buf1, byte[] buf2){
return false;
}
- for(int i = 0; i < buf1.length; i++){
- if(buf1[i] != buf2[i]){
- return false;
- }
- }
- return true;
+ for(int i = 0; i < buf1.length; i++){
+ if(buf1[i] != buf2[i]){
+ return false;
+ }
+ }
+ return true;
}
/** Converts a DSAPublicKey {@code pub} to a byte array.
*
- *@return the DSA public key as a {@code byte[]} in g-p-q-y order
+ *@return the DSA public key as a {@code byte[]} in g-p-q-y order
*/
public static byte[] convertDSAPubKey(DSAPublicKey pub){
byte[] g = strToBytes(pub.getParams().getG().toString());
@@ -268,7 +279,7 @@ public static byte[] convertDSAPubKey(DSAPublicKey pub){
/** Converts a DSAPublicKeyProto {@code pub} to a byte array.
*
- *@return the DSA public key protobuf as a {@code byte[]} in g-p-q-y order
+ *@return the DSA public key protobuf as a {@code byte[]} in g-p-q-y order
*/
public static byte[] convertDSAPubKey(DSAPublicKeyProto pub){
byte[] g = strToBytes(pub.getG());
@@ -304,7 +315,7 @@ public static DSAPublicKeyProto buildDSAPublicKeyProto(DSAPublicKey pub) {
*
*@return the DSAPublicKeyProto
*/
- public static DSAPublicKeyProto buildDSAPublicKeyProto(BigInteger p,
+ public static DSAPublicKeyProto buildDSAPublicKeyProto(BigInteger p,
BigInteger q,
BigInteger g,
BigInteger y) {
@@ -318,7 +329,7 @@ public static DSAPublicKeyProto buildDSAPublicKeyProto(BigInteger p,
}
- /** Converts an AuthPath.UserLeafNode protobuf {@code uln}
+ /** Converts an AuthPath.UserLeafNode protobuf {@code uln}
* to a {@code byte[]}.
*/
public static byte[] ulnProtoToBytes(AuthPath.UserLeafNode uln){
@@ -335,7 +346,7 @@ public static byte[] ulnProtoToBytes(AuthPath.UserLeafNode uln){
byte[] leafBytes = new byte[pubKey.length+usr.length+ep_add.length+auk.length+
apl.length+ep_changed.length+ck.length+sig.length+lastMsg.length];
-
+
ByteBuffer arr = ByteBuffer.wrap(leafBytes);
arr.put(usr);
arr.put(pubKey);
@@ -362,12 +373,12 @@ public static byte[] computeInteriorNodeProtoHashes(byte[] ulnHash,
for(int i = 0; i < inList.size(); i++){
AuthPath.InteriorNode in = inList.get(i);
-
+
if(!in.hasPrunedchild() && !in.hasSubtree()){
ClientLogger.error("No pruned child at level: "+i);
return null;
}
-
+
Hash pcHash = in.getSubtree();
AuthPath.PrunedChild pcSide = in.getPrunedchild();
@@ -379,14 +390,14 @@ public static byte[] computeInteriorNodeProtoHashes(byte[] ulnHash,
}
byte[] prunedChild = subtreeHash.toByteArray();
-
+
if(pcSide == AuthPath.PrunedChild.LEFT){
curHash = ClientUtils.hashChildren(prunedChild, curHash);
}
else if(pcSide == AuthPath.PrunedChild.RIGHT){
curHash = ClientUtils.hashChildren(curHash, prunedChild);
}
-
+
}
// at this point, curHash should be the root node's direct child
@@ -395,7 +406,7 @@ else if(pcSide == AuthPath.PrunedChild.RIGHT){
}
/** Takes the hash {@code authPathHash} computed from an authentication path
- * and incorporates it into the root node {@code root} of an
+ * and incorporates it into the root node {@code root} of an
* AuthPath.RootNode protobuf. Returns this root node as a byte[].
*/
public static byte[] rootProtoToBytes(byte[] authPathHash, AuthPath.RootNode root){
@@ -409,12 +420,12 @@ public static byte[] rootProtoToBytes(byte[] authPathHash, AuthPath.RootNode roo
ClientLogger.error("Bad hash length");
return null;
}
-
+
byte[] prunedChild = subtreeHash.toByteArray();
byte[] rootBytes = new byte[authPathHash.length+prunedChild.length];
-
- ByteBuffer arr = ByteBuffer.wrap(rootBytes);
+
+ ByteBuffer arr = ByteBuffer.wrap(rootBytes);
if(pcSide == AuthPath.PrunedChild.LEFT){
arr.put(prunedChild);
diff --git a/coniks_test_client/src/main/java/org/coniks/coniks_test_client/ConsistencyChecks.java b/coniks_test_client/src/main/java/org/coniks/coniks_test_client/ConsistencyChecks.java
index ff00ff9..5c06030 100644
--- a/coniks_test_client/src/main/java/org/coniks/coniks_test_client/ConsistencyChecks.java
+++ b/coniks_test_client/src/main/java/org/coniks/coniks_test_client/ConsistencyChecks.java
@@ -1,33 +1,33 @@
/*
Copyright (c) 2015-16, Princeton University.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
+ modification, are permitted provided that the following conditions are
met:
- * Redistributions of source code must retain the above copyright
+ * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
distribution.
* Neither the name of Princeton University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
@@ -44,6 +44,8 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
import com.google.protobuf.ByteString;
import org.javatuples.*;
+// coniks-java imports
+import org.coniks.crypto.Util;
import org.coniks.coniks_common.ServerErr;
import org.coniks.coniks_common.C2SProtos.RegistrationResp;
import org.coniks.coniks_common.C2SProtos.AuthPath;
@@ -54,7 +56,7 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* on data received from a CONIKS server.
* These include data binding proof verification,
* and non-equivocation checks.
- *
+ *
*@author Marcela S. Melara (melara@cs.princeton.edu)
*@author Aaron Blankstein
*/
@@ -91,26 +93,27 @@ public static int verifyPubKeyProto (ConiksUser user, AuthPath authPath) {
/** Recomputes the root node from an AuthPath protobuf message
* {@code authPath}.
*
- *@return The recomputed root node as a {@code byte[]} or {@code null}
+ *@return The recomputed root node as a {@code byte[]} or {@code null}
* upon failure.
*/
- private static byte[] recomputeAuthPathRootProto(AuthPath authPath){
-
- AuthPath.UserLeafNode apUln = authPath.getLeaf();
+ private static byte[] recomputeAuthPathRootProto(AuthPath authPath)
+ throws NoSuchAlgorithmException{
+
+ AuthPath.UserLeafNode apUln = authPath.getLeaf();
ByteString index = apUln.getLookupIndex();
// verify the input: expect the index to be the size of the hash
- if(index.size() != ClientUtils.HASH_SIZE_BYTES){
+ if(index.size() != Util.HASH_SIZE_BYTES){
ClientLogger.error("Bad index length");
return null;
}
-
+
byte[] lookupIndex = index.toByteArray();
int numInteriors = apUln.getIntlevels();
- byte[] ulnHash = ClientUtils.hash(ClientUtils.ulnProtoToBytes(apUln));
-
- ArrayList inList =
+ byte[] ulnHash = Util.digest(ClientUtils.ulnProtoToBytes(apUln));
+
+ ArrayList inList =
new ArrayList(authPath.getInteriorList());
if(inList.size() != numInteriors){
@@ -130,7 +133,7 @@ private static byte[] recomputeAuthPathRootProto(AuthPath authPath){
ClientLogger.error("Root malformed");
return null;
}
-
+
return ClientUtils.rootProtoToBytes(interiorsHash, root);
}
@@ -141,16 +144,24 @@ private static byte[] recomputeAuthPathRootProto(AuthPath authPath){
*@return A {@link ConsistencyErr} error code. {@code NO_ERR} indicates
* that the verification passed.
*/
- public static int verifyMappingProto (AuthPath authPath, Commitment comm){
+ public static int verifyMappingProto (AuthPath authPath,
+ Commitment comm){
// this really shouldn't be null at this point, but we'll check jic
if (authPath == null /*|| comm == null*/) {
return ServerErr.MALFORMED_SERVER_MSG_ERR;
}
-
+
// first recompute the root node from the authentication path
- byte[] recomputedRoot = recomputeAuthPathRootProto(authPath);
-
+ byte[] recomputedRoot = null;
+
+ try {
+ recomputedRoot = recomputeAuthPathRootProto(authPath);
+ }
+ catch(NoSuchAlgorithmException e) {
+ return ClientUtils.INTERNAL_CLIENT_ERR;
+ }
+
if (recomputedRoot == null) {
return ServerErr.MALFORMED_SERVER_MSG_ERR;
}
@@ -159,7 +170,18 @@ public static int verifyMappingProto (AuthPath authPath, Commitment comm){
// TODO: implement this
// compute the hash of the recomputed root
- byte[] recomputedRootHash = ClientUtils.hash(recomputedRoot);
+ byte[] recomputedRootHash = null;
+ try {
+ recomputedRootHash = Util.digest(recomputedRoot);
+ }
+ catch(NoSuchAlgorithmException e) {
+ return ClientUtils.INTERNAL_CLIENT_ERR;
+ }
+
+ // something still went wrong with the hash computation
+ if (recomputedRootHash == null) {
+ return ClientUtils.INTERNAL_CLIENT_ERR;
+ }
// get the received root hash from the commitment and compare
// the two byte buffers
diff --git a/coniks_test_client/src/main/java/org/coniks/coniks_test_client/KeyOps.java b/coniks_test_client/src/main/java/org/coniks/coniks_test_client/KeyOps.java
index e68046e..2d85419 100644
--- a/coniks_test_client/src/main/java/org/coniks/coniks_test_client/KeyOps.java
+++ b/coniks_test_client/src/main/java/org/coniks/coniks_test_client/KeyOps.java
@@ -1,33 +1,33 @@
/*
Copyright (c) 2015-16, Princeton University.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
+ modification, are permitted provided that the following conditions are
met:
- * Redistributions of source code must retain the above copyright
+ * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
distribution.
* Neither the name of Princeton University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
@@ -71,7 +71,7 @@ public static DSAPublicKey loadDSAPublicKeyFile (String uname) {
try {
fis = new FileInputStream(filename);
- byte[] keyBytes = new byte[fis.available()];
+ byte[] keyBytes = new byte[fis.available()];
fis.read(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("DSA", "SUN");
@@ -115,7 +115,7 @@ public static DSAPrivateKey loadDSAPrivateKeyFile(String uname){
try {
fis = new FileInputStream(filename);
- byte[] keyBytes = new byte[fis.available()];
+ byte[] keyBytes = new byte[fis.available()];
fis.read(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("DSA", "SUN");
@@ -152,7 +152,8 @@ public static DSAPrivateKey loadDSAPrivateKeyFile(String uname){
*@param pubKey the public key to store for this user
*@return whether the save succeeded
*/
- public static boolean saveDSAPublicKeyFile (String uname, DSAPublicKey pubKey) {
+ public static boolean saveDSAPublicKeyFile (String uname,
+ DSAPublicKey pubKey) {
byte[] keyBytes = pubKey.getEncoded();
String filename = ClientConfig.getUserKeysPath()+"/"+uname+".pub";
@@ -183,7 +184,8 @@ public static boolean saveDSAPublicKeyFile (String uname, DSAPublicKey pubKey) {
*@param pr the private key to be saved
*@return whether the private key was successfully saved or not
*/
- public static boolean saveDSAPrivateKeyFile(String uname, DSAPrivateKey pr) {
+ public static boolean saveDSAPrivateKeyFile(String uname,
+ DSAPrivateKey pr) {
byte[] keyBytes = pr.getEncoded();
String filename = ClientConfig.getUserKeysPath()+"/"+uname+".pr";
@@ -209,7 +211,6 @@ public static boolean saveDSAPrivateKeyFile(String uname, DSAPrivateKey pr) {
}
-
/** Saves the given key pair to disk. Generates an empty
* keystore for the private key if one doesn't exist.
*
@@ -218,11 +219,12 @@ public static boolean saveDSAPrivateKeyFile(String uname, DSAPrivateKey pr) {
*@return whether the save succeeded
*/
public static boolean saveDSAKeyPairFile(String uname, KeyPair kp) {
-
+
boolean success = false;
if (saveDSAPrivateKeyFile(uname, (DSAPrivateKey)kp.getPrivate())) {
- success = saveDSAPublicKeyFile(uname, (DSAPublicKey)kp.getPublic());
+ success =
+ saveDSAPublicKeyFile(uname, (DSAPublicKey)kp.getPublic());
}
return success;
@@ -231,11 +233,14 @@ public static boolean saveDSAKeyPairFile(String uname, KeyPair kp) {
/** Generates a DSA key pair for the client.
*
*@return the DSA key pair or null in case of an error
+ *@deprecated Replaced with
+ *{@link org.coniks.crypto.Keys#generateDSAKeyPair()}.
*/
+ @Deprecated
public static KeyPair generateDSAKeyPair(){
KeyPairGenerator kg;
-
+
try{
kg = KeyPairGenerator.getInstance("DSA");
kg.initialize(1024, new SecureRandom());
diff --git a/coniks_test_client/src/main/java/org/coniks/coniks_test_client/SignatureOps.java b/coniks_test_client/src/main/java/org/coniks/coniks_test_client/SignatureOps.java
index a45712e..5746b4e 100644
--- a/coniks_test_client/src/main/java/org/coniks/coniks_test_client/SignatureOps.java
+++ b/coniks_test_client/src/main/java/org/coniks/coniks_test_client/SignatureOps.java
@@ -1,32 +1,32 @@
/*
Copyright (c) 2015-16, Princeton University.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
+ modification, are permitted provided that the following conditions are
met:
- * Redistributions of source code must retain the above copyright
+ * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
distribution.
* Neither the name of Princeton University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
@@ -39,17 +39,6 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
import javax.crypto.*;
import java.math.BigInteger;
-// TODO(mrochlin)
-// Should use protected keystore instead of just file streams
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-
/** Implements all operations involving digital signatures
* that a CONIKS client must perform.
*
@@ -57,11 +46,17 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*/
public class SignatureOps{
- /** Verifies {@code msg} and the {@code sig} using the DSA PublicKey {@code pk}
+ /** Verifies {@code msg} and the {@code sig} using the DSA PublicKey
+ * {@code pk}
*
- *@return {@code true} if the signature is valid, {@code false} otherwise.
+ *@return {@code true} if the signature is valid,
+ * {@code false} otherwise.
+ *@deprecated Replaced with
+ *{@link org.coniks.crypto.Signing#dsaVerify(DSAPublicKey, byte[], byte[])}.
*/
- public static boolean verifySigFromDSA(byte[] msg, byte[] sig, PublicKey pk) {
+ @Deprecated
+ public static boolean verifySigFromDSA(byte[] msg, byte[] sig,
+ PublicKey pk) {
try {
Signature verifyalg = Signature.getInstance("DSA");
verifyalg.initVerify(pk);
@@ -84,10 +79,12 @@ public static boolean verifySigFromDSA(byte[] msg, byte[] sig, PublicKey pk) {
return false;
}
- /** Signs {@code msg} using DSAPrivateKey {@code prk}
+ /** Signs {@code msg} using DSAPrivateKey {@code prk}
*
- *@return the signature or null on an error
+ *@return the signature or null on an error
+ *@deprecated Replaced with {@link org.coniks.crypto.Signing#dsaSign(DSAPublicKey, byte[], byte[])}.
*/
+ @Deprecated
public static byte[] signDSA(byte[] msg, DSAPrivateKey prk) throws InvalidKeyException {
if (prk == null) {
ClientLogger.error("The given key is invalid.");
diff --git a/coniks_test_client/src/main/java/org/coniks/coniks_test_client/TestClient.java b/coniks_test_client/src/main/java/org/coniks/coniks_test_client/TestClient.java
index a75f4fd..15cf118 100644
--- a/coniks_test_client/src/main/java/org/coniks/coniks_test_client/TestClient.java
+++ b/coniks_test_client/src/main/java/org/coniks/coniks_test_client/TestClient.java
@@ -1,33 +1,33 @@
/*
Copyright (c) 2015-16, Princeton University.
All rights reserved.
-
+
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
+ modification, are permitted provided that the following conditions are
met:
- * Redistributions of source code must retain the above copyright
+ * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
distribution.
* Neither the name of Princeton University nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
@@ -44,6 +44,10 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
import java.lang.NumberFormatException;
import com.google.protobuf.*;
+
+// coniks-java imports
+import org.coniks.crypto.Signing;
+import org.coniks.crypto.Keys;
import org.coniks.coniks_common.C2SProtos.*;
import org.coniks.coniks_common.UtilProtos.ServerResp;
import org.coniks.coniks_common.ServerErr;
@@ -52,9 +56,9 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* that simply displays how each component of the
* protocol works.
* The client is completely agnostic to the underlying format
- * of the data sent to the server (it only needs to know
+ * of the data sent to the server (it only needs to know
* whether it's using protobufs)).
- *
+ *
*@author Marcela S. Melara (melara@cs.princeton.edu)
*@author Aaron Blankstein
*@author Michael Rochlin
@@ -72,15 +76,15 @@ public class TestClient {
private static final String FAKE_PK_DATA = "fake key data";
/** List of coniks users - for now used for testing */
- private static HashMap users;
+ private static HashMap users;
private static int changeCtr = 0; // this is just used to change the key data
-
+
/** Sets the default truststore according to the {@link ClientConfig}.
* This is needed to set up SSL connections with a CONIKS server.
*/
private static void setDefaultTruststore () {
- System.setProperty("javax.net.ssl.trustStore",
+ System.setProperty("javax.net.ssl.trustStore",
ClientConfig.getTruststorePath());
System.setProperty("javax.net.ssl.trustStorePassword",
ClientConfig.getTruststorePassword());
@@ -118,7 +122,7 @@ private static int getServerErr (ServerResp serverResp) {
break;
default:
serverErr = ServerErr.SERVER_ERR;
- break;
+ break;
}
return serverErr;
@@ -133,14 +137,23 @@ private static int getServerErr (ServerResp serverResp) {
*@return whether the registration succeeded or an error code
*/
private static int register (String uname, String server) {
- KeyPair kp = KeyOps.generateDSAKeyPair();
+ KeyPair kp = null;
+
+ try {
+ kp = Keys.generateDSAKeyPair();
+ }
+ catch(NoSuchAlgorithmException e) {
+ ClientLogger.error("[TestClient] "+e.getMessage());
+ return ClientUtils.INTERNAL_CLIENT_ERR;
+ }
+
String pk = uname+" "+FAKE_PK_DATA;
ClientUser user = new ClientUser(uname, pk, kp);
users.put(uname, user);
ClientMessaging.sendRegistrationProto(user, server);
-
+
AbstractMessage serverMsg = ClientMessaging.receiveRegistrationRespProto();
if (serverMsg == null) {
@@ -223,7 +236,7 @@ private static int signedKeyChange(String uname, String server) {
System.out.println("user "+uname+" allows unsigned key changes");
}
- // ugh, maybe this isn't the best.
+ // ugh, maybe this isn't the best.
// we're testing the signing, mostly, so the key data doesn't really matter right now
String newKeyData = user.getKeyData()+changeCtr;
@@ -235,22 +248,32 @@ private static int signedKeyChange(String uname, String server) {
}
// update the change key for good measure
- KeyPair newCk = KeyOps.generateDSAKeyPair();
+ KeyPair newCk = null;
+
+ try {
+ newCk = Keys.generateDSAKeyPair();
+ }
+ catch(NoSuchAlgorithmException e) {
+ ClientLogger.error("[TestClient] "+e.getMessage());
+ user.unloadChangePrivKey();
+ return ClientUtils.INTERNAL_CLIENT_ERR;
+ }
// sign the whole key change request (including all unchanged data)
byte[] sig = null;
try {
- ULNChangeReq changeReq = ClientMessaging.buildULNChangeReqMsgProto(user.getUsername(),
- newKeyData,
- (DSAPublicKey)newCk.getPublic(),
- user.isAllowsUnsignedChanges(),
- user.isAllowsPublicVisibility());
+ ULNChangeReq changeReq =
+ ClientMessaging.buildULNChangeReqMsgProto(user.getUsername(),
+ newKeyData,
+ (DSAPublicKey)newCk.getPublic(),
+ user.isAllowsUnsignedChanges(),
+ user.isAllowsPublicVisibility());
- sig = SignatureOps.signDSA(changeReq.toByteArray(), prKey);
+ sig = Signing.dsaSign(prKey, changeReq.toByteArray());
}
- catch (InvalidKeyException e) {
- ClientLogger.error(e.getMessage());
+ catch (NoSuchAlgorithmException e) {
+ ClientLogger.error("[TestClient] "+e.getMessage());
user.unloadChangePrivKey();
return ClientUtils.INTERNAL_CLIENT_ERR;
}
@@ -284,7 +307,7 @@ else if (serverMsg instanceof ServerResp) {
else {
// TODO: verify registration resp and save the new key data to disk
changeCtr++;
-
+
return ConsistencyErr.CHECK_PASSED;
}
@@ -306,7 +329,7 @@ private static int unsignedKeyChange(String uname, String server) {
return ConsistencyErr.DISALLOWED_OP_ERR;
}
- // ugh, maybe this isn't the best.
+ // ugh, maybe this isn't the best.
// we're testing the signing, mostly, so the key data doesn't really matter right now
String newKeyData = user.getKeyData()+changeCtr;
user.setKeyData(newKeyData);
@@ -324,7 +347,7 @@ else if (serverMsg instanceof ServerResp) {
else {
// TODO: check the registration resp and save the new key data to disk
changeCtr++;
-
+
return ConsistencyErr.CHECK_PASSED;
}
}
@@ -355,23 +378,32 @@ private static int changeKeyChangePolicy(String uname, String server) {
System.out.println("no private key for "+uname);
return ConsistencyErr.KEYSTORE_ERR;
}
-
+
// update the change key for good measure
- KeyPair newCk = KeyOps.generateDSAKeyPair();
-
+ KeyPair newCk = null;
+
+ try {
+ newCk = Keys.generateDSAKeyPair();
+ }
+ catch(NoSuchAlgorithmException e) {
+ ClientLogger.error("[TestClient] "+e.getMessage());
+ user.unloadChangePrivKey();
+ return ClientUtils.INTERNAL_CLIENT_ERR;
+ }
+
// sign the whole policy change request (including all unchanged data)
byte[] sig = null;
try {
- ULNChangeReq changeReq = ClientMessaging.buildULNChangeReqMsgProto(user.getUsername(), user.getKeyData(),
- (DSAPublicKey)newCk.getPublic(),
- user.isAllowsUnsignedChanges(),
+ ULNChangeReq changeReq = ClientMessaging.buildULNChangeReqMsgProto(user.getUsername(), user.getKeyData(),
+ (DSAPublicKey)newCk.getPublic(),
+ user.isAllowsUnsignedChanges(),
user.isAllowsPublicVisibility());
- sig = SignatureOps.signDSA(changeReq.toByteArray(), prKey);
+ sig = Signing.dsaSign(prKey, changeReq.toByteArray());
}
- catch (InvalidKeyException e) {
- ClientLogger.error(e.getMessage());
+ catch (NoSuchAlgorithmException e) {
+ ClientLogger.error("[TestClient] "+e.getMessage());
user.unloadChangePrivKey();
return ClientUtils.INTERNAL_CLIENT_ERR;
}
@@ -384,7 +416,7 @@ private static int changeKeyChangePolicy(String uname, String server) {
ClientLogger.error("Couldn't get a signature for the new policy");
return ClientUtils.INTERNAL_CLIENT_ERR;
}
-
+
// now we can update the user's data internally
user.saveChangeKeyPair(newCk);
@@ -480,7 +512,7 @@ private static void printErrMsg (int err, String uname) {
break;
default:
printErr("Some unknown server error occurred: "+err);
- break;
+ break;
}
}
@@ -491,9 +523,9 @@ private static void printErrMsg (int err, String uname) {
*@return {@code true} if it's valid, {@code false} otherwise.
*/
private static boolean isValidOperation (String op) {
- if (op.equalsIgnoreCase("LOOKUP") ||
- op.equalsIgnoreCase("REGISTER") ||
- op.equalsIgnoreCase("SIGNED") ||
+ if (op.equalsIgnoreCase("LOOKUP") ||
+ op.equalsIgnoreCase("REGISTER") ||
+ op.equalsIgnoreCase("SIGNED") ||
op.equalsIgnoreCase("UNSIGNED") ||
op.equalsIgnoreCase("POLICY")) {
return true;
@@ -537,7 +569,7 @@ else if (numUsers >= 100 && i % (1+ (numUsers / 50)) == 0) {
String uname = "test-"+(offset+i);
int error = 0;
-
+
if(op.equalsIgnoreCase("LOOKUP")){
error = lookup(uname, server);
}
@@ -553,7 +585,7 @@ else if (op.equalsIgnoreCase("UNSIGNED")) {
else if (op.equalsIgnoreCase("POLICY")) {
error = changeKeyChangePolicy(uname, server);
}
-
+
// if we got an error, print a new line so the error msg doesn't
// appear next to the progress dots
if (error != ServerErr.SUCCESS && error != ConsistencyErr.CHECK_PASSED) {
@@ -635,7 +667,7 @@ else if (opMode.equalsIgnoreCase("test")) {
// prompt for the user's name
System.out.print("Enter the next operation (or h for help): ");
-
+
// get their input as a String
String op = scanner.next();
@@ -683,11 +715,11 @@ else if (isValidOperation(op)) {
doOperation(op, numUsers, offset);
System.out.print("Would you like to perform another operation? [y/n]: ");
-
+
cont = scanner.next();
while (!cont.equalsIgnoreCase("y") && !cont.equalsIgnoreCase("n")) {
- System.out.print("Please enter y or n: ");
+ System.out.print("Please enter y or n: ");
cont = scanner.next();
}
}
@@ -696,7 +728,7 @@ else if (isValidOperation(op)) {
usage();
break;
}
-
+
}
System.out.println("Goodbye.");
diff --git a/crypto/pom.xml b/crypto/pom.xml
new file mode 100644
index 0000000..ae287bd
--- /dev/null
+++ b/crypto/pom.xml
@@ -0,0 +1,26 @@
+
+
+ 4.0.0
+
+
+ org.coniks
+ coniks-java
+ 1.3-SNAPSHOT
+
+
+ org.coniks.crypto
+ coniks-crypto
+ 1.3-SNAPSHOT
+ jar
+
+ CONIKS [Crypto]
+ http://coniks.org
+
+ Cryptographic algorithms and operations library for CONIKS.
+
+
+
+ UTF-8
+
+
diff --git a/crypto/src/main/java/org/coniks/crypto/Keys.java b/crypto/src/main/java/org/coniks/crypto/Keys.java
new file mode 100644
index 0000000..f331bbb
--- /dev/null
+++ b/crypto/src/main/java/org/coniks/crypto/Keys.java
@@ -0,0 +1,137 @@
+/*
+ Copyright (c) 2016, Princeton University.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Princeton University nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.coniks.crypto;
+
+import java.security.*;
+import java.security.interfaces.*;
+import java.security.spec.*;
+import java.math.BigInteger;
+
+/** Implements all encryption-key related operations for CONIKS.
+ * Currently supported algorithms: RSA with SHA-256 and DSA.
+ *
+ *@author Marcela S. Melara (melara@cs.princeton.edu)
+ *@author Michael Rochlin
+ */
+public class Keys {
+
+ /** Generates a DSA key pair.
+ *
+ *@return the DSA key pair or null in case of an error.
+ *@throws java.security.NoSuchAlgorithmException
+ */
+ public static KeyPair generateDSAKeyPair()
+ throws NoSuchAlgorithmException {
+ KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA");
+ gen.initialize(1024);
+
+ KeyPair pair = gen.generateKeyPair();
+
+ return pair;
+ }
+
+ /** Get the private key from the DSA key pair.
+ *
+ *@param kp The DSA KeyPair.
+ *@return the DSA private key.
+ */
+ public static DSAPrivateKey getDSAPrivate(KeyPair kp) {
+ return (DSAPrivateKey)kp.getPrivate();
+ }
+
+ /** Get the public key from the DSA key pair.
+ *
+ *@param kp The DSA KeyPair.
+ *@return the DSA public key.
+ */
+ public static DSAPublicKey getDSAPublic(KeyPair kp) {
+ return (DSAPublicKey)kp.getPublic();
+ }
+
+ /** Makes a {@link DSAPublicKey} from its {@code p}, {@code q},
+ * {@code g} and {@code y} parameters.
+ *
+ *@return the DSAPublicKey, or {@code null} in case of an error.
+ */
+ public static DSAPublicKey getDSAPublicFromParams(BigInteger p,
+ BigInteger q,
+ BigInteger g,
+ BigInteger y) {
+
+ DSAPublicKey pk = null;
+ try {
+ KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+ KeySpec publicKeySpec = new DSAPublicKeySpec(y, p, q, g);
+ pk = (DSAPublicKey)keyFactory.generatePublic(publicKeySpec);
+ }
+ // let's panic if an exception occurs
+ finally {
+ return pk;
+ }
+ }
+
+ /** Generates an RSA key pair.
+ *
+ *@return the RSA key pair or null in case of an error.
+ *@throws java.security.NoSuchAlgorithmException
+ */
+ public static KeyPair generateRSAKeyPair()
+ throws NoSuchAlgorithmException {
+ KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
+ gen.initialize(2048);
+
+ KeyPair pair = gen.generateKeyPair();
+
+ return pair;
+ }
+
+ /** Get the private key from the RSA key pair.
+ *
+ *@param kp The RSA KeyPair.
+ *@return the RSA private key.
+ */
+ public static RSAPrivateKey getRSAPrivate(KeyPair kp) {
+ return (RSAPrivateKey)kp.getPrivate();
+ }
+
+ /** Get the public key from the RSA key pair.
+ *
+ *@param kp The RSA KeyPair.
+ *@return the RSA public key.
+ */
+ public static RSAPublicKey getRSAPublic(KeyPair kp) {
+ return (RSAPublicKey)kp.getPublic();
+ }
+
+}
diff --git a/crypto/src/main/java/org/coniks/crypto/Signing.java b/crypto/src/main/java/org/coniks/crypto/Signing.java
new file mode 100644
index 0000000..fababda
--- /dev/null
+++ b/crypto/src/main/java/org/coniks/crypto/Signing.java
@@ -0,0 +1,158 @@
+/*
+ Copyright (c) 2016, Princeton University.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Princeton University nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.coniks.crypto;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+/** Implements all digital signature operations for CONIKS.
+ * Currently supported algorithms: RSA with SHA-256 and DSA.
+ *
+ *@author Marcela S. Melara (melara@cs.princeton.edu)
+ *@author Michael Rochlin
+ */
+public class Signing {
+
+ /** The size of a 2048-bit RSA signature in bytes.
+ */
+ public static final int SIG_SIZE_BYTES = 256;
+
+ /** Generate the RSA digital signature of {@code msg} using {@code key}.
+ *
+ *@param msg The message to be signed.
+ *@param key The {@link java.security.interfaces.RSAPrivateKey} to use
+ * for signing.
+ *@return The {@code byte[]} containing the digital signature
+ * of the {@code msg}, or null in case of an error.
+ *@throws java.security.NoSuchAlgorithmException
+ */
+ public static byte[] rsaSign(RSAPrivateKey key, byte[] msg)
+ throws NoSuchAlgorithmException {
+
+ byte[] sig = null;
+ try {
+ Signature signer = Signature.getInstance("SHA256withRSA");
+ signer.initSign(key, new SecureRandom());
+ signer.update(msg);
+
+ sig = signer.sign();
+ }
+ // let's panic if an exception occurs
+ finally {
+ return sig;
+ }
+ }
+
+ /** Verify the RSA signature {@code sig} of {@code msg} using {@code pk}.
+ *
+ *@return {@code true} if the signature on the message is valid, {@code false}
+ * otherwise.
+ *@throws {@link java.security.NoSuchAlgorithmException NoSuchAlgorithmException}
+ */
+ public static boolean rsaVerify(RSAPublicKey pk, byte[] msg, byte[] sig)
+ throws NoSuchAlgorithmException {
+
+ boolean res = false;
+ try {
+ Signature verifier = Signature.getInstance("SHA256withRSA");
+ verifier.initVerify(pk);
+ verifier.update(msg);
+
+ res = verifier.verify(sig);
+ }
+ // let's panic if an exception occurs
+ finally {
+ return res;
+ }
+ }
+
+ /** Generate the DSA digital signature of {@code msg} using {@code key}.
+ *
+ *@param msg The message to be signed.
+ *@param key The {@link java.security.interfaces.DSAPrivateKey} to use
+ * for signing.
+ *@return The {@code byte[]} containing the digital signature
+ * of the {@code msg}, or null in case of an error.
+ *@throws
+ *{@link java.security.NoSuchAlgorithmException NoSuchAlgorithmException}
+ */
+ public static byte[] dsaSign(DSAPrivateKey key, byte[] msg)
+ throws NoSuchAlgorithmException {
+
+ byte[] sig = null;
+ try {
+ Signature sigProcess = Signature.getInstance("DSA");
+ sigProcess.initSign(key);
+ sigProcess.update(msg);
+ sig = sigProcess.sign();
+ }
+ // let's panic if an exception occurs
+ finally {
+ return sig;
+ }
+ }
+
+ /** Verify the DSA signature {@code sig} of {@code msg} using {@code pk}.
+ *
+ *@return {@code true} if the signature on the message is valid,
+ * {@code false}
+ * otherwise.
+ *@throws
+ *{@link java.security.NoSuchAlgorithmException NoSuchAlgorithmException}
+ */
+ public static boolean dsaVerify(DSAPublicKey pk, byte[] msg, byte[] sig)
+ throws NoSuchAlgorithmException {
+
+ boolean res = false;
+ try {
+ Signature verifyalg = Signature.getInstance("DSA");
+ verifyalg.initVerify(pk);
+ verifyalg.update(msg);
+
+ res = verifyalg.verify(sig);
+ }
+ // let's panic if an exception occurs
+ finally {
+ return res;
+ }
+ }
+
+}
diff --git a/crypto/src/main/java/org/coniks/crypto/Util.java b/crypto/src/main/java/org/coniks/crypto/Util.java
new file mode 100644
index 0000000..9e77c9e
--- /dev/null
+++ b/crypto/src/main/java/org/coniks/crypto/Util.java
@@ -0,0 +1,80 @@
+/*
+ Copyright (c) 2016, Princeton University.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Princeton University nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.coniks.crypto;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/** Implements all cryptographic utility functions for CONIKS.
+ * Currently supported hash algorithms: SHA-256.
+ *
+ *@author Marcela S. Melara (melara@cs.princeton.edu)
+ *@author Michael Rochlin
+ */
+public class Util {
+
+ /** The size of a SHA-256 hash in bits.
+ */
+ public static final int HASH_SIZE_BITS = 256;
+
+ /** The size of a SHA-256 hash in bytes.
+ */
+ public static final int HASH_SIZE_BYTES = HASH_SIZE_BITS/8;
+
+ /** The supported hashing scheme.
+ */
+ public static final String HASH_ID = "SHA-256";
+
+ /** Generates the cryptographic hash of {@code input}.
+ * Current hashing algorithm: SHA-256.
+ *
+ *@return The hash as a {@code byte[]} or null in case of an error.
+ */
+ public static byte[] digest(byte[] input)
+ throws NoSuchAlgorithmException {
+
+ byte [] digest = null;
+ try{
+ MessageDigest md = MessageDigest.getInstance(HASH_ID);
+ digest = md.digest(input);
+ return digest;
+
+ }
+ // let's panic if an exception occurs
+ finally {
+ return digest;
+ }
+ }
+
+}
diff --git a/crypto/src/test/java/org/coniks/crypto/KeysTest.java b/crypto/src/test/java/org/coniks/crypto/KeysTest.java
new file mode 100644
index 0000000..ff44c88
--- /dev/null
+++ b/crypto/src/test/java/org/coniks/crypto/KeysTest.java
@@ -0,0 +1,120 @@
+/*
+ Copyright (c) 2016, Princeton University.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Princeton University nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.coniks.crypto;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import static org.hamcrest.core.StringContains.containsString;
+
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * Unit tests for Keys.
+ */
+public class KeysTest
+{
+
+ @Test
+ public void testGetDSAPrivateFail()
+ throws NoSuchAlgorithmException {
+
+ KeyPair pair = Keys.generateRSAKeyPair();
+
+ try {
+ DSAPrivateKey pk = Keys.getDSAPrivate(pair);
+ fail("Expected a ClassCastException to be thrown");
+ }
+ catch(ClassCastException e) {
+ assertThat(e.getMessage(),
+ containsString("sun.security.rsa.RSAPrivateCrtKeyImpl cannot be cast to java.security.interfaces.DSAPrivateKey"));
+ }
+ }
+
+ @Test
+ public void testGetDSAPublicFail()
+ throws NoSuchAlgorithmException {
+
+ KeyPair pair = Keys.generateRSAKeyPair();
+
+ try {
+ DSAPublicKey pk = Keys.getDSAPublic(pair);
+ fail("Expected a ClassCastException to be thrown");
+ }
+ catch(ClassCastException e) {
+ assertThat(e.getMessage(),
+ containsString("sun.security.rsa.RSAPublicKeyImpl cannot be cast to java.security.interfaces.DSAPublicKey"));
+ }
+ }
+
+ @Test
+ public void testGetRSAPrivateFail()
+ throws NoSuchAlgorithmException {
+
+ KeyPair pair = Keys.generateDSAKeyPair();
+
+ try {
+ RSAPrivateKey pk = Keys.getRSAPrivate(pair);
+ fail("Expected a ClassCastException to be thrown");
+ }
+ catch(ClassCastException e) {
+ assertThat(e.getMessage(),
+ containsString("sun.security.provider.DSAPrivateKey cannot be cast to java.security.interfaces.RSAPrivateKey"));
+ }
+ }
+
+ @Test
+ public void testGetRSAPublicFail()
+ throws NoSuchAlgorithmException {
+
+ KeyPair pair = Keys.generateDSAKeyPair();
+
+ try {
+ RSAPublicKey pk = Keys.getRSAPublic(pair);
+ fail("Expected a ClassCastException to be thrown");
+ }
+ catch(ClassCastException e) {
+ assertThat(e.getMessage(),
+ containsString("sun.security.provider.DSAPublicKeyImpl cannot be cast to java.security.interfaces.RSAPublicKey"));
+ }
+ }
+
+}
diff --git a/crypto/src/test/java/org/coniks/crypto/SigningTest.java b/crypto/src/test/java/org/coniks/crypto/SigningTest.java
new file mode 100644
index 0000000..fcdc5cc
--- /dev/null
+++ b/crypto/src/test/java/org/coniks/crypto/SigningTest.java
@@ -0,0 +1,80 @@
+/*
+ Copyright (c) 2016, Princeton University.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Princeton University nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.coniks.crypto;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * Unit tests for Signing.
+ */
+public class SigningTest
+{
+
+ @Test
+ public void testRsaSignVerify()
+ throws NoSuchAlgorithmException {
+
+ KeyPair pair = Keys.generateRSAKeyPair();
+
+ byte[] msg = "message".getBytes();
+
+ byte[] sig = Signing.rsaSign(Keys.getRSAPrivate(pair), msg);
+
+ assertTrue("Verification of RSA signature failed",
+ Signing.rsaVerify(Keys.getRSAPublic(pair), msg, sig));
+ }
+
+ @Test
+ public void testDsaSignVerify()
+ throws NoSuchAlgorithmException {
+
+ KeyPair pair = Keys.generateDSAKeyPair();
+
+ byte[] msg = "message".getBytes();
+
+ byte[] sig = Signing.dsaSign(Keys.getDSAPrivate(pair), msg);
+
+ assertTrue("Verification of DSA signature failed",
+ Signing.dsaVerify(Keys.getDSAPublic(pair), msg, sig));
+ }
+}
diff --git a/crypto/src/test/java/org/coniks/crypto/UtilTest.java b/crypto/src/test/java/org/coniks/crypto/UtilTest.java
new file mode 100644
index 0000000..961aaaa
--- /dev/null
+++ b/crypto/src/test/java/org/coniks/crypto/UtilTest.java
@@ -0,0 +1,70 @@
+/*
+ Copyright (c) 2016, Princeton University.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Princeton University nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.coniks.crypto;
+
+import org.junit.Test;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import static org.hamcrest.core.StringContains.containsString;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+/**
+ * Unit tests for Util.
+ */
+public class UtilTest
+{
+
+ @Test
+ public void testDigest()
+ throws NoSuchAlgorithmException {
+
+ byte[] msg = "message".getBytes();
+
+ byte[] hash = Util.digest(msg);
+
+ if(hash.length != Util.HASH_SIZE_BYTES) {
+ fail("Computation of hash failed - wrong length.");
+ }
+
+ assertNotNull("Computation of hash failed - null", hash);
+
+ assertFalse("Computation of hash failed - hash is all zeros",
+ Arrays.equals(hash, new byte[Util.HASH_SIZE_BYTES]));
+
+ }
+}
diff --git a/pom.xml b/pom.xml
index 0fa462c..d64e157 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,12 +1,32 @@
-
+
+4.0.0
+
org.coniksconiks-java
+ 1.3-SNAPSHOTpom
- 1.2-SNAPSHOT
- CONIKS Java lib and reference
+
+ CONIKS [Parent]http://coniks.org
+ CONIKS is a key management system that provides transparency for end-user public keys.
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+
+
+ crypto
+ coniks_common
+ coniks_server
+ coniks_test_client
+
@@ -18,12 +38,57 @@
$COVERALLS_TOKEN
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.5.1
+
+
+ 1.7
+ true
+ true
+
+ -Werror
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.19.1
+
-
- coniks_common
- coniks_server
- coniks_test_client
-
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-report-plugin
+ 2.19.1
+
+
+
+ unit-tests
+
+ report
+
+
+
+
+
+ unit-tests-aggregate
+ false
+
+ report
+
+
+ true
+
+
+
+
+
+
+
diff --git a/protos/README.md b/protos/README.md
index df70c29..0fe2e44 100644
--- a/protos/README.md
+++ b/protos/README.md
@@ -28,7 +28,7 @@ protoc --proto_path=. --java_out=../coniks_common/src .proto
This command will automatically place the generated Java code in the appropriate package hierarchy in coniks_common/src.
## Disclaimer
-Please keep in mind that this CONIKS reference implementation is under active development. The repository may contain experimental features that aren't fully tested. We recommend using a [tagged release](https://github.com/coniks-sys/coniks-java/releases).
+Please keep in mind that this CONIKS Java implementation is under active development. The repository may contain experimental features that aren't fully tested. We recommend using a [tagged release](https://github.com/coniks-sys/coniks-java/releases).
##Documentation
[Read the official Google Protobuf documentation](https://developers.google.com/protocol-buffers/)