WIP: clean up signal protocol storage

This commit is contained in:
Ryan ZHAO
2021-02-19 15:11:30 +11:00
parent 1e1b3e02e1
commit d8104c0d5c
69 changed files with 6 additions and 17407 deletions

View File

@@ -120,10 +120,7 @@ object FullBackupExporter {
}
private inline fun shouldExportTable(table: String): Boolean {
return table != SignedPreKeyDatabase.TABLE_NAME &&
table != OneTimePreKeyDatabase.TABLE_NAME &&
table != SessionDatabase.TABLE_NAME &&
table != PushDatabase.TABLE_NAME &&
return table != PushDatabase.TABLE_NAME &&
table != LokiBackupFilesDatabase.TABLE_NAME &&
table != LokiAPIDatabase.openGroupProfilePictureTable &&

View File

@@ -1,30 +0,0 @@
package org.thoughtcrime.securesms.crypto;
import android.content.Context;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
import org.session.libsession.messaging.threads.Address;
import org.session.libsignal.libsignal.SignalProtocolAddress;
import org.session.libsignal.libsignal.state.SessionStore;
import org.session.libsignal.service.api.push.SignalServiceAddress;
public class SessionUtil {
public static boolean hasSession(Context context, @NonNull Address address) {
SessionStore sessionStore = new TextSecureSessionStore(context);
SignalProtocolAddress axolotlAddress = new SignalProtocolAddress(address.serialize(), SignalServiceAddress.DEFAULT_DEVICE_ID);
return sessionStore.containsSession(axolotlAddress);
}
public static void archiveSiblingSessions(Context context, SignalProtocolAddress address) {
TextSecureSessionStore sessionStore = new TextSecureSessionStore(context);
sessionStore.archiveSiblingSessions(address);
}
public static void archiveAllSessions(Context context) {
new TextSecureSessionStore(context).archiveAllSessions();
}
}

View File

@@ -2,150 +2,20 @@ package org.thoughtcrime.securesms.crypto.storage;
import android.content.Context;
import org.session.libsignal.libsignal.IdentityKey;
import org.session.libsignal.libsignal.IdentityKeyPair;
import org.session.libsignal.libsignal.InvalidKeyIdException;
import org.session.libsignal.libsignal.SignalProtocolAddress;
import org.session.libsignal.libsignal.state.IdentityKeyStore;
import org.session.libsignal.libsignal.state.PreKeyRecord;
import org.session.libsignal.libsignal.state.PreKeyStore;
import org.session.libsignal.libsignal.state.SessionRecord;
import org.session.libsignal.libsignal.state.SessionStore;
import org.session.libsignal.libsignal.state.SignalProtocolStore;
import org.session.libsignal.libsignal.state.SignedPreKeyRecord;
import org.session.libsignal.libsignal.state.SignedPreKeyStore;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import java.util.List;
public class SignalProtocolStoreImpl implements SignalProtocolStore {
public class SignalProtocolStoreImpl implements IdentityKeyStore {
private final Context context;
// private final PreKeyStore preKeyStore;
// private final SignedPreKeyStore signedPreKeyStore;
// private final IdentityKeyStore identityKeyStore;
private final SessionStore sessionStore;
public SignalProtocolStoreImpl(Context context) {
// this.preKeyStore = new TextSecurePreKeyStore(context);
// this.signedPreKeyStore = new TextSecurePreKeyStore(context);
// this.identityKeyStore = new TextSecureIdentityKeyStore(context);
this.sessionStore = new TextSecureSessionStore(context);
this.context = context;
}
@Override
public IdentityKeyPair getIdentityKeyPair() {
return IdentityKeyUtil.getIdentityKeyPair(context);
// return identityKeyStore.getIdentityKeyPair();
// throw new UnsupportedOperationException("This method will be removed with refactor.");
}
@Override
public int getLocalRegistrationId() {
// return identityKeyStore.getLocalRegistrationId();
throw new UnsupportedOperationException("This method will be removed with refactor.");
}
@Override
public boolean saveIdentity(SignalProtocolAddress address, IdentityKey identityKey) {
// return identityKeyStore.saveIdentity(address, identityKey);
throw new UnsupportedOperationException("This method will be removed with refactor.");
}
@Override
public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) {
// return identityKeyStore.isTrustedIdentity(address, identityKey, direction);
throw new UnsupportedOperationException("This method will be removed with refactor.");
}
@Override
public IdentityKey getIdentity(SignalProtocolAddress address) {
// return identityKeyStore.getIdentity(address);
throw new UnsupportedOperationException("This method will be removed with refactor.");
}
@Override
public PreKeyRecord loadPreKey(int preKeyId) throws InvalidKeyIdException {
// return preKeyStore.loadPreKey(preKeyId);
throw new UnsupportedOperationException("This method will be removed with refactor.");
}
@Override
public void storePreKey(int preKeyId, PreKeyRecord record) {
// preKeyStore.storePreKey(preKeyId, record);
throw new UnsupportedOperationException("This method will be removed with refactor.");
}
@Override
public boolean containsPreKey(int preKeyId) {
// return preKeyStore.containsPreKey(preKeyId);
throw new UnsupportedOperationException("This method will be removed with refactor.");
}
@Override
public void removePreKey(int preKeyId) {
// preKeyStore.removePreKey(preKeyId);
throw new UnsupportedOperationException("This method will be removed with refactor.");
}
@Override
public SessionRecord loadSession(SignalProtocolAddress axolotlAddress) {
return sessionStore.loadSession(axolotlAddress);
}
@Override
public List<Integer> getSubDeviceSessions(String number) {
return sessionStore.getSubDeviceSessions(number);
}
@Override
public void storeSession(SignalProtocolAddress axolotlAddress, SessionRecord record) {
sessionStore.storeSession(axolotlAddress, record);
}
@Override
public boolean containsSession(SignalProtocolAddress axolotlAddress) {
return sessionStore.containsSession(axolotlAddress);
}
@Override
public void deleteSession(SignalProtocolAddress axolotlAddress) {
sessionStore.deleteSession(axolotlAddress);
}
@Override
public void deleteAllSessions(String number) {
sessionStore.deleteAllSessions(number);
}
@Override
public SignedPreKeyRecord loadSignedPreKey(int signedPreKeyId) throws InvalidKeyIdException {
throw new UnsupportedOperationException("This method will be removed with refactor.");
// return signedPreKeyStore.loadSignedPreKey(signedPreKeyId);
}
@Override
public List<SignedPreKeyRecord> loadSignedPreKeys() {
throw new UnsupportedOperationException("This method will be removed with refactor.");
// return signedPreKeyStore.loadSignedPreKeys();
}
@Override
public void storeSignedPreKey(int signedPreKeyId, SignedPreKeyRecord record) {
throw new UnsupportedOperationException("This method will be removed with refactor.");
// signedPreKeyStore.storeSignedPreKey(signedPreKeyId, record);
}
@Override
public boolean containsSignedPreKey(int signedPreKeyId) {
throw new UnsupportedOperationException("This method will be removed with refactor.");
// return signedPreKeyStore.containsSignedPreKey(signedPreKeyId);
}
@Override
public void removeSignedPreKey(int signedPreKeyId) {
throw new UnsupportedOperationException("This method will be removed with refactor.");
// signedPreKeyStore.removeSignedPreKey(signedPreKeyId);
}
}

View File

@@ -1,110 +0,0 @@
package org.thoughtcrime.securesms.crypto.storage;
import android.content.Context;
import androidx.annotation.NonNull;
import org.session.libsession.messaging.threads.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.SessionDatabase;
import org.session.libsignal.utilities.logging.Log;
import org.session.libsignal.libsignal.SignalProtocolAddress;
import org.session.libsignal.libsignal.protocol.CiphertextMessage;
import org.session.libsignal.libsignal.state.SessionRecord;
import org.session.libsignal.libsignal.state.SessionStore;
import java.util.List;
public class TextSecureSessionStore implements SessionStore {
private static final String TAG = TextSecureSessionStore.class.getSimpleName();
private static final Object FILE_LOCK = new Object();
@NonNull private final Context context;
public TextSecureSessionStore(@NonNull Context context) {
this.context = context;
}
@Override
public SessionRecord loadSession(@NonNull SignalProtocolAddress address) {
synchronized (FILE_LOCK) {
SessionRecord sessionRecord = DatabaseFactory.getSessionDatabase(context).load(Address.fromSerialized(address.getName()), address.getDeviceId());
if (sessionRecord == null) {
Log.w(TAG, "No existing session information found.");
return new SessionRecord();
}
return sessionRecord;
}
}
@Override
public void storeSession(@NonNull SignalProtocolAddress address, @NonNull SessionRecord record) {
synchronized (FILE_LOCK) {
DatabaseFactory.getSessionDatabase(context).store(Address.fromSerialized(address.getName()), address.getDeviceId(), record);
}
}
@Override
public boolean containsSession(SignalProtocolAddress address) {
synchronized (FILE_LOCK) {
SessionRecord sessionRecord = DatabaseFactory.getSessionDatabase(context).load(Address.fromSerialized(address.getName()), address.getDeviceId());
return sessionRecord != null &&
sessionRecord.getSessionState().hasSenderChain() &&
sessionRecord.getSessionState().getSessionVersion() == CiphertextMessage.CURRENT_VERSION;
}
}
@Override
public void deleteSession(SignalProtocolAddress address) {
synchronized (FILE_LOCK) {
DatabaseFactory.getSessionDatabase(context).delete(Address.fromSerialized(address.getName()), address.getDeviceId());
}
}
@Override
public void deleteAllSessions(String name) {
synchronized (FILE_LOCK) {
DatabaseFactory.getSessionDatabase(context).deleteAllFor(Address.fromSerialized(name));
}
}
@Override
public List<Integer> getSubDeviceSessions(String name) {
synchronized (FILE_LOCK) {
return DatabaseFactory.getSessionDatabase(context).getSubDevices(Address.fromSerialized(name));
}
}
public void archiveSiblingSessions(@NonNull SignalProtocolAddress address) {
synchronized (FILE_LOCK) {
List<SessionDatabase.SessionRow> sessions = DatabaseFactory.getSessionDatabase(context).getAllFor(Address.fromSerialized(address.getName()));
for (SessionDatabase.SessionRow row : sessions) {
if (row.getDeviceId() != address.getDeviceId()) {
row.getRecord().archiveCurrentState();
storeSession(new SignalProtocolAddress(row.getAddress().serialize(), row.getDeviceId()), row.getRecord());
}
}
}
}
public void archiveAllSessions(@NonNull String hexEncodedPublicKey) {
SignalProtocolAddress address = new SignalProtocolAddress(hexEncodedPublicKey, -1);
archiveSiblingSessions(address);
}
public void archiveAllSessions() {
synchronized (FILE_LOCK) {
List<SessionDatabase.SessionRow> sessions = DatabaseFactory.getSessionDatabase(context).getAll();
for (SessionDatabase.SessionRow row : sessions) {
row.getRecord().archiveCurrentState();
storeSession(new SignalProtocolAddress(row.getAddress().serialize(), row.getDeviceId()), row.getRecord());
}
}
}
}

View File

@@ -53,9 +53,6 @@ public class DatabaseFactory {
private final GroupDatabase groupDatabase;
private final RecipientDatabase recipientDatabase;
private final GroupReceiptDatabase groupReceiptDatabase;
private final OneTimePreKeyDatabase preKeyDatabase;
private final SignedPreKeyDatabase signedPreKeyDatabase;
private final SessionDatabase sessionDatabase;
private final SearchDatabase searchDatabase;
private final JobDatabase jobDatabase;
private final StickerDatabase stickerDatabase;
@@ -125,18 +122,6 @@ public class DatabaseFactory {
return getInstance(context).groupReceiptDatabase;
}
public static OneTimePreKeyDatabase getPreKeyDatabase(Context context) {
return getInstance(context).preKeyDatabase;
}
public static SignedPreKeyDatabase getSignedPreKeyDatabase(Context context) {
return getInstance(context).signedPreKeyDatabase;
}
public static SessionDatabase getSessionDatabase(Context context) {
return getInstance(context).sessionDatabase;
}
public static SearchDatabase getSearchDatabase(Context context) {
return getInstance(context).searchDatabase;
}
@@ -212,9 +197,6 @@ public class DatabaseFactory {
this.groupDatabase = new GroupDatabase(context, databaseHelper);
this.recipientDatabase = new RecipientDatabase(context, databaseHelper);
this.groupReceiptDatabase = new GroupReceiptDatabase(context, databaseHelper);
this.preKeyDatabase = new OneTimePreKeyDatabase(context, databaseHelper);
this.signedPreKeyDatabase = new SignedPreKeyDatabase(context, databaseHelper);
this.sessionDatabase = new SessionDatabase(context, databaseHelper);
this.searchDatabase = new SearchDatabase(context, databaseHelper);
this.jobDatabase = new JobDatabase(context, databaseHelper);
this.stickerDatabase = new StickerDatabase(context, databaseHelper, attachmentSecret);

View File

@@ -1,81 +0,0 @@
package org.thoughtcrime.securesms.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import androidx.annotation.Nullable;
import org.session.libsignal.utilities.logging.Log;
import net.sqlcipher.database.SQLiteDatabase;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.session.libsignal.utilities.Base64;
import org.session.libsignal.libsignal.InvalidKeyException;
import org.session.libsignal.libsignal.ecc.Curve;
import org.session.libsignal.libsignal.ecc.ECKeyPair;
import org.session.libsignal.libsignal.ecc.ECPrivateKey;
import org.session.libsignal.libsignal.ecc.ECPublicKey;
import org.session.libsignal.libsignal.state.PreKeyRecord;
import java.io.IOException;
public class OneTimePreKeyDatabase extends Database {
private static final String TAG = OneTimePreKeyDatabase.class.getSimpleName();
public static final String TABLE_NAME = "one_time_prekeys";
private static final String ID = "_id";
public static final String KEY_ID = "key_id";
public static final String PUBLIC_KEY = "public_key";
public static final String PRIVATE_KEY = "private_key";
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME +
" (" + ID + " INTEGER PRIMARY KEY, " +
KEY_ID + " INTEGER UNIQUE, " +
PUBLIC_KEY + " TEXT NOT NULL, " +
PRIVATE_KEY + " TEXT NOT NULL);";
OneTimePreKeyDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
super(context, databaseHelper);
}
public @Nullable PreKeyRecord getPreKey(int keyId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
try (Cursor cursor = database.query(TABLE_NAME, null, KEY_ID + " = ?",
new String[] {String.valueOf(keyId)},
null, null, null))
{
if (cursor != null && cursor.moveToFirst()) {
try {
ECPublicKey publicKey = Curve.decodePoint(Base64.decode(cursor.getString(cursor.getColumnIndexOrThrow(PUBLIC_KEY))), 0);
ECPrivateKey privateKey = Curve.decodePrivatePoint(Base64.decode(cursor.getString(cursor.getColumnIndexOrThrow(PRIVATE_KEY))));
return new PreKeyRecord(keyId, new ECKeyPair(publicKey, privateKey));
} catch (InvalidKeyException | IOException e) {
Log.w(TAG, e);
}
}
}
return null;
}
public void insertPreKey(int keyId, PreKeyRecord record) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_ID, keyId);
contentValues.put(PUBLIC_KEY, Base64.encodeBytes(record.getKeyPair().getPublicKey().serialize()));
contentValues.put(PRIVATE_KEY, Base64.encodeBytes(record.getKeyPair().getPrivateKey().serialize()));
database.replace(TABLE_NAME, null, contentValues);
}
public void removePreKey(int keyId) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
database.delete(TABLE_NAME, KEY_ID + " = ?", new String[] {String.valueOf(keyId)});
}
}

