Add the ability to have separate ACI and PNI protocol stores.

This commit is contained in:
Greyson Parrelli
2022-01-26 16:22:19 -05:00
committed by Cody Henthorne
parent dd7a2834bc
commit 33f4bb0000
33 changed files with 204 additions and 188 deletions

View File

@@ -44,7 +44,7 @@ public class PreKeyUtil {
private static final int BATCH_SIZE = 100;
public synchronized static List<PreKeyRecord> generatePreKeys(Context context) {
PreKeyStore preKeyStore = ApplicationDependencies.getPreKeyStore();
PreKeyStore preKeyStore = ApplicationDependencies.getProtocolStore().aci();
List<PreKeyRecord> records = new LinkedList<>();
int preKeyIdOffset = TextSecurePreferences.getNextPreKeyId(context);
@@ -64,7 +64,7 @@ public class PreKeyUtil {
public synchronized static SignedPreKeyRecord generateSignedPreKey(Context context, IdentityKeyPair identityKeyPair, boolean active) {
try {
SignedPreKeyStore signedPreKeyStore = ApplicationDependencies.getPreKeyStore();
SignedPreKeyStore signedPreKeyStore = ApplicationDependencies.getProtocolStore().aci();
int signedPreKeyId = TextSecurePreferences.getNextSignedPreKeyId(context);
ECKeyPair keyPair = Curve.generateKeyPair();
byte[] signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());

View File

@@ -22,7 +22,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().requireServiceId(), distributionId);
ApplicationDependencies.getProtocolStore().aci().senderKeys().deleteAllFor(Recipient.self().requireServiceId(), distributionId);
SignalDatabase.senderKeyShared().deleteAllFor(distributionId);
}
}
@@ -40,7 +40,7 @@ public final class SenderKeyUtil {
*/
public static void clearAllState(@NonNull Context context) {
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
ApplicationDependencies.getSenderKeyStore().deleteAll();
ApplicationDependencies.getProtocolStore().aci().senderKeys().deleteAll();
SignalDatabase.senderKeyShared().deleteAll();
}
}

View File

@@ -15,24 +15,24 @@ public class SessionUtil {
public static boolean hasSession(@NonNull RecipientId id) {
SignalProtocolAddress axolotlAddress = new SignalProtocolAddress(Recipient.resolved(id).requireServiceId(), SignalServiceAddress.DEFAULT_DEVICE_ID);
return ApplicationDependencies.getSessionStore().containsSession(axolotlAddress);
return ApplicationDependencies.getProtocolStore().aci().containsSession(axolotlAddress);
}
public static void archiveSiblingSessions(SignalProtocolAddress address) {
ApplicationDependencies.getSessionStore().archiveSiblingSessions(address);
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSiblingSessions(address);
}
public static void archiveAllSessions() {
ApplicationDependencies.getSessionStore().archiveAllSessions();
ApplicationDependencies.getProtocolStore().aci().sessions().archiveAllSessions();
}
public static void archiveSession(RecipientId recipientId, int deviceId) {
ApplicationDependencies.getSessionStore().archiveSession(recipientId, deviceId);
ApplicationDependencies.getProtocolStore().aci().sessions().archiveSession(recipientId, deviceId);
}
public static boolean ratchetKeyMatches(@NonNull Recipient recipient, int deviceId, @NonNull ECPublicKey ratchetKey) {
SignalProtocolAddress address = new SignalProtocolAddress(recipient.resolve().requireServiceId(), deviceId);
SessionRecord session = ApplicationDependencies.getSessionStore().loadSession(address);
SessionRecord session = ApplicationDependencies.getProtocolStore().aci().loadSession(address);
return session.currentRatchetKeyMatches(ratchetKey);
}

View File

@@ -2,9 +2,9 @@ package org.thoughtcrime.securesms.crypto.storage;
import android.content.Context;
import org.thoughtcrime.securesms.database.SignalDatabase;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.IdentityKeyPair;
@@ -12,14 +12,10 @@ import org.whispersystems.libsignal.InvalidKeyIdException;
import org.whispersystems.libsignal.NoSessionException;
import org.whispersystems.libsignal.SignalProtocolAddress;
import org.whispersystems.libsignal.groups.state.SenderKeyRecord;
import org.whispersystems.libsignal.state.IdentityKeyStore;
import org.whispersystems.libsignal.state.PreKeyRecord;
import org.whispersystems.libsignal.state.PreKeyStore;
import org.whispersystems.libsignal.state.SessionRecord;
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
import org.whispersystems.libsignal.state.SignedPreKeyStore;
import org.whispersystems.signalservice.api.SignalServiceDataStore;
import org.whispersystems.signalservice.api.SignalServiceSessionStore;
import org.whispersystems.signalservice.api.SignalServiceAccountDataStore;
import org.whispersystems.signalservice.api.push.DistributionId;
import java.util.Collection;
@@ -27,22 +23,32 @@ import java.util.List;
import java.util.Set;
import java.util.UUID;
public class SignalProtocolStoreImpl implements SignalServiceDataStore {
public class SignalServiceAccountDataStoreImpl implements SignalServiceAccountDataStore {
private final Context context;
private final PreKeyStore preKeyStore;
private final SignedPreKeyStore signedPreKeyStore;
private final IdentityKeyStore identityKeyStore;
private final SignalServiceSessionStore sessionStore;
private final SignalSenderKeyStore senderKeyStore;
private final Context context;
private final TextSecurePreKeyStore preKeyStore;
private final TextSecurePreKeyStore signedPreKeyStore;
private final TextSecureIdentityKeyStore identityKeyStore;
private final TextSecureSessionStore sessionStore;
private final SignalSenderKeyStore senderKeyStore;
public SignalProtocolStoreImpl(Context context) {
public SignalServiceAccountDataStoreImpl(@NonNull Context context,
@NonNull TextSecurePreKeyStore preKeyStore,
@NonNull TextSecureIdentityKeyStore identityKeyStore,
@NonNull TextSecureSessionStore sessionStore,
@NonNull SignalSenderKeyStore senderKeyStore)
{
this.context = context;
this.preKeyStore = ApplicationDependencies.getPreKeyStore();
this.signedPreKeyStore = ApplicationDependencies.getPreKeyStore();
this.identityKeyStore = ApplicationDependencies.getIdentityStore();
this.sessionStore = ApplicationDependencies.getSessionStore();
this.senderKeyStore = ApplicationDependencies.getSenderKeyStore();
this.preKeyStore = preKeyStore;
this.signedPreKeyStore = preKeyStore;
this.identityKeyStore = identityKeyStore;
this.sessionStore = sessionStore;
this.senderKeyStore = senderKeyStore;
}
@Override
public boolean isMultiDevice() {
return TextSecurePreferences.isMultiDevice(context);
}
@Override
@@ -185,17 +191,20 @@ public class SignalProtocolStoreImpl implements SignalServiceDataStore {
senderKeyStore.clearSenderKeySharedWith(addresses);
}
@Override
public boolean isMultiDevice() {
return TextSecurePreferences.isMultiDevice(context);
public @NonNull TextSecureIdentityKeyStore identities() {
return identityKeyStore;
}
@Override
public Transaction beginTransaction() {
SignalDatabase.getRawDatabase().beginTransaction();
return () -> {
SignalDatabase.getRawDatabase().setTransactionSuccessful();
SignalDatabase.getRawDatabase().endTransaction();
};
public @NonNull TextSecurePreKeyStore preKeys() {
return preKeyStore;
}
public @NonNull TextSecureSessionStore sessions() {
return sessionStore;
}
public @NonNull SignalSenderKeyStore senderKeys() {
return senderKeyStore;
}
}

View File

@@ -0,0 +1,52 @@
package org.thoughtcrime.securesms.crypto.storage;
import android.content.Context;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.SignalServiceDataStore;
import org.whispersystems.signalservice.api.push.AccountIdentifier;
public final class SignalServiceDataStoreImpl implements SignalServiceDataStore {
private final Context context;
private final SignalServiceAccountDataStoreImpl aciStore;
private final SignalServiceAccountDataStoreImpl pniStore;
public SignalServiceDataStoreImpl(@NonNull Context context,
@NonNull SignalServiceAccountDataStoreImpl aciStore,
@NonNull SignalServiceAccountDataStoreImpl pniStore)
{
this.context = context;
this.aciStore = aciStore;
this.pniStore = pniStore;
}
@Override
public SignalServiceAccountDataStoreImpl get(@NonNull AccountIdentifier accountIdentifier) {
if (accountIdentifier.equals(SignalStore.account().getAci())) {
return aciStore;
} else if (accountIdentifier.equals(SignalStore.account().getPni())) {
return pniStore;
} else {
throw new IllegalArgumentException("No matching store found for " + accountIdentifier);
}
}
@Override
public SignalServiceAccountDataStoreImpl aci() {
return aciStore;
}
@Override
public SignalServiceAccountDataStoreImpl pni() {
return pniStore;
}
@Override
public boolean isMultiDevice() {
return TextSecurePreferences.isMultiDevice(context);
}
}