diff --git a/src/org/thoughtcrime/securesms/crypto/PreKeyUtil.java b/src/org/thoughtcrime/securesms/crypto/PreKeyUtil.java index 092d0ecc52..2fca2ab61a 100644 --- a/src/org/thoughtcrime/securesms/crypto/PreKeyUtil.java +++ b/src/org/thoughtcrime/securesms/crypto/PreKeyUtil.java @@ -19,6 +19,7 @@ package org.thoughtcrime.securesms.crypto; import android.content.Context; +import org.jetbrains.annotations.Nullable; import org.thoughtcrime.securesms.crypto.storage.TextSecurePreKeyStore; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.libsignal.IdentityKeyPair; @@ -90,7 +91,17 @@ public class PreKeyUtil { return TextSecurePreferences.getActiveSignedPreKeyId(context); } - // region - Loki + // region Loki + public static synchronized @Nullable SignedPreKeyRecord getActiveSignedPreKey(Context context) { + SignedPreKeyStore signedPreKeyStore = new TextSecurePreKeyStore(context); + try { + return signedPreKeyStore.loadSignedPreKey(getActiveSignedPreKeyId(context)); + } catch (InvalidKeyIdException e) { + // Fall through + } + return null; + } + public synchronized static List generatePreKeys(Context context, int amount) { PreKeyStore preKeyStore = new TextSecurePreKeyStore(context); List records = new LinkedList<>(); diff --git a/src/org/thoughtcrime/securesms/database/DatabaseFactory.java b/src/org/thoughtcrime/securesms/database/DatabaseFactory.java index 4935584987..46c1b25375 100644 --- a/src/org/thoughtcrime/securesms/database/DatabaseFactory.java +++ b/src/org/thoughtcrime/securesms/database/DatabaseFactory.java @@ -31,6 +31,8 @@ import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.database.helpers.ClassicOpenHelper; import org.thoughtcrime.securesms.database.helpers.SQLCipherMigrationHelper; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; +import org.thoughtcrime.securesms.loki.LokiContactPreKeyDatabase; +import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase; import org.thoughtcrime.securesms.util.TextSecurePreferences; public class DatabaseFactory { @@ -59,6 +61,10 @@ public class DatabaseFactory { private final SearchDatabase searchDatabase; private final JobDatabase jobDatabase; + // Loki + private final LokiContactPreKeyDatabase lokiContactPreKeyDatabase; + private final LokiPreKeyBundleDatabase lokiPreKeyBundleDatabase; + public static DatabaseFactory getInstance(Context context) { synchronized (lock) { if (instance == null) @@ -144,6 +150,18 @@ public class DatabaseFactory { return getInstance(context).databaseHelper.getReadableDatabase(); } + // region Loki + + public static LokiContactPreKeyDatabase getLokiContactPreKeyDatabase(Context context) { + return getInstance(context).lokiContactPreKeyDatabase; + } + + public static LokiPreKeyBundleDatabase getLokiPreKeyBundleDatabase(Context context) { + return getInstance(context).lokiPreKeyBundleDatabase; + } + + // endregion + public static void upgradeRestored(Context context, SQLiteDatabase database){ getInstance(context).databaseHelper.onUpgrade(database, database.getVersion(), -1); getInstance(context).databaseHelper.markCurrent(database); @@ -174,6 +192,9 @@ public class DatabaseFactory { this.sessionDatabase = new SessionDatabase(context, databaseHelper); this.searchDatabase = new SearchDatabase(context, databaseHelper); this.jobDatabase = new JobDatabase(context, databaseHelper); + + this.lokiContactPreKeyDatabase = new LokiContactPreKeyDatabase(context, databaseHelper); + this.lokiPreKeyBundleDatabase = new LokiPreKeyBundleDatabase(context, databaseHelper); } public void onApplicationLevelUpgrade(@NonNull Context context, @NonNull MasterSecret masterSecret, diff --git a/src/org/thoughtcrime/securesms/loki/LokiContactPreKeyDatabase.kt b/src/org/thoughtcrime/securesms/loki/LokiContactPreKeyDatabase.kt index 37985f340d..16d09074b6 100644 --- a/src/org/thoughtcrime/securesms/loki/LokiContactPreKeyDatabase.kt +++ b/src/org/thoughtcrime/securesms/loki/LokiContactPreKeyDatabase.kt @@ -32,7 +32,7 @@ class LokiContactPreKeyDatabase(context: Context, helper: SQLCipherOpenHelper) : fun getPreKey(pubKey: String): PreKeyRecord? { val database = databaseHelper.readableDatabase return database.get(tableName, "${Companion.pubKey} = ?", arrayOf(pubKey)) { cursor -> - val preKeyId = cursor.getInt(cursor.getColumnIndexOrThrow(preKeyId)) + val preKeyId = cursor.getInt(preKeyId) PreKeyUtil.loadPreKey(context, preKeyId) } } diff --git a/src/org/thoughtcrime/securesms/loki/LokiDatabaseUtilities.kt b/src/org/thoughtcrime/securesms/loki/LokiDatabaseUtilities.kt index ec6233e5d9..312702307f 100644 --- a/src/org/thoughtcrime/securesms/loki/LokiDatabaseUtilities.kt +++ b/src/org/thoughtcrime/securesms/loki/LokiDatabaseUtilities.kt @@ -1,7 +1,8 @@ package org.thoughtcrime.securesms.loki -import android.database.Cursor +import net.sqlcipher.Cursor import net.sqlcipher.database.SQLiteDatabase +import org.thoughtcrime.securesms.util.Base64 fun SQLiteDatabase.get(table: String, query: String, arguments: Array, get: (Cursor) -> T): T? { var cursor: Cursor? = null @@ -14,4 +15,16 @@ fun SQLiteDatabase.get(table: String, query: String, arguments: Array + val registrationId = cursor.getInt(registrationId) + val deviceId = cursor.getInt(deviceId) + val preKeyId = cursor.getInt(preKeyId) + val preKey = Curve.decodePoint(cursor.getBase64Bytes(preKeyPublic), 0) + val signedPreKeyId = cursor.getInt(signedPreKeyId) + val signedPreKey = Curve.decodePoint(cursor.getBase64Bytes(signedPreKeyPublic), 0) + val signedPreKeySignature = cursor.getBase64Bytes(signedPreKeySignature) + val identityKey = IdentityKey(cursor.getBase64Bytes(identityKey), 0) + + PreKeyBundle(registrationId, deviceId, preKeyId, preKey, signedPreKeyId, signedPreKey, signedPreKeySignature, identityKey) + } + } + + /** + * Set the `PreKeyBundle` fore the given contact. + * @param pubKey String The hex encoded public key of the contact + * @param preKeyBundle PreKeyBundle The pre key bundle + */ + fun setPreKeyBundle(pubKey: String, preKeyBundle: PreKeyBundle) { + val database = databaseHelper.writableDatabase + val contentValues = ContentValues() + contentValues.put(registrationId, preKeyBundle.registrationId) + contentValues.put(deviceId, preKeyBundle.deviceId) + contentValues.put(preKeyId, preKeyBundle.preKeyId) + contentValues.put(preKeyPublic, Base64.encodeBytes(preKeyBundle.preKey.serialize())) + contentValues.put(signedPreKeyId, preKeyBundle.signedPreKeyId) + contentValues.put(signedPreKeyPublic, Base64.encodeBytes(preKeyBundle.signedPreKey.serialize())) + contentValues.put(signedPreKeySignature, Base64.encodeBytes(preKeyBundle.signedPreKeySignature)) + contentValues.put(identityKey, Base64.encodeBytes(preKeyBundle.identityKey.serialize())) + contentValues.put(Companion.pubKey, pubKey) + + database.insertWithOnConflict(tableName, null, contentValues, SQLiteDatabase.CONFLICT_REPLACE) + } + + /** + * Remove the `PreKeyBundle` for the given contact. + * @param pubKey String The hex encoded public key of the contact + */ + fun removePreKeyBundle(pubKey: String) { + val database = databaseHelper.writableDatabase + database.delete(tableName, "${Companion.pubKey} = ?", arrayOf(pubKey)) + } + } \ No newline at end of file