View File

@@ -1,173 +0,0 @@
package org.thoughtcrime.securesms.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.sqlcipher.database.SQLiteDatabase;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.session.libsignal.utilities.logging.Log;
import org.session.libsession.messaging.threads.Address;
import org.session.libsignal.libsignal.state.SessionRecord;
import org.session.libsignal.service.api.push.SignalServiceAddress;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
public class SessionDatabase extends Database {
private static final String TAG = SessionDatabase.class.getSimpleName();
public static final String TABLE_NAME = "sessions";
private static final String ID = "_id";
public static final String ADDRESS = "address";
public static final String DEVICE = "device";
public static final String RECORD = "record";
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME +
"(" + ID + " INTEGER PRIMARY KEY, " + ADDRESS + " TEXT NOT NULL, " +
DEVICE + " INTEGER NOT NULL, " + RECORD + " BLOB NOT NULL, " +
"UNIQUE(" + ADDRESS + "," + DEVICE + ") ON CONFLICT REPLACE);";
SessionDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
super(context, databaseHelper);
}
public void store(@NonNull Address address, int deviceId, @NonNull SessionRecord record) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(ADDRESS, address.serialize());
values.put(DEVICE, deviceId);
values.put(RECORD, record.serialize());
database.insertWithOnConflict(TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
public @Nullable SessionRecord load(@NonNull Address address, int deviceId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
try (Cursor cursor = database.query(TABLE_NAME, new String[]{RECORD},
ADDRESS + " = ? AND " + DEVICE + " = ?",
new String[] {address.serialize(), String.valueOf(deviceId)},
null, null, null))
{
if (cursor != null && cursor.moveToFirst()) {
try {
return new SessionRecord(cursor.getBlob(cursor.getColumnIndexOrThrow(RECORD)));
} catch (IOException e) {
Log.w(TAG, e);
}
}
}
return null;
}
public @NonNull List<SessionRow> getAllFor(@NonNull Address address) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
List<SessionRow> results = new LinkedList<>();
try (Cursor cursor = database.query(TABLE_NAME, null,
ADDRESS + " = ?",
new String[] {address.serialize()},
null, null, null))
{
while (cursor != null && cursor.moveToNext()) {
try {
results.add(new SessionRow(address,
cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE)),
new SessionRecord(cursor.getBlob(cursor.getColumnIndexOrThrow(RECORD)))));
} catch (IOException e) {
Log.w(TAG, e);
}
}
}
return results;
}
public @NonNull List<SessionRow> getAll() {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
List<SessionRow> results = new LinkedList<>();
try (Cursor cursor = database.query(TABLE_NAME, null, null, null, null, null, null)) {
while (cursor != null && cursor.moveToNext()) {
try {
results.add(new SessionRow(Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS))),
cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE)),
new SessionRecord(cursor.getBlob(cursor.getColumnIndexOrThrow(RECORD)))));
} catch (IOException e) {
Log.w(TAG, e);
}
}
}
return results;
}
public @NonNull List<Integer> getSubDevices(@NonNull Address address) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
List<Integer> results = new LinkedList<>();
try (Cursor cursor = database.query(TABLE_NAME, new String[] {DEVICE},
ADDRESS + " = ?",
new String[] {address.serialize()},
null, null, null))
{
while (cursor != null && cursor.moveToNext()) {
int device = cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE));
if (device != SignalServiceAddress.DEFAULT_DEVICE_ID) {
results.add(device);
}
}
}
return results;
}
public void delete(@NonNull Address address, int deviceId) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
database.delete(TABLE_NAME, ADDRESS + " = ? AND " + DEVICE + " = ?",
new String[] {address.serialize(), String.valueOf(deviceId)});
}
public void deleteAllFor(@NonNull Address address) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
database.delete(TABLE_NAME, ADDRESS + " = ?", new String[] {address.serialize()});
}
public static final class SessionRow {
private final Address address;
private final int deviceId;
private final SessionRecord record;
public SessionRow(Address address, int deviceId, SessionRecord record) {
this.address = address;
this.deviceId = deviceId;
this.record = record;
}
public Address getAddress() {
return address;
}
public int getDeviceId() {
return deviceId;
}
public SessionRecord getRecord() {
return record;
}
}
}

