kopia lustrzana https://github.com/ryukoposting/Signal-Android
Update sender key store and MSL to be recipient-remap-safe.
The MSL is now remapped in the merge, and the sender key store is now just keyed off of UUIDs.fork-5.53.8
rodzic
88074134af
commit
f65de84c19
|
@ -8,6 +8,7 @@ import org.thoughtcrime.securesms.crypto.storage.SignalSenderKeyStore;
|
|||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||
import org.whispersystems.signalservice.api.SignalSessionLock;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
@ -20,7 +21,7 @@ public final class SenderKeyUtil {
|
|||
*/
|
||||
public static void rotateOurKey(@NonNull Context context, @NonNull DistributionId distributionId) {
|
||||
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
ApplicationDependencies.getSenderKeyStore().deleteAllFor(Recipient.self().getId(), distributionId);
|
||||
ApplicationDependencies.getSenderKeyStore().deleteAllFor(Recipient.self().requireServiceId(), distributionId);
|
||||
DatabaseFactory.getSenderKeySharedDatabase(context).deleteAllFor(distributionId);
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +30,8 @@ public final class SenderKeyUtil {
|
|||
* Gets when the sender key session was created, or -1 if it doesn't exist.
|
||||
*/
|
||||
public static long getCreateTimeForOurKey(@NonNull Context context, @NonNull DistributionId distributionId) {
|
||||
return DatabaseFactory.getSenderKeyDatabase(context).getCreatedTime(Recipient.self().getId(), SignalServiceAddress.DEFAULT_DEVICE_ID, distributionId);
|
||||
SignalProtocolAddress address = new SignalProtocolAddress(Recipient.self().requireServiceId(), SignalServiceAddress.DEFAULT_DEVICE_ID);
|
||||
return DatabaseFactory.getSenderKeyDatabase(context).getCreatedTime(address, distributionId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,16 +34,14 @@ public final class SignalSenderKeyStore implements SignalServiceSenderKeyStore {
|
|||
@Override
|
||||
public void storeSenderKey(@NonNull SignalProtocolAddress sender, @NonNull UUID distributionId, @NonNull SenderKeyRecord record) {
|
||||
synchronized (LOCK) {
|
||||
RecipientId recipientId = RecipientId.fromExternalPush(sender.getName());
|
||||
DatabaseFactory.getSenderKeyDatabase(context).store(recipientId, sender.getDeviceId(), DistributionId.from(distributionId), record);
|
||||
DatabaseFactory.getSenderKeyDatabase(context).store(sender, DistributionId.from(distributionId), record);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SenderKeyRecord loadSenderKey(@NonNull SignalProtocolAddress sender, @NonNull UUID distributionId) {
|
||||
synchronized (LOCK) {
|
||||
RecipientId recipientId = RecipientId.fromExternalPush(sender.getName());
|
||||
return DatabaseFactory.getSenderKeyDatabase(context).load(recipientId, sender.getDeviceId(), DistributionId.from(distributionId));
|
||||
return DatabaseFactory.getSenderKeyDatabase(context).load(sender, DistributionId.from(distributionId));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,9 +69,9 @@ public final class SignalSenderKeyStore implements SignalServiceSenderKeyStore {
|
|||
/**
|
||||
* Removes all sender key session state for all devices for the provided recipient-distributionId pair.
|
||||
*/
|
||||
public void deleteAllFor(@NonNull RecipientId recipientId, @NonNull DistributionId distributionId) {
|
||||
public void deleteAllFor(@NonNull String addressName, @NonNull DistributionId distributionId) {
|
||||
synchronized (LOCK) {
|
||||
DatabaseFactory.getSenderKeyDatabase(context).deleteAllFor(recipientId, distributionId);
|
||||
DatabaseFactory.getSenderKeyDatabase(context).deleteAllFor(addressName, distributionId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -362,5 +362,17 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: SQLC
|
|||
db.delete(PayloadTable.TABLE_NAME, query, args)
|
||||
}
|
||||
|
||||
fun remapRecipient(oldRecipientId: RecipientId, newRecipientId: RecipientId) {
|
||||
val values = ContentValues().apply {
|
||||
put(RecipientTable.RECIPIENT_ID, newRecipientId.serialize())
|
||||
}
|
||||
|
||||
val db = databaseHelper.signalWritableDatabase
|
||||
val query = "${RecipientTable.RECIPIENT_ID} = ?"
|
||||
val args = SqlUtil.buildArgs(oldRecipientId.serialize())
|
||||
|
||||
db.update(RecipientTable.TABLE_NAME, values, query, args)
|
||||
}
|
||||
|
||||
private data class RecipientDevice(val recipientId: RecipientId, val devices: List<Int>)
|
||||
}
|
||||
|
|
|
@ -3111,6 +3111,9 @@ public class RecipientDatabase extends Database {
|
|||
Log.w(TAG, "Had no sessions. No action necessary.", true);
|
||||
}
|
||||
|
||||
// MSL
|
||||
DatabaseFactory.getMessageLogDatabase(context).remapRecipient(byE164, byUuid);
|
||||
|
||||
// Mentions
|
||||
ContentValues mentionRecipientValues = new ContentValues();
|
||||
mentionRecipientValues.put(MentionDatabase.RECIPIENT_ID, byUuid.serialize());
|
||||
|
|
|
@ -10,8 +10,8 @@ import androidx.annotation.Nullable;
|
|||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.CursorUtil;
|
||||
import org.thoughtcrime.securesms.util.SqlUtil;
|
||||
import org.whispersystems.libsignal.groups.state.SenderKeyRecord;
|
||||
|
@ -31,30 +31,30 @@ public class SenderKeyDatabase extends Database {
|
|||
public static final String TABLE_NAME = "sender_keys";
|
||||
|
||||
private static final String ID = "_id";
|
||||
public static final String RECIPIENT_ID = "recipient_id";
|
||||
public static final String ADDRESS = "address";
|
||||
public static final String DEVICE = "device";
|
||||
public static final String DISTRIBUTION_ID = "distribution_id";
|
||||
public static final String RECORD = "record";
|
||||
public static final String CREATED_AT = "created_at";
|
||||
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
RECIPIENT_ID + " INTEGER NOT NULL, " +
|
||||
ADDRESS + " TEXT NOT NULL, " +
|
||||
DEVICE + " INTEGER NOT NULL, " +
|
||||
DISTRIBUTION_ID + " TEXT NOT NULL, " +
|
||||
RECORD + " BLOB NOT NULL, " +
|
||||
CREATED_AT + " INTEGER NOT NULL, " +
|
||||
"UNIQUE(" + RECIPIENT_ID + "," + DEVICE + ", " + DISTRIBUTION_ID + ") ON CONFLICT REPLACE);";
|
||||
"UNIQUE(" + ADDRESS + "," + DEVICE + ", " + DISTRIBUTION_ID + ") ON CONFLICT REPLACE);";
|
||||
|
||||
SenderKeyDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
|
||||
super(context, databaseHelper);
|
||||
}
|
||||
|
||||
public void store(@NonNull RecipientId recipientId, int deviceId, @NonNull DistributionId distributionId, @NonNull SenderKeyRecord record) {
|
||||
public void store(@NonNull SignalProtocolAddress address, @NonNull DistributionId distributionId, @NonNull SenderKeyRecord record) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(RECIPIENT_ID, recipientId.serialize());
|
||||
values.put(DEVICE, deviceId);
|
||||
values.put(ADDRESS, address.getName());
|
||||
values.put(DEVICE, address.getDeviceId());
|
||||
values.put(DISTRIBUTION_ID, distributionId.toString());
|
||||
values.put(RECORD, record.serialize());
|
||||
values.put(CREATED_AT, System.currentTimeMillis());
|
||||
|
@ -62,11 +62,11 @@ public class SenderKeyDatabase extends Database {
|
|||
db.insertWithOnConflict(TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
|
||||
}
|
||||
|
||||
public @Nullable SenderKeyRecord load(@NonNull RecipientId recipientId, int deviceId, @NonNull DistributionId distributionId) {
|
||||
public @Nullable SenderKeyRecord load(@NonNull SignalProtocolAddress address, @NonNull DistributionId distributionId) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
|
||||
|
||||
String query = RECIPIENT_ID + " = ? AND " + DEVICE + " = ? AND " + DISTRIBUTION_ID + " = ?";
|
||||
String[] args = SqlUtil.buildArgs(recipientId, deviceId, distributionId);
|
||||
String query = ADDRESS + " = ? AND " + DEVICE + " = ? AND " + DISTRIBUTION_ID + " = ?";
|
||||
String[] args = SqlUtil.buildArgs(address.getName(), address.getDeviceId(), distributionId);
|
||||
|
||||
try (Cursor cursor = db.query(TABLE_NAME, new String[]{ RECORD }, query, args, null, null, null)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
|
@ -84,11 +84,11 @@ public class SenderKeyDatabase extends Database {
|
|||
/**
|
||||
* Gets when the sender key session was created, or -1 if it doesn't exist.
|
||||
*/
|
||||
public long getCreatedTime(@NonNull RecipientId recipientId, int deviceId, @NonNull DistributionId distributionId) {
|
||||
public long getCreatedTime(@NonNull SignalProtocolAddress address, @NonNull DistributionId distributionId) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
|
||||
|
||||
String query = RECIPIENT_ID + " = ? AND " + DEVICE + " = ? AND " + DISTRIBUTION_ID + " = ?";
|
||||
String[] args = SqlUtil.buildArgs(recipientId, deviceId, distributionId);
|
||||
String query = ADDRESS + " = ? AND " + DEVICE + " = ? AND " + DISTRIBUTION_ID + " = ?";
|
||||
String[] args = SqlUtil.buildArgs(address.getName(), address.getDeviceId(), distributionId);
|
||||
|
||||
try (Cursor cursor = db.query(TABLE_NAME, new String[]{ CREATED_AT }, query, args, null, null, null)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
|
@ -102,10 +102,10 @@ public class SenderKeyDatabase extends Database {
|
|||
/**
|
||||
* Removes all sender key session state for all devices for the provided recipient-distributionId pair.
|
||||
*/
|
||||
public void deleteAllFor(@NonNull RecipientId recipientId, @NonNull DistributionId distributionId) {
|
||||
public void deleteAllFor(@NonNull String addressName, @NonNull DistributionId distributionId) {
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
String query = RECIPIENT_ID + " = ? AND " + DISTRIBUTION_ID + " = ?";
|
||||
String[] args = SqlUtil.buildArgs(recipientId, distributionId);
|
||||
String query = ADDRESS + " = ? AND " + DISTRIBUTION_ID + " = ?";
|
||||
String[] args = SqlUtil.buildArgs(addressName, distributionId);
|
||||
|
||||
db.delete(TABLE_NAME, query, args);
|
||||
}
|
||||
|
|
|
@ -217,8 +217,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements SignalDatab
|
|||
private static final int CLEANUP_SESSION_MIGRATION = 116;
|
||||
private static final int RECEIPT_TIMESTAMP = 117;
|
||||
private static final int BADGES = 118;
|
||||
private static final int SENDER_KEY_UUID = 119;
|
||||
|
||||
private static final int DATABASE_VERSION = 118;
|
||||
private static final int DATABASE_VERSION = 119;
|
||||
private static final String DATABASE_NAME = "signal.db";
|
||||
|
||||
private final Context context;
|
||||
|
@ -2048,6 +2049,32 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements SignalDatab
|
|||
db.execSQL("ALTER TABLE recipient ADD COLUMN badges BLOB DEFAULT NULL");
|
||||
}
|
||||
|
||||
if (oldVersion < SENDER_KEY_UUID) {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
db.execSQL("CREATE TABLE sender_keys_tmp (_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"address TEXT NOT NULL, " +
|
||||
"device INTEGER NOT NULL, " +
|
||||
"distribution_id TEXT NOT NULL, " +
|
||||
"record BLOB NOT NULL, " +
|
||||
"created_at INTEGER NOT NULL, " +
|
||||
"UNIQUE(address, device, distribution_id) ON CONFLICT REPLACE)");
|
||||
|
||||
db.execSQL("INSERT INTO sender_keys_tmp (address, device, distribution_id, record, created_at) " +
|
||||
"SELECT recipient.uuid AS new_address, " +
|
||||
"sender_keys.device, " +
|
||||
"sender_keys.distribution_id, " +
|
||||
"sender_keys.record, " +
|
||||
"sender_keys.created_at " +
|
||||
"FROM sender_keys INNER JOIN recipient ON sender_keys.recipient_id = recipient._id " +
|
||||
"WHERE new_address NOT NULL");
|
||||
|
||||
db.execSQL("DROP TABLE sender_keys");
|
||||
db.execSQL("ALTER TABLE sender_keys_tmp RENAME TO sender_keys");
|
||||
|
||||
Log.d(TAG, "Sender key migration took " + (System.currentTimeMillis() - start) + " ms");
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
|
Ładowanie…
Reference in New Issue