2022-02-01 19:09:04 +00:00
|
|
|
package org.thoughtcrime.securesms.database
|
|
|
|
|
|
|
|
import android.content.Context
|
|
|
|
import androidx.core.content.contentValuesOf
|
2022-03-23 16:56:11 +00:00
|
|
|
import org.signal.core.util.SqlUtil
|
2022-02-01 19:09:04 +00:00
|
|
|
import org.signal.core.util.logging.Log
|
2022-03-23 16:56:11 +00:00
|
|
|
import org.signal.core.util.requireNonNullString
|
2022-03-24 17:23:23 +00:00
|
|
|
import org.signal.libsignal.protocol.InvalidKeyException
|
|
|
|
import org.signal.libsignal.protocol.ecc.Curve
|
|
|
|
import org.signal.libsignal.protocol.ecc.ECKeyPair
|
|
|
|
import org.signal.libsignal.protocol.state.PreKeyRecord
|
2022-02-01 19:09:04 +00:00
|
|
|
import org.thoughtcrime.securesms.util.Base64
|
2022-02-17 20:55:54 +00:00
|
|
|
import org.whispersystems.signalservice.api.push.ServiceId
|
2022-02-01 19:09:04 +00:00
|
|
|
import java.io.IOException
|
|
|
|
|
2022-02-02 16:53:26 +00:00
|
|
|
class OneTimePreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : Database(context, databaseHelper) {
|
2022-02-01 19:09:04 +00:00
|
|
|
companion object {
|
|
|
|
private val TAG = Log.tag(OneTimePreKeyDatabase::class.java)
|
|
|
|
|
|
|
|
const val TABLE_NAME = "one_time_prekeys"
|
|
|
|
const val ID = "_id"
|
|
|
|
const val ACCOUNT_ID = "account_id"
|
|
|
|
const val KEY_ID = "key_id"
|
|
|
|
const val PUBLIC_KEY = "public_key"
|
|
|
|
const val PRIVATE_KEY = "private_key"
|
|
|
|
const val CREATE_TABLE = """
|
|
|
|
CREATE TABLE $TABLE_NAME (
|
|
|
|
$ID INTEGER PRIMARY KEY,
|
|
|
|
$ACCOUNT_ID TEXT NOT NULL,
|
|
|
|
$KEY_ID INTEGER UNIQUE,
|
|
|
|
$PUBLIC_KEY TEXT NOT NULL,
|
|
|
|
$PRIVATE_KEY TEXT NOT NULL,
|
|
|
|
UNIQUE($ACCOUNT_ID, $KEY_ID)
|
|
|
|
)
|
|
|
|
"""
|
|
|
|
}
|
|
|
|
|
2022-02-17 20:55:54 +00:00
|
|
|
fun get(serviceId: ServiceId, keyId: Int): PreKeyRecord? {
|
|
|
|
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId), null, null, null).use { cursor ->
|
2022-02-01 19:09:04 +00:00
|
|
|
if (cursor.moveToFirst()) {
|
|
|
|
try {
|
|
|
|
val publicKey = Curve.decodePoint(Base64.decode(cursor.requireNonNullString(PUBLIC_KEY)), 0)
|
|
|
|
val privateKey = Curve.decodePrivatePoint(Base64.decode(cursor.requireNonNullString(PRIVATE_KEY)))
|
|
|
|
return PreKeyRecord(keyId, ECKeyPair(publicKey, privateKey))
|
|
|
|
} catch (e: InvalidKeyException) {
|
|
|
|
Log.w(TAG, e)
|
|
|
|
} catch (e: IOException) {
|
|
|
|
Log.w(TAG, e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2022-02-17 20:55:54 +00:00
|
|
|
fun insert(serviceId: ServiceId, keyId: Int, record: PreKeyRecord) {
|
2022-02-01 19:09:04 +00:00
|
|
|
val contentValues = contentValuesOf(
|
2022-02-17 20:55:54 +00:00
|
|
|
ACCOUNT_ID to serviceId.toString(),
|
2022-02-01 19:09:04 +00:00
|
|
|
KEY_ID to keyId,
|
|
|
|
PUBLIC_KEY to Base64.encodeBytes(record.keyPair.publicKey.serialize()),
|
|
|
|
PRIVATE_KEY to Base64.encodeBytes(record.keyPair.privateKey.serialize())
|
|
|
|
)
|
|
|
|
|
|
|
|
writableDatabase.replace(TABLE_NAME, null, contentValues)
|
|
|
|
}
|
|
|
|
|
2022-02-17 20:55:54 +00:00
|
|
|
fun delete(serviceId: ServiceId, keyId: Int) {
|
2022-02-01 19:09:04 +00:00
|
|
|
val database = databaseHelper.signalWritableDatabase
|
2022-02-17 20:55:54 +00:00
|
|
|
database.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId))
|
2022-02-01 19:09:04 +00:00
|
|
|
}
|
|
|
|
}
|