View File

@@ -1,117 +0,0 @@
package org.thoughtcrime.securesms.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.sqlcipher.database.SQLiteDatabase;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.session.libsignal.utilities.logging.Log;
import org.session.libsignal.utilities.Base64;
import org.session.libsignal.libsignal.InvalidKeyException;
import org.session.libsignal.libsignal.ecc.Curve;
import org.session.libsignal.libsignal.ecc.ECKeyPair;
import org.session.libsignal.libsignal.ecc.ECPrivateKey;
import org.session.libsignal.libsignal.ecc.ECPublicKey;
import org.session.libsignal.libsignal.state.SignedPreKeyRecord;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
public class SignedPreKeyDatabase extends Database {
private static final String TAG = SignedPreKeyDatabase.class.getSimpleName();
public static final String TABLE_NAME = "signed_prekeys";
private static final String ID = "_id";
public static final String KEY_ID = "key_id";
public static final String PUBLIC_KEY = "public_key";
public static final String PRIVATE_KEY = "private_key";
public static final String SIGNATURE = "signature";
public static final String TIMESTAMP = "timestamp";
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME +
" (" + ID + " INTEGER PRIMARY KEY, " +
KEY_ID + " INTEGER UNIQUE, " +
PUBLIC_KEY + " TEXT NOT NULL, " +
PRIVATE_KEY + " TEXT NOT NULL, " +
SIGNATURE + " TEXT NOT NULL, " +
TIMESTAMP + " INTEGER DEFAULT 0);";
SignedPreKeyDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
super(context, databaseHelper);
}
public @Nullable SignedPreKeyRecord getSignedPreKey(int keyId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
try (Cursor cursor = database.query(TABLE_NAME, null, KEY_ID + " = ?",
new String[] {String.valueOf(keyId)},
null, null, null))
{
if (cursor != null && cursor.moveToFirst()) {
try {
ECPublicKey publicKey = Curve.decodePoint(Base64.decode(cursor.getString(cursor.getColumnIndexOrThrow(PUBLIC_KEY))), 0);
ECPrivateKey privateKey = Curve.decodePrivatePoint(Base64.decode(cursor.getString(cursor.getColumnIndexOrThrow(PRIVATE_KEY))));
byte[] signature = Base64.decode(cursor.getString(cursor.getColumnIndexOrThrow(SIGNATURE)));
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP));
return new SignedPreKeyRecord(keyId, timestamp, new ECKeyPair(publicKey, privateKey), signature);
} catch (InvalidKeyException | IOException e) {
Log.w(TAG, e);
}
}
}
return null;
}
public @NonNull List<SignedPreKeyRecord> getAllSignedPreKeys() {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
List<SignedPreKeyRecord> results = new LinkedList<>();
try (Cursor cursor = database.query(TABLE_NAME, null, null, null, null, null, null)) {
while (cursor != null && cursor.moveToNext()) {
try {
int keyId = cursor.getInt(cursor.getColumnIndexOrThrow(KEY_ID));
ECPublicKey publicKey = Curve.decodePoint(Base64.decode(cursor.getString(cursor.getColumnIndexOrThrow(PUBLIC_KEY))), 0);
ECPrivateKey privateKey = Curve.decodePrivatePoint(Base64.decode(cursor.getString(cursor.getColumnIndexOrThrow(PRIVATE_KEY))));
byte[] signature = Base64.decode(cursor.getString(cursor.getColumnIndexOrThrow(SIGNATURE)));
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP));
results.add(new SignedPreKeyRecord(keyId, timestamp, new ECKeyPair(publicKey, privateKey), signature));
} catch (InvalidKeyException | IOException e) {
Log.w(TAG, e);
}
}
}
return results;
}
public void insertSignedPreKey(int keyId, SignedPreKeyRecord record) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_ID, keyId);
contentValues.put(PUBLIC_KEY, Base64.encodeBytes(record.getKeyPair().getPublicKey().serialize()));
contentValues.put(PRIVATE_KEY, Base64.encodeBytes(record.getKeyPair().getPrivateKey().serialize()));
contentValues.put(SIGNATURE, Base64.encodeBytes(record.getSignature()));
contentValues.put(TIMESTAMP, record.getTimestamp());
database.replace(TABLE_NAME, null, contentValues);
}
public void removeSignedPreKey(int keyId) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
database.delete(TABLE_NAME, KEY_ID + " = ? AND " + SIGNATURE + " IS NOT NULL", new String[] {String.valueOf(keyId)});
}
}

