diff --git a/.gitignore b/.gitignore
index 7307e2f78..b7e3f2847 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-/build
+build
/obj
*.iml
.gradle
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644
index 000000000..482532e39
--- /dev/null
+++ b/android/build.gradle
@@ -0,0 +1,96 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.0.0'
+ }
+}
+
+apply plugin: 'com.android.library'
+apply plugin: 'maven'
+apply plugin: 'signing'
+
+archivesBaseName = "axolotl-android"
+version = version_number
+group = group_info
+
+android {
+ compileSdkVersion 21
+ buildToolsVersion "21.1.2"
+
+ sourceSets {
+ androidTest {
+ java.srcDirs = ['src/androidTest/java', project(':tests').file('src/main/java')]
+ }
+ }
+
+ libraryVariants.all { variant ->
+ variant.outputs.each { output ->
+ def outputFile = output.outputFile
+ if (outputFile != null && outputFile.name.endsWith('.aar')) {
+ def fileName = "${archivesBaseName}-${version}.aar"
+ output.outputFile = new File(outputFile.parent, fileName)
+ }
+ }
+ }
+}
+
+repositories {
+ mavenCentral()
+ mavenLocal()
+}
+
+dependencies {
+ compile "org.whispersystems:curve25519-android:${curve25519_version}"
+ compile (project(':java')) {
+ exclude group: 'org.whispersystems', module: 'curve25519-java'
+ }
+}
+
+signing {
+ required { has("release") && gradle.taskGraph.hasTask("uploadArchives") }
+ sign configurations.archives
+}
+
+uploadArchives {
+ configuration = configurations.archives
+ repositories.mavenDeployer {
+ beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
+
+ repository(url: sonatypeRepo) {
+ authentication(userName: whisperSonatypeUsername, password: whisperSonatypePassword)
+ }
+
+ pom.project {
+ name 'axolotl-android'
+ packaging 'aar'
+ description 'Axolotl library for Android'
+ url 'https://github.com/WhisperSystems/libaxolotl-android'
+
+ scm {
+ url 'scm:git@github.com:WhisperSystems/libaxolotl-android.git'
+ connection 'scm:git@github.com:WhisperSystems/libaxolotl-android.git'
+ developerConnection 'scm:git@github.com:WhisperSystems/libaxolotl-android.git'
+ }
+
+ developers {
+ developer {
+ name 'Moxie Marlinspike'
+ }
+ }
+ }
+ }
+}
+
+task installArchives(type: Upload) {
+ description "Installs the artifacts to the local Maven repository."
+ configuration = configurations['archives']
+ repositories {
+ mavenDeployer {
+ repository url: "file://${System.properties['user.home']}/.m2/repository"
+ }
+ }
+}
+
diff --git a/android/src/androidTest/java/org/whispersystems/libaxolotl/CurveTest.java b/android/src/androidTest/java/org/whispersystems/libaxolotl/CurveTest.java
new file mode 100644
index 000000000..bb539d490
--- /dev/null
+++ b/android/src/androidTest/java/org/whispersystems/libaxolotl/CurveTest.java
@@ -0,0 +1,26 @@
+package org.whispersystems.libaxolotl;
+
+import junit.framework.TestCase;
+
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+
+public class CurveTest extends TestCase {
+
+ public void testPureJava() {
+ assertTrue(Curve.isNative());
+ }
+
+ public void testSignatureOverflow() throws InvalidKeyException {
+ ECKeyPair keys = Curve.generateKeyPair();
+ byte[] message = new byte[4096];
+
+ try {
+ byte[] signature = Curve.calculateSignature(keys.getPrivateKey(), message);
+ throw new InvalidKeyException("Should have asserted!");
+ } catch (AssertionError e) {
+ // Success!
+ }
+ }
+
+}
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..85f0fe6b2
--- /dev/null
+++ b/android/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+
+
diff --git a/android/src/main/java/org/whispersystems/libaxolotl/util/AndroidAxolotlLogger.java b/android/src/main/java/org/whispersystems/libaxolotl/util/AndroidAxolotlLogger.java
new file mode 100644
index 000000000..302c08a44
--- /dev/null
+++ b/android/src/main/java/org/whispersystems/libaxolotl/util/AndroidAxolotlLogger.java
@@ -0,0 +1,24 @@
+package org.whispersystems.libaxolotl.util;
+
+import android.util.Log;
+import android.util.SparseIntArray;
+
+import org.whispersystems.libaxolotl.logging.AxolotlLogger;
+
+public class AndroidAxolotlLogger implements AxolotlLogger {
+
+ private static final SparseIntArray PRIORITY_MAP = new SparseIntArray(5) {{
+ put(AxolotlLogger.INFO, Log.INFO);
+ put(AxolotlLogger.ASSERT, Log.ASSERT);
+ put(AxolotlLogger.DEBUG, Log.DEBUG);
+ put(AxolotlLogger.VERBOSE, Log.VERBOSE);
+ put(AxolotlLogger.WARN, Log.WARN);
+
+ }};
+
+ @Override
+ public void log(int priority, String tag, String message) {
+ int androidPriority = PRIORITY_MAP.get(priority, Log.WARN);
+ Log.println(androidPriority, tag, message);
+ }
+}
diff --git a/build.gradle b/build.gradle
index bb67b6bb3..0aa148e3e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,110 +1,19 @@
buildscript {
- repositories {
- mavenCentral()
- }
-
dependencies {
- classpath 'com.android.tools.build:gradle:1.0.0'
classpath files('libs/gradle-witness.jar')
}
}
-apply plugin: 'com.android.library'
-apply plugin: 'witness'
-apply plugin: 'maven'
-apply plugin: 'signing'
+subprojects {
+ apply plugin: 'witness'
-archivesBaseName = "axolotl-android"
-version = "1.0.0"
-group = "org.whispersystems"
+ ext.version_number = "1.0.1"
+ ext.group_info = "org.whispersystems"
+ ext.curve25519_version = "0.1.3"
-repositories {
- mavenCentral()
-}
-
-dependencies {
- compile 'com.google.protobuf:protobuf-java:2.5.0'
-}
-
-dependencyVerification {
- verify = [
- 'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74',
- ]
-}
-
-android {
- compileSdkVersion 21
- buildToolsVersion '21.1.1'
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_7
- targetCompatibility JavaVersion.VERSION_1_7
- }
-
- android {
- sourceSets {
- main {
- jniLibs.srcDirs = ['libs']
- }
- }
- }
-
- libraryVariants.all { variant ->
- variant.outputs.each { output ->
- def outputFile = output.outputFile
- if (outputFile != null && outputFile.name.endsWith('.aar')) {
- def fileName = "${archivesBaseName}-${version}.aar"
- output.outputFile = new File(outputFile.parent, fileName)
- }
- }
- }
-}
-
-signing {
- required { has("release") && gradle.taskGraph.hasTask("uploadArchives") }
- sign configurations.archives
-}
-
-uploadArchives {
- configuration = configurations.archives
- repositories.mavenDeployer {
- beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
-
- repository(url: sonatypeRepo) {
- authentication(userName: whisperSonatypeUsername, password: whisperSonatypePassword)
- }
-
- pom.project {
- name 'axolotl-android'
- packaging 'aar'
- description 'Axolotl encryption library for Android'
- url 'https://github.com/WhisperSystems/libaxolotl-android'
-
- scm {
- url 'scm:git@github.com:WhisperSystems/libaxolotl-android.git'
- connection 'scm:git@github.com:WhisperSystems/libaxolotl-android.git'
- developerConnection 'scm:git@github.com:WhisperSystems/libaxolotl-android.git'
- }
-
- licenses {
- license {
- name 'GPLv3'
- url 'https://www.gnu.org/licenses/gpl-3.0.txt'
- distribution 'repo'
- }
- }
-
- developers {
- developer {
- name 'Moxie Marlinspike'
- }
- }
- }
- }
-}
-
-tasks.whenTaskAdded { task ->
- if (task.name.equals("lint")) {
- task.enabled = false
+ dependencyVerification {
+ verify = [
+ 'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74',
+ ]
}
}
diff --git a/java/build.gradle b/java/build.gradle
new file mode 100644
index 000000000..11834e6b7
--- /dev/null
+++ b/java/build.gradle
@@ -0,0 +1,83 @@
+apply plugin: 'java'
+apply plugin: 'maven'
+apply plugin: 'signing'
+
+sourceCompatibility = 1.7
+archivesBaseName = "axolotl-java"
+version = version_number
+group = group_info
+
+repositories {
+ mavenCentral()
+ mavenLocal()
+}
+
+sourceSets {
+ test {
+ java {
+ srcDirs = ['src/test/java/', project(':tests').file('src/main/java')]
+ }
+ }
+}
+
+dependencies {
+ compile "org.whispersystems:curve25519-java:${curve25519_version}"
+ compile 'com.google.protobuf:protobuf-java:2.5.0'
+
+ testCompile ('junit:junit:3.8.2')
+}
+
+
+test {
+ testLogging {
+ events 'passed'
+ showStandardStreams = true
+ }
+
+ include 'org/whispersystems/**'
+}
+
+signing {
+ required { has("release") && gradle.taskGraph.hasTask("uploadArchives") }
+ sign configurations.archives
+}
+
+uploadArchives {
+ configuration = configurations.archives
+ repositories.mavenDeployer {
+ beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
+
+ repository(url: sonatypeRepo) {
+ authentication(userName: whisperSonatypeUsername, password: whisperSonatypePassword)
+ }
+
+ pom.project {
+ name 'axolotl-java'
+ packaging 'jar'
+ description 'Axolotl library for Java'
+ url 'https://github.com/WhisperSystems/libaxolotl-android'
+
+ scm {
+ url 'scm:git@github.com:WhisperSystems/libaxolotl-android.git'
+ connection 'scm:git@github.com:WhisperSystems/libaxolotl-android.git'
+ developerConnection 'scm:git@github.com:WhisperSystems/libaxolotl-android.git'
+ }
+
+ developers {
+ developer {
+ name 'Moxie Marlinspike'
+ }
+ }
+ }
+ }
+}
+
+task installArchives(type: Upload) {
+ description "Installs the artifacts to the local Maven repository."
+ configuration = configurations['archives']
+ repositories {
+ mavenDeployer {
+ repository url: "file://${System.properties['user.home']}/.m2/repository"
+ }
+ }
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/DuplicateMessageException.java b/java/src/main/java/org/whispersystems/libaxolotl/DuplicateMessageException.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/DuplicateMessageException.java
rename to java/src/main/java/org/whispersystems/libaxolotl/DuplicateMessageException.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/IdentityKey.java b/java/src/main/java/org/whispersystems/libaxolotl/IdentityKey.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/IdentityKey.java
rename to java/src/main/java/org/whispersystems/libaxolotl/IdentityKey.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/IdentityKeyPair.java b/java/src/main/java/org/whispersystems/libaxolotl/IdentityKeyPair.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/IdentityKeyPair.java
rename to java/src/main/java/org/whispersystems/libaxolotl/IdentityKeyPair.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/InvalidKeyException.java b/java/src/main/java/org/whispersystems/libaxolotl/InvalidKeyException.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/InvalidKeyException.java
rename to java/src/main/java/org/whispersystems/libaxolotl/InvalidKeyException.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/InvalidKeyIdException.java b/java/src/main/java/org/whispersystems/libaxolotl/InvalidKeyIdException.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/InvalidKeyIdException.java
rename to java/src/main/java/org/whispersystems/libaxolotl/InvalidKeyIdException.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/InvalidMacException.java b/java/src/main/java/org/whispersystems/libaxolotl/InvalidMacException.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/InvalidMacException.java
rename to java/src/main/java/org/whispersystems/libaxolotl/InvalidMacException.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/InvalidMessageException.java b/java/src/main/java/org/whispersystems/libaxolotl/InvalidMessageException.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/InvalidMessageException.java
rename to java/src/main/java/org/whispersystems/libaxolotl/InvalidMessageException.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/InvalidVersionException.java b/java/src/main/java/org/whispersystems/libaxolotl/InvalidVersionException.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/InvalidVersionException.java
rename to java/src/main/java/org/whispersystems/libaxolotl/InvalidVersionException.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/LegacyMessageException.java b/java/src/main/java/org/whispersystems/libaxolotl/LegacyMessageException.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/LegacyMessageException.java
rename to java/src/main/java/org/whispersystems/libaxolotl/LegacyMessageException.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/NoSessionException.java b/java/src/main/java/org/whispersystems/libaxolotl/NoSessionException.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/NoSessionException.java
rename to java/src/main/java/org/whispersystems/libaxolotl/NoSessionException.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java b/java/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java
similarity index 99%
rename from src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java
rename to java/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java
index 2d1c89692..736d9ab1f 100644
--- a/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java
+++ b/java/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java
@@ -1,10 +1,10 @@
package org.whispersystems.libaxolotl;
-import android.util.Log;
import org.whispersystems.libaxolotl.ecc.Curve;
import org.whispersystems.libaxolotl.ecc.ECKeyPair;
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
+import org.whispersystems.libaxolotl.logging.Log;
import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
import org.whispersystems.libaxolotl.protocol.KeyExchangeMessage;
import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
diff --git a/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java b/java/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/SessionCipher.java
rename to java/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/StaleKeyExchangeException.java b/java/src/main/java/org/whispersystems/libaxolotl/StaleKeyExchangeException.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/StaleKeyExchangeException.java
rename to java/src/main/java/org/whispersystems/libaxolotl/StaleKeyExchangeException.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/UntrustedIdentityException.java b/java/src/main/java/org/whispersystems/libaxolotl/UntrustedIdentityException.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/UntrustedIdentityException.java
rename to java/src/main/java/org/whispersystems/libaxolotl/UntrustedIdentityException.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java b/java/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java
similarity index 59%
rename from src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java
index 66b8cc3ab..5d47e3aa2 100644
--- a/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java
+++ b/java/src/main/java/org/whispersystems/libaxolotl/ecc/Curve.java
@@ -16,25 +16,41 @@
*/
package org.whispersystems.libaxolotl.ecc;
+import org.whispersystems.curve25519.Curve25519KeyPair;
import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.curve25519.Curve25519;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
public class Curve {
public static final int DJB_TYPE = 0x05;
+ public static boolean isNative() {
+ return Curve25519.isNative();
+ }
+
public static ECKeyPair generateKeyPair() {
- return Curve25519.generateKeyPair();
+ SecureRandom secureRandom = getSecureRandom();
+ Curve25519KeyPair keyPair = Curve25519.generateKeyPair(secureRandom);
+
+ return new ECKeyPair(new DjbECPublicKey(keyPair.getPublicKey()),
+ new DjbECPrivateKey(keyPair.getPrivateKey()));
}
public static ECPublicKey decodePoint(byte[] bytes, int offset)
throws InvalidKeyException
{
- int type = bytes[offset];
+ int type = bytes[offset] & 0xFF;
- if (type == DJB_TYPE) {
- return Curve25519.decodePoint(bytes, offset);
- } else {
- throw new InvalidKeyException("Unknown key type: " + type);
+ switch (type) {
+ case Curve.DJB_TYPE:
+ byte[] keyBytes = new byte[32];
+ System.arraycopy(bytes, offset+1, keyBytes, 0, keyBytes.length);
+ return new DjbECPublicKey(keyBytes);
+ default:
+ throw new InvalidKeyException("Bad key type: " + type);
}
}
@@ -50,7 +66,8 @@ public class Curve {
}
if (publicKey.getType() == DJB_TYPE) {
- return Curve25519.calculateAgreement(publicKey, privateKey);
+ return Curve25519.calculateAgreement(((DjbECPublicKey)publicKey).getPublicKey(),
+ ((DjbECPrivateKey)privateKey).getPrivateKey());
} else {
throw new InvalidKeyException("Unknown type: " + publicKey.getType());
}
@@ -60,7 +77,7 @@ public class Curve {
throws InvalidKeyException
{
if (signingKey.getType() == DJB_TYPE) {
- return Curve25519.verifySignature(signingKey, message, signature);
+ return Curve25519.verifySignature(((DjbECPublicKey)signingKey).getPublicKey(), message, signature);
} else {
throw new InvalidKeyException("Unknown type: " + signingKey.getType());
}
@@ -70,9 +87,17 @@ public class Curve {
throws InvalidKeyException
{
if (signingKey.getType() == DJB_TYPE) {
- return Curve25519.calculateSignature(signingKey, message);
+ return Curve25519.calculateSignature(getSecureRandom(), ((DjbECPrivateKey)signingKey).getPrivateKey(), message);
} else {
throw new InvalidKeyException("Unknown type: " + signingKey.getType());
}
}
+
+ private static SecureRandom getSecureRandom() {
+ try {
+ return SecureRandom.getInstance("SHA1PRNG");
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+ }
}
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPrivateKey.java b/java/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPrivateKey.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPrivateKey.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPrivateKey.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPublicKey.java b/java/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPublicKey.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPublicKey.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ecc/DjbECPublicKey.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/ECKeyPair.java b/java/src/main/java/org/whispersystems/libaxolotl/ecc/ECKeyPair.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/ecc/ECKeyPair.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ecc/ECKeyPair.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/ECPrivateKey.java b/java/src/main/java/org/whispersystems/libaxolotl/ecc/ECPrivateKey.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/ecc/ECPrivateKey.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ecc/ECPrivateKey.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/ECPublicKey.java b/java/src/main/java/org/whispersystems/libaxolotl/ecc/ECPublicKey.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/ecc/ECPublicKey.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ecc/ECPublicKey.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java b/java/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java
rename to java/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/GroupSessionBuilder.java b/java/src/main/java/org/whispersystems/libaxolotl/groups/GroupSessionBuilder.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/groups/GroupSessionBuilder.java
rename to java/src/main/java/org/whispersystems/libaxolotl/groups/GroupSessionBuilder.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderChainKey.java b/java/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderChainKey.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderChainKey.java
rename to java/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderChainKey.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderMessageKey.java b/java/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderMessageKey.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderMessageKey.java
rename to java/src/main/java/org/whispersystems/libaxolotl/groups/ratchet/SenderMessageKey.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java b/java/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java
rename to java/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java b/java/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java
rename to java/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java b/java/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java
rename to java/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/kdf/DerivedMessageSecrets.java b/java/src/main/java/org/whispersystems/libaxolotl/kdf/DerivedMessageSecrets.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/kdf/DerivedMessageSecrets.java
rename to java/src/main/java/org/whispersystems/libaxolotl/kdf/DerivedMessageSecrets.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/kdf/DerivedRootSecrets.java b/java/src/main/java/org/whispersystems/libaxolotl/kdf/DerivedRootSecrets.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/kdf/DerivedRootSecrets.java
rename to java/src/main/java/org/whispersystems/libaxolotl/kdf/DerivedRootSecrets.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/kdf/HKDF.java b/java/src/main/java/org/whispersystems/libaxolotl/kdf/HKDF.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/kdf/HKDF.java
rename to java/src/main/java/org/whispersystems/libaxolotl/kdf/HKDF.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv2.java b/java/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv2.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv2.java
rename to java/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv2.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv3.java b/java/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv3.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv3.java
rename to java/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFv3.java
diff --git a/java/src/main/java/org/whispersystems/libaxolotl/logging/AxolotlLogger.java b/java/src/main/java/org/whispersystems/libaxolotl/logging/AxolotlLogger.java
new file mode 100644
index 000000000..e8baf5e43
--- /dev/null
+++ b/java/src/main/java/org/whispersystems/libaxolotl/logging/AxolotlLogger.java
@@ -0,0 +1,13 @@
+package org.whispersystems.libaxolotl.logging;
+
+public interface AxolotlLogger {
+
+ public static final int VERBOSE = 2;
+ public static final int DEBUG = 3;
+ public static final int INFO = 4;
+ public static final int WARN = 5;
+ public static final int ERROR = 6;
+ public static final int ASSERT = 7;
+
+ public void log(int priority, String tag, String message);
+}
diff --git a/java/src/main/java/org/whispersystems/libaxolotl/logging/AxolotlLoggerProvider.java b/java/src/main/java/org/whispersystems/libaxolotl/logging/AxolotlLoggerProvider.java
new file mode 100644
index 000000000..e385aa09a
--- /dev/null
+++ b/java/src/main/java/org/whispersystems/libaxolotl/logging/AxolotlLoggerProvider.java
@@ -0,0 +1,14 @@
+package org.whispersystems.libaxolotl.logging;
+
+public class AxolotlLoggerProvider {
+
+ private static AxolotlLogger provider;
+
+ public static AxolotlLogger getProvider() {
+ return provider;
+ }
+
+ public static void setProvider(AxolotlLogger provider) {
+ AxolotlLoggerProvider.provider = provider;
+ }
+}
diff --git a/java/src/main/java/org/whispersystems/libaxolotl/logging/Log.java b/java/src/main/java/org/whispersystems/libaxolotl/logging/Log.java
new file mode 100644
index 000000000..22db9baf8
--- /dev/null
+++ b/java/src/main/java/org/whispersystems/libaxolotl/logging/Log.java
@@ -0,0 +1,86 @@
+package org.whispersystems.libaxolotl.logging;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.UnknownHostException;
+
+public class Log {
+
+ private Log() {}
+
+ public static void v(String tag, String msg) {
+ log(AxolotlLogger.VERBOSE, tag, msg);
+ }
+
+ public static void v(String tag, String msg, Throwable tr) {
+ log(AxolotlLogger.VERBOSE, tag, msg + '\n' + getStackTraceString(tr));
+ }
+
+ public static void d(String tag, String msg) {
+ log(AxolotlLogger.DEBUG, tag, msg);
+ }
+
+ public static void d(String tag, String msg, Throwable tr) {
+ log(AxolotlLogger.DEBUG, tag, msg + '\n' + getStackTraceString(tr));
+ }
+
+ public static void i(String tag, String msg) {
+ log(AxolotlLogger.INFO, tag, msg);
+ }
+
+ public static void i(String tag, String msg, Throwable tr) {
+ log(AxolotlLogger.INFO, tag, msg + '\n' + getStackTraceString(tr));
+ }
+
+ public static void w(String tag, String msg) {
+ log(AxolotlLogger.WARN, tag, msg);
+ }
+
+ public static void w(String tag, String msg, Throwable tr) {
+ log(AxolotlLogger.WARN, tag, msg + '\n' + getStackTraceString(tr));
+ }
+
+ public static void w(String tag, Throwable tr) {
+ log(AxolotlLogger.WARN, tag, getStackTraceString(tr));
+ }
+
+ public static void e(String tag, String msg) {
+ log(AxolotlLogger.ERROR, tag, msg);
+ }
+
+ public static void e(String tag, String msg, Throwable tr) {
+ log(AxolotlLogger.ERROR, tag, msg + '\n' + getStackTraceString(tr));
+ }
+
+ private static String getStackTraceString(Throwable tr) {
+ if (tr == null) {
+ return "";
+ }
+
+ // This is to reduce the amount of log spew that apps do in the non-error
+ // condition of the network being unavailable.
+ Throwable t = tr;
+ while (t != null) {
+ if (t instanceof UnknownHostException) {
+ return "";
+ }
+ t = t.getCause();
+ }
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ tr.printStackTrace(pw);
+ pw.flush();
+ return sw.toString();
+ }
+
+ private static void log(int priority, String tag, String msg) {
+ AxolotlLogger logger = AxolotlLoggerProvider.getProvider();
+
+ if (logger != null) {
+ logger.log(priority, tag, msg);
+ }
+ }
+
+
+}
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/CiphertextMessage.java b/java/src/main/java/org/whispersystems/libaxolotl/protocol/CiphertextMessage.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/protocol/CiphertextMessage.java
rename to java/src/main/java/org/whispersystems/libaxolotl/protocol/CiphertextMessage.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/KeyExchangeMessage.java b/java/src/main/java/org/whispersystems/libaxolotl/protocol/KeyExchangeMessage.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/protocol/KeyExchangeMessage.java
rename to java/src/main/java/org/whispersystems/libaxolotl/protocol/KeyExchangeMessage.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/PreKeyWhisperMessage.java b/java/src/main/java/org/whispersystems/libaxolotl/protocol/PreKeyWhisperMessage.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/protocol/PreKeyWhisperMessage.java
rename to java/src/main/java/org/whispersystems/libaxolotl/protocol/PreKeyWhisperMessage.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyDistributionMessage.java b/java/src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyDistributionMessage.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyDistributionMessage.java
rename to java/src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyDistributionMessage.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyMessage.java b/java/src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyMessage.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyMessage.java
rename to java/src/main/java/org/whispersystems/libaxolotl/protocol/SenderKeyMessage.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperMessage.java b/java/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperMessage.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/protocol/WhisperMessage.java
rename to java/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperMessage.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperProtos.java b/java/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperProtos.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/protocol/WhisperProtos.java
rename to java/src/main/java/org/whispersystems/libaxolotl/protocol/WhisperProtos.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/AliceAxolotlParameters.java b/java/src/main/java/org/whispersystems/libaxolotl/ratchet/AliceAxolotlParameters.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/ratchet/AliceAxolotlParameters.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ratchet/AliceAxolotlParameters.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/BobAxolotlParameters.java b/java/src/main/java/org/whispersystems/libaxolotl/ratchet/BobAxolotlParameters.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/ratchet/BobAxolotlParameters.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ratchet/BobAxolotlParameters.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKey.java b/java/src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKey.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKey.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKey.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/MessageKeys.java b/java/src/main/java/org/whispersystems/libaxolotl/ratchet/MessageKeys.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/ratchet/MessageKeys.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ratchet/MessageKeys.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSession.java b/java/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSession.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSession.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSession.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/RootKey.java b/java/src/main/java/org/whispersystems/libaxolotl/ratchet/RootKey.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/ratchet/RootKey.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ratchet/RootKey.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/ratchet/SymmetricAxolotlParameters.java b/java/src/main/java/org/whispersystems/libaxolotl/ratchet/SymmetricAxolotlParameters.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/ratchet/SymmetricAxolotlParameters.java
rename to java/src/main/java/org/whispersystems/libaxolotl/ratchet/SymmetricAxolotlParameters.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/AxolotlStore.java b/java/src/main/java/org/whispersystems/libaxolotl/state/AxolotlStore.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/state/AxolotlStore.java
rename to java/src/main/java/org/whispersystems/libaxolotl/state/AxolotlStore.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/IdentityKeyStore.java b/java/src/main/java/org/whispersystems/libaxolotl/state/IdentityKeyStore.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/state/IdentityKeyStore.java
rename to java/src/main/java/org/whispersystems/libaxolotl/state/IdentityKeyStore.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/PreKeyBundle.java b/java/src/main/java/org/whispersystems/libaxolotl/state/PreKeyBundle.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/state/PreKeyBundle.java
rename to java/src/main/java/org/whispersystems/libaxolotl/state/PreKeyBundle.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/PreKeyRecord.java b/java/src/main/java/org/whispersystems/libaxolotl/state/PreKeyRecord.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/state/PreKeyRecord.java
rename to java/src/main/java/org/whispersystems/libaxolotl/state/PreKeyRecord.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/PreKeyStore.java b/java/src/main/java/org/whispersystems/libaxolotl/state/PreKeyStore.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/state/PreKeyStore.java
rename to java/src/main/java/org/whispersystems/libaxolotl/state/PreKeyStore.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/SessionRecord.java b/java/src/main/java/org/whispersystems/libaxolotl/state/SessionRecord.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/state/SessionRecord.java
rename to java/src/main/java/org/whispersystems/libaxolotl/state/SessionRecord.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java b/java/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java
similarity index 99%
rename from src/main/java/org/whispersystems/libaxolotl/state/SessionState.java
rename to java/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java
index 9b2b1e2ae..e724e7df8 100644
--- a/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java
+++ b/java/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java
@@ -17,7 +17,6 @@
package org.whispersystems.libaxolotl.state;
-import android.util.Log;
import com.google.protobuf.ByteString;
@@ -29,6 +28,7 @@ import org.whispersystems.libaxolotl.ecc.ECKeyPair;
import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
import org.whispersystems.libaxolotl.kdf.HKDF;
+import org.whispersystems.libaxolotl.logging.Log;
import org.whispersystems.libaxolotl.ratchet.ChainKey;
import org.whispersystems.libaxolotl.ratchet.MessageKeys;
import org.whispersystems.libaxolotl.ratchet.RootKey;
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/SessionStore.java b/java/src/main/java/org/whispersystems/libaxolotl/state/SessionStore.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/state/SessionStore.java
rename to java/src/main/java/org/whispersystems/libaxolotl/state/SessionStore.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyRecord.java b/java/src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyRecord.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyRecord.java
rename to java/src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyRecord.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyStore.java b/java/src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyStore.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyStore.java
rename to java/src/main/java/org/whispersystems/libaxolotl/state/SignedPreKeyStore.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/state/StorageProtos.java b/java/src/main/java/org/whispersystems/libaxolotl/state/StorageProtos.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/state/StorageProtos.java
rename to java/src/main/java/org/whispersystems/libaxolotl/state/StorageProtos.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/ByteUtil.java b/java/src/main/java/org/whispersystems/libaxolotl/util/ByteUtil.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/util/ByteUtil.java
rename to java/src/main/java/org/whispersystems/libaxolotl/util/ByteUtil.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/Hex.java b/java/src/main/java/org/whispersystems/libaxolotl/util/Hex.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/util/Hex.java
rename to java/src/main/java/org/whispersystems/libaxolotl/util/Hex.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java b/java/src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java
rename to java/src/main/java/org/whispersystems/libaxolotl/util/KeyHelper.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/Medium.java b/java/src/main/java/org/whispersystems/libaxolotl/util/Medium.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/util/Medium.java
rename to java/src/main/java/org/whispersystems/libaxolotl/util/Medium.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/Pair.java b/java/src/main/java/org/whispersystems/libaxolotl/util/Pair.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/util/Pair.java
rename to java/src/main/java/org/whispersystems/libaxolotl/util/Pair.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/guava/Absent.java b/java/src/main/java/org/whispersystems/libaxolotl/util/guava/Absent.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/util/guava/Absent.java
rename to java/src/main/java/org/whispersystems/libaxolotl/util/guava/Absent.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/guava/Function.java b/java/src/main/java/org/whispersystems/libaxolotl/util/guava/Function.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/util/guava/Function.java
rename to java/src/main/java/org/whispersystems/libaxolotl/util/guava/Function.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/guava/Optional.java b/java/src/main/java/org/whispersystems/libaxolotl/util/guava/Optional.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/util/guava/Optional.java
rename to java/src/main/java/org/whispersystems/libaxolotl/util/guava/Optional.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/guava/Preconditions.java b/java/src/main/java/org/whispersystems/libaxolotl/util/guava/Preconditions.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/util/guava/Preconditions.java
rename to java/src/main/java/org/whispersystems/libaxolotl/util/guava/Preconditions.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/guava/Present.java b/java/src/main/java/org/whispersystems/libaxolotl/util/guava/Present.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/util/guava/Present.java
rename to java/src/main/java/org/whispersystems/libaxolotl/util/guava/Present.java
diff --git a/src/main/java/org/whispersystems/libaxolotl/util/guava/Supplier.java b/java/src/main/java/org/whispersystems/libaxolotl/util/guava/Supplier.java
similarity index 100%
rename from src/main/java/org/whispersystems/libaxolotl/util/guava/Supplier.java
rename to java/src/main/java/org/whispersystems/libaxolotl/util/guava/Supplier.java
diff --git a/java/src/test/java/org/whispersystems/libaxolotl/CurveTest.java b/java/src/test/java/org/whispersystems/libaxolotl/CurveTest.java
new file mode 100644
index 000000000..734f6c860
--- /dev/null
+++ b/java/src/test/java/org/whispersystems/libaxolotl/CurveTest.java
@@ -0,0 +1,26 @@
+package org.whispersystems.libaxolotl;
+
+import junit.framework.TestCase;
+
+import org.whispersystems.libaxolotl.ecc.Curve;
+import org.whispersystems.libaxolotl.ecc.ECKeyPair;
+
+public class CurveTest extends TestCase {
+
+ public void testPureJava() {
+ assertFalse(Curve.isNative());
+ }
+
+ public void testSignatureOverflow() throws InvalidKeyException {
+ ECKeyPair keys = Curve.generateKeyPair();
+ byte[] message = new byte[4096];
+
+ try {
+ byte[] signature = Curve.calculateSignature(keys.getPrivateKey(), message);
+ throw new InvalidKeyException("Should have asserted!");
+ } catch (IllegalArgumentException e) {
+ // Success!
+ }
+ }
+
+}
diff --git a/libs/armeabi-v7a/libcurve25519.so b/libs/armeabi-v7a/libcurve25519.so
deleted file mode 100755
index 92bc52357..000000000
Binary files a/libs/armeabi-v7a/libcurve25519.so and /dev/null differ
diff --git a/libs/armeabi/libcurve25519.so b/libs/armeabi/libcurve25519.so
deleted file mode 100755
index 8fc5d8f21..000000000
Binary files a/libs/armeabi/libcurve25519.so and /dev/null differ
diff --git a/libs/mips/libcurve25519.so b/libs/mips/libcurve25519.so
deleted file mode 100755
index b738852c3..000000000
Binary files a/libs/mips/libcurve25519.so and /dev/null differ
diff --git a/libs/x86/libcurve25519.so b/libs/x86/libcurve25519.so
deleted file mode 100755
index c06bd2b73..000000000
Binary files a/libs/x86/libcurve25519.so and /dev/null differ
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 000000000..7412250bb
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':java', ':android', ':tests'
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
deleted file mode 100644
index 28d281688..000000000
--- a/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
diff --git a/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java b/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java
deleted file mode 100644
index 685a4a11c..000000000
--- a/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- * Copyright (C) 2013 Open Whisper Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.whispersystems.libaxolotl.ecc;
-
-import org.whispersystems.libaxolotl.InvalidKeyException;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-
-public class Curve25519 {
-
- static {
- System.loadLibrary("curve25519");
-
- try {
- random = SecureRandom.getInstance("SHA1PRNG");
- } catch (NoSuchAlgorithmException e) {
- throw new AssertionError(e);
- }
- }
-
- private static final SecureRandom random;
-
- private static native byte[] calculateAgreement(byte[] ourPrivate, byte[] theirPublic);
- private static native byte[] generatePublicKey(byte[] privateKey);
- private static native byte[] generatePrivateKey(byte[] random);
-
- private static native byte[] calculateSignature(byte[] random, byte[] privateKey, byte[] message);
- private static native boolean verifySignature(byte[] publicKey, byte[] message, byte[] signature);
-
- public static ECKeyPair generateKeyPair() {
- byte[] privateKey = generatePrivateKey();
- byte[] publicKey = generatePublicKey(privateKey);
-
- return new ECKeyPair(new DjbECPublicKey(publicKey), new DjbECPrivateKey(privateKey));
- }
-
- static byte[] calculateAgreement(ECPublicKey publicKey, ECPrivateKey privateKey) {
- return calculateAgreement(((DjbECPrivateKey)privateKey).getPrivateKey(),
- ((DjbECPublicKey)publicKey).getPublicKey());
- }
-
- static byte[] calculateSignature(ECPrivateKey privateKey, byte[] message) {
- byte[] random = getRandom(64);
- return calculateSignature(random, ((DjbECPrivateKey)privateKey).getPrivateKey(), message);
- }
-
- static boolean verifySignature(ECPublicKey publicKey, byte[] message, byte[] signature) {
- return verifySignature(((DjbECPublicKey)publicKey).getPublicKey(), message, signature);
- }
-
- static ECPublicKey decodePoint(byte[] encoded, int offset)
- throws InvalidKeyException
- {
- int type = encoded[offset] & 0xFF;
- byte[] keyBytes = new byte[32];
- System.arraycopy(encoded, offset+1, keyBytes, 0, keyBytes.length);
-
- if (type != Curve.DJB_TYPE) {
- throw new InvalidKeyException("Bad key type: " + type);
- }
-
- return new DjbECPublicKey(keyBytes);
- }
-
- private static byte[] generatePrivateKey() {
- byte[] privateKey = new byte[32];
- random.nextBytes(privateKey);
-
- return generatePrivateKey(privateKey);
- }
-
- private static byte[] getRandom(int size) {
- try {
- byte[] random = new byte[size];
- SecureRandom.getInstance("SHA1PRNG").nextBytes(random);
-
- return random;
- } catch (NoSuchAlgorithmException e) {
- throw new AssertionError(e);
- }
- }
-
-}
diff --git a/tests/build.gradle b/tests/build.gradle
new file mode 100644
index 000000000..bc71da90c
--- /dev/null
+++ b/tests/build.gradle
@@ -0,0 +1,13 @@
+apply plugin: 'java'
+
+repositories {
+ mavenCentral()
+ mavenLocal()
+}
+
+dependencies {
+ compile 'junit:junit:3.8.2'
+ testCompile 'junit:junit:3.8.2'
+
+ compile project(':java')
+}
\ No newline at end of file
diff --git a/src/androidTest/java/org/whispersystems/test/InMemoryAxolotlStore.java b/tests/src/main/java/org/whispersystems/libaxolotl/InMemoryAxolotlStore.java
similarity index 94%
rename from src/androidTest/java/org/whispersystems/test/InMemoryAxolotlStore.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/InMemoryAxolotlStore.java
index 4e0018657..e375c5747 100644
--- a/src/androidTest/java/org/whispersystems/test/InMemoryAxolotlStore.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/InMemoryAxolotlStore.java
@@ -1,8 +1,5 @@
-package org.whispersystems.test;
+package org.whispersystems.libaxolotl;
-import org.whispersystems.libaxolotl.IdentityKey;
-import org.whispersystems.libaxolotl.IdentityKeyPair;
-import org.whispersystems.libaxolotl.InvalidKeyIdException;
import org.whispersystems.libaxolotl.state.AxolotlStore;
import org.whispersystems.libaxolotl.state.PreKeyRecord;
import org.whispersystems.libaxolotl.state.SessionRecord;
diff --git a/src/androidTest/java/org/whispersystems/test/InMemoryIdentityKeyStore.java b/tests/src/main/java/org/whispersystems/libaxolotl/InMemoryIdentityKeyStore.java
similarity index 91%
rename from src/androidTest/java/org/whispersystems/test/InMemoryIdentityKeyStore.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/InMemoryIdentityKeyStore.java
index 8a2e1d8f3..acb6110a4 100644
--- a/src/androidTest/java/org/whispersystems/test/InMemoryIdentityKeyStore.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/InMemoryIdentityKeyStore.java
@@ -1,7 +1,5 @@
-package org.whispersystems.test;
+package org.whispersystems.libaxolotl;
-import org.whispersystems.libaxolotl.IdentityKey;
-import org.whispersystems.libaxolotl.IdentityKeyPair;
import org.whispersystems.libaxolotl.ecc.Curve;
import org.whispersystems.libaxolotl.ecc.ECKeyPair;
import org.whispersystems.libaxolotl.state.IdentityKeyStore;
diff --git a/src/androidTest/java/org/whispersystems/test/InMemoryPreKeyStore.java b/tests/src/main/java/org/whispersystems/libaxolotl/InMemoryPreKeyStore.java
similarity index 91%
rename from src/androidTest/java/org/whispersystems/test/InMemoryPreKeyStore.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/InMemoryPreKeyStore.java
index 7c3cea08b..a2ea6811d 100644
--- a/src/androidTest/java/org/whispersystems/test/InMemoryPreKeyStore.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/InMemoryPreKeyStore.java
@@ -1,6 +1,5 @@
-package org.whispersystems.test;
+package org.whispersystems.libaxolotl;
-import org.whispersystems.libaxolotl.InvalidKeyIdException;
import org.whispersystems.libaxolotl.state.PreKeyRecord;
import org.whispersystems.libaxolotl.state.PreKeyStore;
diff --git a/src/androidTest/java/org/whispersystems/test/InMemorySessionStore.java b/tests/src/main/java/org/whispersystems/libaxolotl/InMemorySessionStore.java
similarity index 97%
rename from src/androidTest/java/org/whispersystems/test/InMemorySessionStore.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/InMemorySessionStore.java
index 0d148ab03..2d03d4377 100644
--- a/src/androidTest/java/org/whispersystems/test/InMemorySessionStore.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/InMemorySessionStore.java
@@ -1,4 +1,4 @@
-package org.whispersystems.test;
+package org.whispersystems.libaxolotl;
import org.whispersystems.libaxolotl.state.SessionRecord;
import org.whispersystems.libaxolotl.state.SessionStore;
diff --git a/src/androidTest/java/org/whispersystems/test/InMemorySignedPreKeyStore.java b/tests/src/main/java/org/whispersystems/libaxolotl/InMemorySignedPreKeyStore.java
similarity index 94%
rename from src/androidTest/java/org/whispersystems/test/InMemorySignedPreKeyStore.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/InMemorySignedPreKeyStore.java
index 7449eecea..9f452d6d5 100644
--- a/src/androidTest/java/org/whispersystems/test/InMemorySignedPreKeyStore.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/InMemorySignedPreKeyStore.java
@@ -1,6 +1,5 @@
-package org.whispersystems.test;
+package org.whispersystems.libaxolotl;
-import org.whispersystems.libaxolotl.InvalidKeyIdException;
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
import org.whispersystems.libaxolotl.state.SignedPreKeyStore;
diff --git a/src/androidTest/java/org/whispersystems/test/SessionBuilderTest.java b/tests/src/main/java/org/whispersystems/libaxolotl/SessionBuilderTest.java
similarity index 97%
rename from src/androidTest/java/org/whispersystems/test/SessionBuilderTest.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/SessionBuilderTest.java
index 802f401dc..0912493ee 100644
--- a/src/androidTest/java/org/whispersystems/test/SessionBuilderTest.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/SessionBuilderTest.java
@@ -1,18 +1,7 @@
-package org.whispersystems.test;
+package org.whispersystems.libaxolotl;
-import android.test.AndroidTestCase;
+import junit.framework.TestCase;
-import org.whispersystems.libaxolotl.DuplicateMessageException;
-import org.whispersystems.libaxolotl.InvalidKeyException;
-import org.whispersystems.libaxolotl.InvalidKeyIdException;
-import org.whispersystems.libaxolotl.InvalidMessageException;
-import org.whispersystems.libaxolotl.InvalidVersionException;
-import org.whispersystems.libaxolotl.LegacyMessageException;
-import org.whispersystems.libaxolotl.NoSessionException;
-import org.whispersystems.libaxolotl.SessionBuilder;
-import org.whispersystems.libaxolotl.SessionCipher;
-import org.whispersystems.libaxolotl.StaleKeyExchangeException;
-import org.whispersystems.libaxolotl.UntrustedIdentityException;
import org.whispersystems.libaxolotl.ecc.Curve;
import org.whispersystems.libaxolotl.ecc.ECKeyPair;
import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
@@ -29,7 +18,7 @@ import org.whispersystems.libaxolotl.util.Pair;
import java.util.HashSet;
import java.util.Set;
-public class SessionBuilderTest extends AndroidTestCase {
+public class SessionBuilderTest extends TestCase {
private static final long ALICE_RECIPIENT_ID = 5L;
private static final long BOB_RECIPIENT_ID = 2L;
diff --git a/src/androidTest/java/org/whispersystems/test/SessionCipherTest.java b/tests/src/main/java/org/whispersystems/libaxolotl/SessionCipherTest.java
similarity index 94%
rename from src/androidTest/java/org/whispersystems/test/SessionCipherTest.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/SessionCipherTest.java
index 52b5fa898..e956ed775 100644
--- a/src/androidTest/java/org/whispersystems/test/SessionCipherTest.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/SessionCipherTest.java
@@ -1,15 +1,7 @@
-package org.whispersystems.test;
+package org.whispersystems.libaxolotl;
-import android.test.AndroidTestCase;
+import junit.framework.TestCase;
-import org.whispersystems.libaxolotl.DuplicateMessageException;
-import org.whispersystems.libaxolotl.IdentityKey;
-import org.whispersystems.libaxolotl.IdentityKeyPair;
-import org.whispersystems.libaxolotl.InvalidKeyException;
-import org.whispersystems.libaxolotl.InvalidMessageException;
-import org.whispersystems.libaxolotl.LegacyMessageException;
-import org.whispersystems.libaxolotl.NoSessionException;
-import org.whispersystems.libaxolotl.SessionCipher;
import org.whispersystems.libaxolotl.ecc.Curve;
import org.whispersystems.libaxolotl.ecc.ECKeyPair;
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
@@ -31,7 +23,7 @@ import java.util.List;
import java.util.Random;
-public class SessionCipherTest extends AndroidTestCase {
+public class SessionCipherTest extends TestCase {
public void testBasicSessionV2()
throws InvalidKeyException, DuplicateMessageException,
diff --git a/src/androidTest/java/org/whispersystems/test/SimultaneousInitiateTests.java b/tests/src/main/java/org/whispersystems/libaxolotl/SimultaneousInitiateTests.java
similarity index 96%
rename from src/androidTest/java/org/whispersystems/test/SimultaneousInitiateTests.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/SimultaneousInitiateTests.java
index dffde57c6..f09fedf8e 100644
--- a/src/androidTest/java/org/whispersystems/test/SimultaneousInitiateTests.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/SimultaneousInitiateTests.java
@@ -1,18 +1,7 @@
-package org.whispersystems.test;
+package org.whispersystems.libaxolotl;
-import android.test.AndroidTestCase;
-import android.util.Log;
+import junit.framework.TestCase;
-import org.whispersystems.libaxolotl.DuplicateMessageException;
-import org.whispersystems.libaxolotl.InvalidKeyException;
-import org.whispersystems.libaxolotl.InvalidKeyIdException;
-import org.whispersystems.libaxolotl.InvalidMessageException;
-import org.whispersystems.libaxolotl.InvalidVersionException;
-import org.whispersystems.libaxolotl.LegacyMessageException;
-import org.whispersystems.libaxolotl.NoSessionException;
-import org.whispersystems.libaxolotl.SessionBuilder;
-import org.whispersystems.libaxolotl.SessionCipher;
-import org.whispersystems.libaxolotl.UntrustedIdentityException;
import org.whispersystems.libaxolotl.ecc.Curve;
import org.whispersystems.libaxolotl.ecc.ECKeyPair;
import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
@@ -27,7 +16,7 @@ import org.whispersystems.libaxolotl.util.Medium;
import java.util.Arrays;
import java.util.Random;
-public class SimultaneousInitiateTests extends AndroidTestCase {
+public class SimultaneousInitiateTests extends TestCase {
private static final long BOB_RECIPENT_ID = 12345;
private static final long ALICE_RECIPIENT_ID = 6789;
@@ -243,7 +232,6 @@ public class SimultaneousInitiateTests extends AndroidTestCase {
assertFalse(isSessionIdEqual(aliceStore, bobStore));
for (int i=0;i<50;i++) {
- Log.w("SimultaneousInitiateTests", "Iteration: " + i);
CiphertextMessage messageForBobRepeat = aliceSessionCipher.encrypt("hey there".getBytes());
CiphertextMessage messageForAliceRepeat = bobSessionCipher.encrypt("sample message".getBytes());
@@ -323,7 +311,6 @@ public class SimultaneousInitiateTests extends AndroidTestCase {
}
for (int i=0;i<50;i++) {
- Log.w("SimultaneousInitiateTests", "Iteration: " + i);
CiphertextMessage messageForBobRepeat = aliceSessionCipher.encrypt("hey there".getBytes());
CiphertextMessage messageForAliceRepeat = bobSessionCipher.encrypt("sample message".getBytes());
@@ -412,7 +399,6 @@ public class SimultaneousInitiateTests extends AndroidTestCase {
}
for (int i=0;i<50;i++) {
- Log.w("SimultaneousInitiateTests", "Iteration: " + i);
CiphertextMessage messageForBobRepeat = aliceSessionCipher.encrypt("hey there".getBytes());
CiphertextMessage messageForAliceRepeat = bobSessionCipher.encrypt("sample message".getBytes());
diff --git a/src/androidTest/java/org/whispersystems/test/ecc/Curve25519Test.java b/tests/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519Test.java
similarity index 92%
rename from src/androidTest/java/org/whispersystems/test/ecc/Curve25519Test.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519Test.java
index 4b8ce2ea1..b10085bbc 100644
--- a/src/androidTest/java/org/whispersystems/test/ecc/Curve25519Test.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/ecc/Curve25519Test.java
@@ -1,20 +1,15 @@
-package org.whispersystems.test.ecc;
+package org.whispersystems.libaxolotl.ecc;
-import android.test.AndroidTestCase;
+import junit.framework.TestCase;
import org.whispersystems.libaxolotl.InvalidKeyException;
-import org.whispersystems.libaxolotl.ecc.Curve;
-import org.whispersystems.libaxolotl.ecc.ECKeyPair;
-import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
-import org.whispersystems.libaxolotl.ecc.ECPublicKey;
import java.util.Arrays;
-public class Curve25519Test extends AndroidTestCase {
+public class Curve25519Test extends TestCase {
public void testAgreement() throws InvalidKeyException {
-
byte[] alicePublic = {(byte) 0x05, (byte) 0x1b, (byte) 0xb7, (byte) 0x59, (byte) 0x66,
(byte) 0xf2, (byte) 0xe9, (byte) 0x3a, (byte) 0x36, (byte) 0x91,
(byte) 0xdf, (byte) 0xff, (byte) 0x94, (byte) 0x2b, (byte) 0xb2,
@@ -138,17 +133,4 @@ public class Curve25519Test extends AndroidTestCase {
}
}
}
-
- public void testSignatureOverflow() throws InvalidKeyException {
- ECKeyPair keys = Curve.generateKeyPair();
- byte[] message = new byte[4096];
-
- try {
- byte[] signature = Curve.calculateSignature(keys.getPrivateKey(), message);
- throw new InvalidKeyException("Should have asserted!");
- } catch (AssertionError e) {
- // Success!
- }
- }
-
}
diff --git a/src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java b/tests/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipherTest.java
similarity index 94%
rename from src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipherTest.java
index 6d93e9212..7c9892b02 100644
--- a/src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipherTest.java
@@ -1,25 +1,20 @@
-package org.whispersystems.test.groups;
+package org.whispersystems.libaxolotl.groups;
-import android.test.AndroidTestCase;
-import android.util.Log;
+import junit.framework.TestCase;
import org.whispersystems.libaxolotl.DuplicateMessageException;
import org.whispersystems.libaxolotl.InvalidMessageException;
import org.whispersystems.libaxolotl.LegacyMessageException;
import org.whispersystems.libaxolotl.NoSessionException;
import org.whispersystems.libaxolotl.ecc.ECKeyPair;
-import org.whispersystems.libaxolotl.groups.GroupCipher;
-import org.whispersystems.libaxolotl.groups.GroupSessionBuilder;
import org.whispersystems.libaxolotl.protocol.SenderKeyDistributionMessage;
import org.whispersystems.libaxolotl.util.KeyHelper;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-public class GroupCipherTest extends AndroidTestCase {
+public class GroupCipherTest extends TestCase {
public void testBasicEncryptDecrypt()
throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException
diff --git a/src/androidTest/java/org/whispersystems/test/groups/InMemorySenderKeyStore.java b/tests/src/main/java/org/whispersystems/libaxolotl/groups/InMemorySenderKeyStore.java
similarity index 94%
rename from src/androidTest/java/org/whispersystems/test/groups/InMemorySenderKeyStore.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/groups/InMemorySenderKeyStore.java
index 450d802d9..c012566a1 100644
--- a/src/androidTest/java/org/whispersystems/test/groups/InMemorySenderKeyStore.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/groups/InMemorySenderKeyStore.java
@@ -1,4 +1,4 @@
-package org.whispersystems.test.groups;
+package org.whispersystems.libaxolotl.groups;
import org.whispersystems.libaxolotl.groups.state.SenderKeyRecord;
import org.whispersystems.libaxolotl.groups.state.SenderKeyStore;
diff --git a/src/androidTest/java/org/whispersystems/test/kdf/HKDFTest.java b/tests/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFTest.java
similarity index 98%
rename from src/androidTest/java/org/whispersystems/test/kdf/HKDFTest.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFTest.java
index 079bc4fa5..4cf7166ae 100644
--- a/src/androidTest/java/org/whispersystems/test/kdf/HKDFTest.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/kdf/HKDFTest.java
@@ -1,12 +1,10 @@
-package org.whispersystems.test.kdf;
+package org.whispersystems.libaxolotl.kdf;
-import android.test.AndroidTestCase;
-
-import org.whispersystems.libaxolotl.kdf.HKDF;
+import junit.framework.TestCase;
import java.util.Arrays;
-public class HKDFTest extends AndroidTestCase {
+public class HKDFTest extends TestCase {
public void testVectorV3() {
byte[] ikm = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
diff --git a/src/androidTest/java/org/whispersystems/test/ratchet/ChainKeyTest.java b/tests/src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKeyTest.java
similarity index 94%
rename from src/androidTest/java/org/whispersystems/test/ratchet/ChainKeyTest.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKeyTest.java
index 1197f3ebe..ad17ebb9d 100644
--- a/src/androidTest/java/org/whispersystems/test/ratchet/ChainKeyTest.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/ratchet/ChainKeyTest.java
@@ -1,14 +1,13 @@
-package org.whispersystems.test.ratchet;
+package org.whispersystems.libaxolotl.ratchet;
-import android.test.AndroidTestCase;
+import junit.framework.TestCase;
import org.whispersystems.libaxolotl.kdf.HKDF;
-import org.whispersystems.libaxolotl.ratchet.ChainKey;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
-public class ChainKeyTest extends AndroidTestCase {
+public class ChainKeyTest extends TestCase {
public void testChainKeyDerivationV2() throws NoSuchAlgorithmException {
diff --git a/src/androidTest/java/org/whispersystems/test/ratchet/RatchetingSessionTest.java b/tests/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSessionTest.java
similarity index 97%
rename from src/androidTest/java/org/whispersystems/test/ratchet/RatchetingSessionTest.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSessionTest.java
index 311aff906..939294551 100644
--- a/src/androidTest/java/org/whispersystems/test/ratchet/RatchetingSessionTest.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/ratchet/RatchetingSessionTest.java
@@ -1,7 +1,6 @@
-package org.whispersystems.test.ratchet;
+package org.whispersystems.libaxolotl.ratchet;
-import android.test.AndroidTestCase;
-import android.util.Log;
+import junit.framework.TestCase;
import org.whispersystems.libaxolotl.IdentityKey;
import org.whispersystems.libaxolotl.IdentityKeyPair;
@@ -10,16 +9,12 @@ import org.whispersystems.libaxolotl.ecc.Curve;
import org.whispersystems.libaxolotl.ecc.ECKeyPair;
import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
-import org.whispersystems.libaxolotl.ratchet.AliceAxolotlParameters;
-import org.whispersystems.libaxolotl.ratchet.BobAxolotlParameters;
-import org.whispersystems.libaxolotl.ratchet.RatchetingSession;
import org.whispersystems.libaxolotl.state.SessionState;
-import org.whispersystems.libaxolotl.util.Hex;
import org.whispersystems.libaxolotl.util.guava.Optional;
import java.util.Arrays;
-public class RatchetingSessionTest extends AndroidTestCase {
+public class RatchetingSessionTest extends TestCase {
public void testRatchetingSessionAsBob() throws InvalidKeyException {
byte[] bobPublic = {(byte) 0x05, (byte) 0x2c, (byte) 0xb4, (byte) 0x97,
diff --git a/src/androidTest/java/org/whispersystems/test/ratchet/RootKeyTest.java b/tests/src/main/java/org/whispersystems/libaxolotl/ratchet/RootKeyTest.java
similarity index 95%
rename from src/androidTest/java/org/whispersystems/test/ratchet/RootKeyTest.java
rename to tests/src/main/java/org/whispersystems/libaxolotl/ratchet/RootKeyTest.java
index c48ef23d2..008c7b400 100644
--- a/src/androidTest/java/org/whispersystems/test/ratchet/RootKeyTest.java
+++ b/tests/src/main/java/org/whispersystems/libaxolotl/ratchet/RootKeyTest.java
@@ -1,6 +1,6 @@
-package org.whispersystems.test.ratchet;
+package org.whispersystems.libaxolotl.ratchet;
-import android.test.AndroidTestCase;
+import junit.framework.TestCase;
import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.ecc.Curve;
@@ -8,14 +8,12 @@ import org.whispersystems.libaxolotl.ecc.ECKeyPair;
import org.whispersystems.libaxolotl.ecc.ECPrivateKey;
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
import org.whispersystems.libaxolotl.kdf.HKDF;
-import org.whispersystems.libaxolotl.ratchet.ChainKey;
-import org.whispersystems.libaxolotl.ratchet.RootKey;
import org.whispersystems.libaxolotl.util.Pair;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
-public class RootKeyTest extends AndroidTestCase {
+public class RootKeyTest extends TestCase {
public void testRootKeyDerivationV2() throws NoSuchAlgorithmException, InvalidKeyException {
byte[] rootKeySeed = {(byte) 0x7b, (byte) 0xa6, (byte) 0xde, (byte) 0xbc, (byte) 0x2b,