This commit is contained in:
Niels Andriesse
2019-06-21 10:39:05 +10:00
parent bd00013f02
commit a1b6eaf3f5
9 changed files with 99 additions and 140 deletions

View File

@@ -8,50 +8,42 @@ import org.thoughtcrime.securesms.database.Database
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.whispersystems.libsignal.state.PreKeyRecord
/**
* A database for associating pre key records to contact public keys.
*/
class LokiContactPreKeyDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
companion object {
private val tableName = "loki_contact_pre_key_database"
private val preKeyId = "pre_key_id"
private val pubKey = "pub_key"
@JvmStatic
val createTableCommand = "CREATE TABLE $tableName ($preKeyId INTEGER PRIMARY KEY, $pubKey TEXT);"
private val preKeyID = "pre_key_id"
private val hexEncodedPublicKey = "public_key"
@JvmStatic val createTableCommand = "CREATE TABLE $tableName ($preKeyID INTEGER PRIMARY KEY, $hexEncodedPublicKey TEXT);"
}
fun hasPreKey(pubKey: String): Boolean {
fun hasPreKey(hexEncodedPublicKey: String): Boolean {
val database = databaseHelper.readableDatabase
return database.get(tableName, "${Companion.pubKey} = ?", arrayOf(pubKey)) { cursor ->
return database.get(tableName, "${Companion.hexEncodedPublicKey} = ?", arrayOf(hexEncodedPublicKey)) { cursor ->
cursor.count > 0
} ?: false
}
fun getPreKey(pubKey: String): PreKeyRecord? {
fun getPreKey(hexEncodedPublicKey: String): PreKeyRecord? {
val database = databaseHelper.readableDatabase
return database.get(tableName, "${Companion.pubKey} = ?", arrayOf(pubKey)) { cursor ->
val preKeyId = cursor.getInt(preKeyId)
PreKeyUtil.loadPreKey(context, preKeyId)
return database.get(tableName, "${Companion.hexEncodedPublicKey} = ?", arrayOf(hexEncodedPublicKey)) { cursor ->
val preKeyID = cursor.getInt(preKeyID)
PreKeyUtil.loadPreKey(context, preKeyID)
}
}
fun getOrCreatePreKey(pubKey: String): PreKeyRecord {
return getPreKey(pubKey) ?: generateAndStorePreKey(pubKey)
fun getOrCreatePreKey(hexEncodedPublicKey: String): PreKeyRecord {
return getPreKey(hexEncodedPublicKey) ?: generateAndStorePreKey(hexEncodedPublicKey)
}
private fun generateAndStorePreKey(pubKey: String): PreKeyRecord {
val records = PreKeyUtil.generatePreKeys(context, 1)
PreKeyUtil.storePreKeyRecords(context, records)
val record = records.first()
private fun generateAndStorePreKey(hexEncodedPublicKey: String): PreKeyRecord {
val preKeyRecords = PreKeyUtil.generatePreKeys(context, 1)
PreKeyUtil.storePreKeyRecords(context, preKeyRecords)
val record = preKeyRecords.first()
val database = databaseHelper.writableDatabase
val values = ContentValues()
values.put(Companion.pubKey, pubKey)
values.put(preKeyId, record.id)
values.put(Companion.hexEncodedPublicKey, hexEncodedPublicKey)
values.put(preKeyID, record.id)
database.insertWithOnConflict(tableName, null, values, SQLiteDatabase.CONFLICT_REPLACE)
return record
}

View File

@@ -9,30 +9,25 @@ class LokiMessageFriendRequestDatabase(context: Context, helper: SQLCipherOpenHe
companion object {
private val tableName = "loki_sms_friend_request_database"
private val smsId = "_id"
private val messageID = "message_id"
private val isFriendRequest = "is_friend_request"
@JvmStatic
val createTableCommand = "CREATE TABLE $tableName ($smsId INTEGER PRIMARY KEY, $isFriendRequest INTEGER DEFAULT 0);"
@JvmStatic val createTableCommand = "CREATE TABLE $tableName ($messageID INTEGER PRIMARY KEY, $isFriendRequest INTEGER DEFAULT 0);"
}
fun getIsFriendRequest(messageId: Long): Boolean {
fun getIsFriendRequest(messageID: Long): Boolean {
val database = databaseHelper.readableDatabase
return database.get(tableName, ID_WHERE, arrayOf( messageId.toString() )) { cursor ->
return database.get(tableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
val rawIsFriendRequest = cursor.getInt(isFriendRequest)
rawIsFriendRequest == 1
} ?: false
}
fun setIsFriendRequest(messageId: Long, isFriendRequest: Boolean) {
fun setIsFriendRequest(messageID: Long, isFriendRequest: Boolean) {
val database = databaseHelper.writableDatabase
val rawIsFriendRequest = if (isFriendRequest) 1 else 0
val contentValues = ContentValues()
contentValues.put(smsId, messageId)
contentValues.put(Companion.messageID, messageID)
contentValues.put(Companion.isFriendRequest, rawIsFriendRequest)
database.insertOrUpdate(tableName, contentValues, ID_WHERE, arrayOf( messageId.toString() ))
database.insertOrUpdate(tableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
}
}

View File

@@ -19,101 +19,86 @@ class LokiPreKeyBundleDatabase(context: Context, helper: SQLCipherOpenHelper) :
companion object {
private val tableName = "loki_pre_key_bundle_database"
private val pubKey = "pub_key"
private val preKeyId = "pre_key_id"
private val hexEncodedPublicKey = "public_key"
private val preKeyID = "pre_key_id"
private val preKeyPublic = "pre_key_public"
private val signedPreKeyId = "signed_pre_key_id"
private val signedPreKeyID = "signed_pre_key_id"
private val signedPreKeyPublic = "signed_pre_key_public"
private val signedPreKeySignature = "signed_pre_key_signature"
private val identityKey = "identity_key"
private val deviceId = "device_id"
private val registrationId = "registration_id"
@JvmStatic
val createTableCommand = "CREATE TABLE $tableName (" +
"$pubKey TEXT PRIMARY KEY," +
"$preKeyId INTEGER," +
"$preKeyPublic TEXT NOT NULL," +
"$signedPreKeyId INTEGER," +
"$signedPreKeyPublic TEXT NOT NULL," +
"$signedPreKeySignature TEXT," +
"$identityKey TEXT NOT NULL," +
"$deviceId INTEGER," +
"$registrationId INTEGER" +
");"
private val deviceID = "device_id"
private val registrationID = "registration_id"
@JvmStatic val createTableCommand = "CREATE TABLE $tableName (" + "$hexEncodedPublicKey TEXT PRIMARY KEY," + "$preKeyID INTEGER," +
"$preKeyPublic TEXT NOT NULL," + "$signedPreKeyID INTEGER," + "$signedPreKeyPublic TEXT NOT NULL," +
"$signedPreKeySignature TEXT," + "$identityKey TEXT NOT NULL," + "$deviceID INTEGER," + "$registrationID INTEGER" + ");"
}
/**
* Generate a `PreKeyBundle` for the given contact.
* This generated bundle shouldn't be stored locally since this is used to generate bundles to send to other users.
*
* @param pubKey String The hex encoded public key of the contact.
* @param hexEncodedPublicKey String The hex encoded public key of the contact.
* @return PreKeyBundle? A pre key bundle or `null` if something went wrong.
*/
fun generatePreKeyBundle(pubKey: String): PreKeyBundle? {
fun generatePreKeyBundle(hexEncodedPublicKey: String): PreKeyBundle? {
val identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context)
val signedPreKey = PreKeyUtil.getActiveSignedPreKey(context) ?: return null
val preKeyRecord = DatabaseFactory.getLokiContactPreKeyDatabase(context).getOrCreatePreKey(pubKey)
val registrationId = TextSecurePreferences.getLocalRegistrationId(context)
if (registrationId == 0) return null
val deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID
return PreKeyBundle(registrationId, deviceId,preKeyRecord.id, preKeyRecord.keyPair.publicKey, signedPreKey.id, signedPreKey.keyPair.publicKey, signedPreKey.signature, identityKeyPair.publicKey)
val preKeyRecord = DatabaseFactory.getLokiContactPreKeyDatabase(context).getOrCreatePreKey(hexEncodedPublicKey)
val registrationID = TextSecurePreferences.getLocalRegistrationId(context)
if (registrationID == 0) return null
val deviceID = SignalServiceAddress.DEFAULT_DEVICE_ID
return PreKeyBundle(registrationID, deviceID,preKeyRecord.id, preKeyRecord.keyPair.publicKey, signedPreKey.id, signedPreKey.keyPair.publicKey, signedPreKey.signature, identityKeyPair.publicKey)
}
/**
* Get the `PreKeyBundle` associated with the given contact.
*
* @param pubKey String The hex encoded public key of the contact.
* @param hexEncodedPublicKey String The hex encoded public key of the contact.
* @return PreKeyBundle? The pre key bundle or `null` if it doesn't exist.
*/
fun getPreKeyBundle(pubKey: String): PreKeyBundle? {
fun getPreKeyBundle(hexEncodedPublicKey: String): PreKeyBundle? {
val database = databaseHelper.readableDatabase
return database.get(tableName, "${Companion.pubKey} = ?", arrayOf(pubKey)) { cursor ->
val registrationId = cursor.getInt(registrationId)
val deviceId = cursor.getInt(deviceId)
val preKeyId = cursor.getInt(preKeyId)
return database.get(tableName, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey )) { cursor ->
val registrationID = cursor.getInt(registrationID)
val deviceID = cursor.getInt(deviceID)
val preKeyID = cursor.getInt(preKeyID)
val preKey = Curve.decodePoint(cursor.getBase64EncodedData(preKeyPublic), 0)
val signedPreKeyId = cursor.getInt(signedPreKeyId)
val signedPreKeyID = cursor.getInt(signedPreKeyID)
val signedPreKey = Curve.decodePoint(cursor.getBase64EncodedData(signedPreKeyPublic), 0)
val signedPreKeySignature = cursor.getBase64EncodedData(signedPreKeySignature)
val identityKey = IdentityKey(cursor.getBase64EncodedData(identityKey), 0)
PreKeyBundle(registrationId, deviceId, preKeyId, preKey, signedPreKeyId, signedPreKey, signedPreKeySignature, identityKey)
PreKeyBundle(registrationID, deviceID, preKeyID, preKey, signedPreKeyID, signedPreKey, signedPreKeySignature, identityKey)
}
}
/**
* Set the `PreKeyBundle` for the given contact.
*
* @param pubKey String The hex encoded public key of the contact.
* @param hexEncodedPublicKey String The hex encoded public key of the contact.
* @param preKeyBundle PreKeyBundle The pre key bundle.
*/
fun setPreKeyBundle(pubKey: String, preKeyBundle: PreKeyBundle) {
fun setPreKeyBundle(hexEncodedPublicKey: 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(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(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)
contentValues.put(Companion.hexEncodedPublicKey, hexEncodedPublicKey)
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.
* @param hexEncodedPublicKey String The hex encoded public key of the contact.
*/
fun removePreKeyBundle(pubKey: String) {
fun removePreKeyBundle(hexEncodedPublicKey: String) {
val database = databaseHelper.writableDatabase
database.delete(tableName, "${Companion.pubKey} = ?", arrayOf(pubKey))
database.delete(tableName, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey ))
}
}

View File

@@ -11,15 +11,15 @@ class LokiPreKeyBundleStore(val context: Context) : LokiPreKeyBundleStoreProtoco
private val lock = Object()
}
override fun getPreKeyBundle(pubKey: String): PreKeyBundle? {
override fun getPreKeyBundle(hexEncodedPublicKey: String): PreKeyBundle? {
synchronized(lock) {
return DatabaseFactory.getLokiPreKeyBundleDatabase(context).getPreKeyBundle(pubKey)
return DatabaseFactory.getLokiPreKeyBundleDatabase(context).getPreKeyBundle(hexEncodedPublicKey)
}
}
override fun removePreKeyBundle(pubKey: String) {
override fun removePreKeyBundle(hexEncodedPublicKey: String) {
synchronized(lock) {
DatabaseFactory.getLokiPreKeyBundleDatabase(context).removePreKeyBundle(pubKey)
DatabaseFactory.getLokiPreKeyBundleDatabase(context).removePreKeyBundle(hexEncodedPublicKey)
}
}
}

View File

@@ -9,16 +9,14 @@ class LokiThreadFriendRequestDatabase(context: Context, helper: SQLCipherOpenHel
companion object {
private val tableName = "loki_thread_friend_request_database"
private val threadId = "_id"
private val threadID = "thread_id"
private val friendRequestStatus = "friend_request_status"
@JvmStatic
val createTableCommand = "CREATE TABLE $tableName ($threadId INTEGER PRIMARY KEY, $friendRequestStatus INTEGER DEFAULT 0);"
@JvmStatic val createTableCommand = "CREATE TABLE $tableName ($threadID INTEGER PRIMARY KEY, $friendRequestStatus INTEGER DEFAULT 0);"
}
fun getFriendRequestStatus(threadId: Long): LokiFriendRequestStatus {
fun getFriendRequestStatus(threadID: Long): LokiFriendRequestStatus {
val db = databaseHelper.readableDatabase
val result = db.get(tableName, ID_WHERE, arrayOf( threadId.toString() )) { cursor ->
val result = db.get(tableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
cursor.getInt(friendRequestStatus)
}
return if (result != null) {
@@ -28,12 +26,12 @@ class LokiThreadFriendRequestDatabase(context: Context, helper: SQLCipherOpenHel
}
}
fun setFriendRequestStatus(threadId: Long, status: LokiFriendRequestStatus) {
fun setFriendRequestStatus(threadID: Long, status: LokiFriendRequestStatus) {
val database = databaseHelper.writableDatabase
val contentValues = ContentValues(1)
contentValues.put(Companion.threadId, threadId)
contentValues.put(Companion.threadID, threadID)
contentValues.put(friendRequestStatus, status.rawValue)
database.insertOrUpdate(tableName, contentValues, ID_WHERE, arrayOf( threadId.toString() ))
database.insertOrUpdate(tableName, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
notifyConversationListListeners()
}
}