View File

@@ -17,12 +17,9 @@ import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.GroupReceiptDatabase;
import org.thoughtcrime.securesms.database.JobDatabase;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.OneTimePreKeyDatabase;
import org.thoughtcrime.securesms.database.PushDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.SearchDatabase;
import org.thoughtcrime.securesms.database.SessionDatabase;
import org.thoughtcrime.securesms.database.SignedPreKeyDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.StickerDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
@@ -94,9 +91,6 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
db.execSQL(GroupDatabase.CREATE_TABLE);
db.execSQL(RecipientDatabase.CREATE_TABLE);
db.execSQL(GroupReceiptDatabase.CREATE_TABLE);
db.execSQL(OneTimePreKeyDatabase.CREATE_TABLE);
db.execSQL(SignedPreKeyDatabase.CREATE_TABLE);
db.execSQL(SessionDatabase.CREATE_TABLE);
for (String sql : SearchDatabase.CREATE_TABLE) {
db.execSQL(sql);
}

View File

@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.dependencies;
import android.content.Context;
import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.SignalServiceAccountManager;
import org.session.libsignal.service.api.SignalServiceMessageReceiver;
import org.session.libsignal.service.api.SignalServiceMessageSender;
import org.session.libsignal.service.api.util.CredentialsProvider;
@@ -74,7 +73,6 @@ public class SignalCommunicationModule {
private final Context context;
private final SignalServiceNetworkAccess networkAccess;
private SignalServiceAccountManager accountManager;
private SignalServiceMessageSender messageSender;
private SignalServiceMessageReceiver messageReceiver;

View File

@@ -15,7 +15,6 @@ import com.annimon.stream.Collectors;
import com.annimon.stream.Stream;
import org.session.libsession.messaging.jobs.Data;
import org.session.libsession.utilities.MediaTypes;
import org.session.libsignal.metadata.InvalidMetadataMessageException;
import org.session.libsignal.metadata.ProtocolInvalidMessageException;
import org.session.libsignal.service.api.crypto.SignalServiceCipher;
@@ -37,7 +36,6 @@ import org.session.libsession.utilities.TextSecurePreferences;
import org.thoughtcrime.securesms.contactshare.ContactModelMapper;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
@@ -47,11 +45,9 @@ import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.PushDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.StickerDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.database.model.StickerRecord;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.groups.GroupMessageProcessor;
import org.thoughtcrime.securesms.jobmanager.Job;
@@ -70,15 +66,11 @@ import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.mms.StickerSlide;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage;
import org.thoughtcrime.securesms.sms.IncomingEndSessionMessage;
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.session.libsignal.utilities.Hex;
import org.session.libsignal.libsignal.InvalidMessageException;
import org.session.libsignal.libsignal.state.SignalProtocolStore;
import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.SignalServiceMessageSender;
import org.session.libsignal.service.api.messages.SignalServiceContent;
@@ -89,11 +81,9 @@ import org.session.libsignal.service.api.messages.SignalServiceGroup;
import org.session.libsignal.service.api.messages.SignalServiceReceiptMessage;
import org.session.libsignal.service.api.messages.SignalServiceTypingMessage;
import org.session.libsignal.service.api.messages.shared.SharedContact;
import org.session.libsignal.service.api.push.SignalServiceAddress;
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager;
import org.session.libsignal.service.loki.utilities.PublicKeyValidation;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;

View File

@@ -290,7 +290,6 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
.asExpirationUpdate(message.isExpirationUpdate())
.withProfileKey(profileKey.orNull())
.withQuote(quote.orNull())
.withSticker(sticker.orNull())
.withSharedContacts(sharedContacts)
.withPreviews(previews);
}

