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,