Merge pull request #371 from loki-project/security

Switch Key Pair Generation Mechanism
This commit is contained in:
Niels Andriesse 2020-10-29 11:07:55 +11:00 committed by GitHub
commit c96c2bdb69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 11 deletions

View File

@ -55,6 +55,12 @@ repositories {
includeGroupByRegex "com\\.amulyakhare.*" includeGroupByRegex "com\\.amulyakhare.*"
} }
} }
maven {
url "https://dl.bintray.com/terl/lazysodium-maven"
content {
includeGroupByRegex "com\\.goterl\\.lazycode.*"
}
}
google() google()
jcenter() jcenter()
maven { url "https://jitpack.io" } 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:signal-service-android:2.13.2" // Run ./gradlew install from session-android-service to install
implementation "org.whispersystems:curve25519-java:0.5.0" implementation "org.whispersystems:curve25519-java:0.5.0"
// Remote: // 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.google.protobuf:protobuf-java:2.5.0"
implementation "com.fasterxml.jackson.core:jackson-databind:2.9.8" implementation "com.fasterxml.jackson.core:jackson-databind:2.9.8"
implementation "com.squareup.okhttp3:okhttp:3.12.1" implementation "com.squareup.okhttp3:okhttp:3.12.1"
@ -264,6 +272,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-dagger.pro', 'proguard-dagger.pro',
'proguard-jackson.pro', 'proguard-jackson.pro',
'proguard-jna.pro',
'proguard-sqlite.pro', 'proguard-sqlite.pro',
'proguard-appcompat-v7.pro', 'proguard-appcompat-v7.pro',
'proguard-square-okhttp.pro', 'proguard-square-okhttp.pro',

3
proguard-jna.pro Normal file
View File

@ -0,0 +1,3 @@
-dontwarn java.awt.*
-keep class com.sun.jna.* { *; }
-keepclassmembers class * extends com.sun.jna.* { public *; }

View File

@ -51,6 +51,8 @@ public class IdentityKeyUtil {
public static final String IDENTITY_PUBLIC_KEY_PREF = "pref_identity_public_v3"; 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 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"; public static final String lokiSeedKey = "loki_seed";

View File

@ -13,8 +13,12 @@ import android.text.SpannableStringBuilder
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan import android.text.style.ClickableSpan
import android.text.style.StyleSpan import android.text.style.StyleSpan
import android.util.Log
import android.view.View import android.view.View
import android.widget.Toast 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 kotlinx.android.synthetic.main.activity_register.*
import network.loki.messenger.R import network.loki.messenger.R
import org.thoughtcrime.securesms.BaseActionBarActivity 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.Hex
import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.curve25519.Curve25519 import org.whispersystems.curve25519.Curve25519
import org.whispersystems.libsignal.ecc.Curve import org.whispersystems.libsignal.ecc.*
import org.whispersystems.libsignal.ecc.ECKeyPair
import org.whispersystems.libsignal.util.KeyHelper import org.whispersystems.libsignal.util.KeyHelper
import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey
import java.io.File
import java.io.FileOutputStream
class RegisterActivity : BaseActionBarActivity() { class RegisterActivity : BaseActionBarActivity() {
private val sodium = LazySodiumAndroid(SodiumAndroid())
private var seed: ByteArray? = null 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() } set(value) { field = value; updatePublicKeyTextView() }
// region Lifecycle // region Lifecycle
@ -72,7 +75,10 @@ class RegisterActivity : BaseActionBarActivity() {
private fun updateKeyPair() { private fun updateKeyPair() {
val seedCandidate = Curve25519.getInstance(Curve25519.BEST).generateSeed(16) val seedCandidate = Curve25519.getInstance(Curve25519.BEST).generateSeed(16)
try { 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) { } catch (exception: Exception) {
return updateKeyPair() return updateKeyPair()
} }
@ -80,7 +86,7 @@ class RegisterActivity : BaseActionBarActivity() {
} }
private fun updatePublicKeyTextView() { private fun updatePublicKeyTextView() {
val hexEncodedPublicKey = keyPair!!.hexEncodedPublicKey val hexEncodedPublicKey = x25519KeyPair!!.hexEncodedPublicKey
val characterCount = hexEncodedPublicKey.count() val characterCount = hexEncodedPublicKey.count()
var count = 0 var count = 0
val limit = 32 val limit = 32
@ -112,9 +118,11 @@ class RegisterActivity : BaseActionBarActivity() {
// region Interaction // region Interaction
private fun register() { private fun register() {
IdentityKeyUtil.save(this, IdentityKeyUtil.lokiSeedKey, Hex.toStringCondensed(seed)) 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_PUBLIC_KEY_PREF, Base64.encodeBytes(x25519KeyPair!!.publicKey.serialize()))
IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(keyPair!!.privateKey.serialize())) IdentityKeyUtil.save(this, IdentityKeyUtil.IDENTITY_PRIVATE_KEY_PREF, Base64.encodeBytes(x25519KeyPair!!.privateKey.serialize()))
val userHexEncodedPublicKey = keyPair!!.hexEncodedPublicKey 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) val registrationID = KeyHelper.generateRegistrationId(false)
TextSecurePreferences.setLocalRegistrationId(this, registrationID) TextSecurePreferences.setLocalRegistrationId(this, registrationID)
DatabaseFactory.getIdentityDatabase(this).saveIdentity(Address.fromSerialized(userHexEncodedPublicKey), DatabaseFactory.getIdentityDatabase(this).saveIdentity(Address.fromSerialized(userHexEncodedPublicKey),
@ -129,7 +137,7 @@ class RegisterActivity : BaseActionBarActivity() {
private fun copyPublicKey() { private fun copyPublicKey() {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager 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) clipboard.setPrimaryClip(clip)
Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
} }