View File

@@ -263,7 +263,6 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
.withExpiration((int)(message.getExpiresIn() / 1000))
.withProfileKey(profileKey.orNull())
.withQuote(quote.orNull())
.withSticker(sticker.orNull())
.withSharedContacts(sharedContacts)
.withPreviews(previews)
.asExpirationUpdate(message.isExpirationUpdate())
@@ -277,7 +276,6 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
.withExpiration((int)(message.getExpiresIn() / 1000))
.withProfileKey(profileKey.orNull())
.withQuote(quote.orNull())
.withSticker(sticker.orNull())
.withSharedContacts(sharedContacts)
.withPreviews(previews)
.asExpirationUpdate(message.isExpirationUpdate())

View File

@@ -210,7 +210,6 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
.withBody(message.getBody())
.withExpiration((int)(message.getExpiresIn() / 1000))
.withProfileKey(profileKey.orNull())
.asEndSessionMessage(message.isEndSession())
.build();
SignalServiceDataMessage textSecureSelfSendMessage = SignalServiceDataMessage.newBuilder()
@@ -219,7 +218,6 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
.withSyncTarget(destination.serialize())
.withExpiration((int)(message.getExpiresIn() / 1000))
.withProfileKey(profileKey.orNull())
.asEndSessionMessage(message.isEndSession())
.build();
if (userPublicKey.equals(address.getNumber())) {