diff --git a/build.gradle b/build.gradle index bf4c2a5328..9b21884457 100644 --- a/build.gradle +++ b/build.gradle @@ -55,6 +55,12 @@ repositories { includeGroupByRegex "com\\.amulyakhare.*" } } + maven { + url "https://dl.bintray.com/terl/lazysodium-maven" + content { + includeGroupByRegex "com\\.goterl\\.lazycode.*" + } + } google() jcenter() maven { url "https://jitpack.io" } @@ -145,6 +151,8 @@ dependencies { implementation "org.whispersystems:signal-service-android:2.13.2" // Run ./gradlew install from session-android-service to install implementation "org.whispersystems:curve25519-java:0.5.0" // Remote: + implementation "com.goterl.lazycode:lazysodium-android:4.2.0@aar" + implementation "net.java.dev.jna:jna:5.5.0@aar" implementation "com.google.protobuf:protobuf-java:2.5.0" implementation "com.fasterxml.jackson.core:jackson-databind:2.9.8" implementation "com.squareup.okhttp3:okhttp:3.12.1" @@ -264,6 +272,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-dagger.pro', 'proguard-jackson.pro', + 'proguard-jna.pro', 'proguard-sqlite.pro', 'proguard-appcompat-v7.pro', 'proguard-square-okhttp.pro', diff --git a/proguard-jna.pro b/proguard-jna.pro new file mode 100644 index 0000000000..e80831221c --- /dev/null +++ b/proguard-jna.pro @@ -0,0 +1,3 @@ +-dontwarn java.awt.* +-keep class com.sun.jna.* { *; } +-keepclassmembers class * extends com.sun.jna.* { public *; } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java b/src/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java index f2fc74b687..b8b5dd6518 100644 --- a/src/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java +++ b/src/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java @@ -51,6 +51,8 @@ public class IdentityKeyUtil { public static final String IDENTITY_PUBLIC_KEY_PREF = "pref_identity_public_v3"; public static final String IDENTITY_PRIVATE_KEY_PREF = "pref_identity_private_v3"; + public static final String ED25519_PUBLIC_KEY = "pref_ed25519_public_key"; + public static final String ED25519_SECRET_KEY = "pref_ed25519_secret_key"; public static final String lokiSeedKey = "loki_seed"; diff --git a/src/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt index 1ebf1ca1fd..1737b01e5d 100644 --- a/src/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt @@ -13,8 +13,12 @@ import android.text.SpannableStringBuilder import android.text.method.LinkMovementMethod import android.text.style.ClickableSpan import android.text.style.StyleSpan +import android.util.Log import android.view.View import android.widget.Toast +import com.goterl.lazycode.lazysodium.LazySodiumAndroid +import com.goterl.lazycode.lazysodium.SodiumAndroid +import com.goterl.lazycode.lazysodium.utils.KeyPair import kotlinx.android.synthetic.main.activity_register.* import network.loki.messenger.R import org.thoughtcrime.securesms.BaseActionBarActivity @@ -28,16 +32,15 @@ import org.thoughtcrime.securesms.util.Base64 import org.thoughtcrime.securesms.util.Hex import org.thoughtcrime.securesms.util.TextSecurePreferences import org.whispersystems.curve25519.Curve25519 -import org.whispersystems.libsignal.ecc.Curve -import org.whispersystems.libsignal.ecc.ECKeyPair +import org.whispersystems.libsignal.ecc.* import org.whispersystems.libsignal.util.KeyHelper import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey -import java.io.File -import java.io.FileOutputStream class RegisterActivity : BaseActionBarActivity() { + private val sodium = LazySodiumAndroid(SodiumAndroid()) private var seed: ByteArray? = null - private var keyPair: ECKeyPair? = null + private var ed25519KeyPair: KeyPair? = null + private var x25519KeyPair: ECKeyPair? = null set(value) { field = value; updatePublicKeyTextView() } // region Lifecycle @@ -72,7 +75,10 @@ class RegisterActivity : BaseActionBarActivity() { private fun updateKeyPair() { val seedCandidate = Curve25519.getInstance(Curve25519.BEST).generateSeed(16) try { - this.keyPair = Curve.generateKeyPair(seedCandidate + seedCandidate) // Validate the seed + val padding = ByteArray(16) { 0 } + ed25519KeyPair = sodium.cryptoSignSeedKeypair(seedCandidate + padding) + val x25519KeyPair = sodium.convertKeyPairEd25519ToCurve25519(ed25519KeyPair) + this.x25519KeyPair = ECKeyPair(DjbECPublicKey(x25519KeyPair.publicKey.asBytes), DjbECPrivateKey(x25519KeyPair.secretKey.asBytes)) } catch (exception: Exception) { return updateKeyPair() } @@ -80,7 +86,7 @@ class RegisterActivity : BaseActionBarActivity() { } private fun updatePublicKeyTextView() { - val hexEncodedPublicKey = keyPair!!.hexEncodedPublicKey + val hexEncodedPublicKey = x25519KeyPair!!.hexEncodedPublicKey val characterCount = hexEncodedPublicKey.count() var count = 0 val limit = 32 @@ -112,9 +118,11 @@ class RegisterActivity : BaseActionBarActivity() { // region Interaction private fun register() { IdentityKeyUtil.save(this, IdentityKeyUtil.lokiSeedKey, Hex.toStringCondensed(seed)) - IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PUBLIC_KEY_PREF, Base64.encodeBytes(keyPair!!.publicKey.serialize())) - IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(keyPair!!.privateKey.serialize())) - val userHexEncodedPublicKey = keyPair!!.hexEncodedPublicKey + IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PUBLIC_KEY_PREF, Base64.encodeBytes(x25519KeyPair!!.publicKey.serialize())) + IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(x25519KeyPair!!.privateKey.serialize())) + IdentityKeyUtil.save(this, IdentityKeyUtil.ED25519_PUBLIC_KEY, Base64.encodeBytes(ed25519KeyPair!!.publicKey.asBytes)) + IdentityKeyUtil.save(this, IdentityKeyUtil.ED25519_SECRET_KEY, Base64.encodeBytes(ed25519KeyPair!!.secretKey.asBytes)) + val userHexEncodedPublicKey = x25519KeyPair!!.hexEncodedPublicKey val registrationID = KeyHelper.generateRegistrationId(false) TextSecurePreferences.setLocalRegistrationId(this, registrationID) DatabaseFactory.getIdentityDatabase(this).saveIdentity(Address.fromSerialized(userHexEncodedPublicKey), @@ -129,7 +137,7 @@ class RegisterActivity : BaseActionBarActivity() { private fun copyPublicKey() { val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val clip = ClipData.newPlainText("Session ID", keyPair!!.hexEncodedPublicKey) + val clip = ClipData.newPlainText("Session ID", x25519KeyPair!!.hexEncodedPublicKey) clipboard.setPrimaryClip(clip) Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show() }