mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-22 12:08:34 +00:00
Use RemoteConfig for UsePqRatchet.
Co-authored-by: Greyson Parrelli <greyson@signal.org>
This commit is contained in:
committed by
Greyson Parrelli
parent
f6b74ad2a0
commit
173983a1ab
@@ -6,6 +6,7 @@ import org.signal.libsignal.protocol.IdentityKey
|
|||||||
import org.signal.libsignal.protocol.IdentityKeyPair
|
import org.signal.libsignal.protocol.IdentityKeyPair
|
||||||
import org.signal.libsignal.protocol.SessionBuilder
|
import org.signal.libsignal.protocol.SessionBuilder
|
||||||
import org.signal.libsignal.protocol.SignalProtocolAddress
|
import org.signal.libsignal.protocol.SignalProtocolAddress
|
||||||
|
import org.signal.libsignal.protocol.UsePqRatchet
|
||||||
import org.signal.libsignal.protocol.ecc.ECKeyPair
|
import org.signal.libsignal.protocol.ecc.ECKeyPair
|
||||||
import org.signal.libsignal.protocol.groups.state.SenderKeyRecord
|
import org.signal.libsignal.protocol.groups.state.SenderKeyRecord
|
||||||
import org.signal.libsignal.protocol.state.IdentityKeyStore
|
import org.signal.libsignal.protocol.state.IdentityKeyStore
|
||||||
@@ -68,7 +69,7 @@ class BobClient(val serviceId: ServiceId, val e164: String, val identityKeyPair:
|
|||||||
|
|
||||||
if (!aciStore.containsSession(getAliceProtocolAddress())) {
|
if (!aciStore.containsSession(getAliceProtocolAddress())) {
|
||||||
val sessionBuilder = SignalSessionBuilder(sessionLock, SessionBuilder(aciStore, getAliceProtocolAddress()))
|
val sessionBuilder = SignalSessionBuilder(sessionLock, SessionBuilder(aciStore, getAliceProtocolAddress()))
|
||||||
sessionBuilder.process(getAlicePreKeyBundle())
|
sessionBuilder.process(getAlicePreKeyBundle(), UsePqRatchet.NO)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cipher.encrypt(getAliceProtocolAddress(), getAliceUnidentifiedAccess(), envelopeContent)
|
return cipher.encrypt(getAliceProtocolAddress(), getAliceUnidentifiedAccess(), envelopeContent)
|
||||||
@@ -77,7 +78,7 @@ class BobClient(val serviceId: ServiceId, val e164: String, val identityKeyPair:
|
|||||||
|
|
||||||
fun decrypt(envelope: Envelope, serverDeliveredTimestamp: Long) {
|
fun decrypt(envelope: Envelope, serverDeliveredTimestamp: Long) {
|
||||||
val cipher = SignalServiceCipher(serviceAddress, 1, aciStore, sessionLock, SealedSenderAccessUtil.getCertificateValidator())
|
val cipher = SignalServiceCipher(serviceAddress, 1, aciStore, sessionLock, SealedSenderAccessUtil.getCertificateValidator())
|
||||||
cipher.decrypt(envelope, serverDeliveredTimestamp)
|
cipher.decrypt(envelope, serverDeliveredTimestamp, UsePqRatchet.NO)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAliceServiceId(): ServiceId {
|
private fun getAliceServiceId(): ServiceId {
|
||||||
|
|||||||
@@ -170,7 +170,8 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
|
|||||||
Optional.of(new SecurityEventListener(context)),
|
Optional.of(new SecurityEventListener(context)),
|
||||||
SignalExecutors.newCachedBoundedExecutor("signal-messages", ThreadUtil.PRIORITY_IMPORTANT_BACKGROUND_THREAD, 1, 16, 30),
|
SignalExecutors.newCachedBoundedExecutor("signal-messages", ThreadUtil.PRIORITY_IMPORTANT_BACKGROUND_THREAD, 1, 16, 30),
|
||||||
ByteUnit.KILOBYTES.toBytes(256),
|
ByteUnit.KILOBYTES.toBytes(256),
|
||||||
RemoteConfig::useMessageSendRestFallback);
|
RemoteConfig::useMessageSendRestFallback,
|
||||||
|
RemoteConfig.usePqRatchet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ object MessageDecryptor {
|
|||||||
|
|
||||||
return try {
|
return try {
|
||||||
val startTimeNanos = System.nanoTime()
|
val startTimeNanos = System.nanoTime()
|
||||||
val cipherResult: SignalServiceCipherResult? = cipher.decrypt(envelope, serverDeliveredTimestamp)
|
val cipherResult: SignalServiceCipherResult? = cipher.decrypt(envelope, serverDeliveredTimestamp, RemoteConfig.usePqRatchet)
|
||||||
val endTimeNanos = System.nanoTime()
|
val endTimeNanos = System.nanoTime()
|
||||||
|
|
||||||
if (cipherResult == null) {
|
if (cipherResult == null) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import org.signal.core.util.gibiBytes
|
|||||||
import org.signal.core.util.kibiBytes
|
import org.signal.core.util.kibiBytes
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
import org.signal.core.util.mebiBytes
|
import org.signal.core.util.mebiBytes
|
||||||
|
import org.signal.libsignal.protocol.UsePqRatchet
|
||||||
import org.thoughtcrime.securesms.BuildConfig
|
import org.thoughtcrime.securesms.BuildConfig
|
||||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||||
import org.thoughtcrime.securesms.groups.SelectionLimits
|
import org.thoughtcrime.securesms.groups.SelectionLimits
|
||||||
@@ -1154,5 +1155,15 @@ object RemoteConfig {
|
|||||||
durationUnit = DurationUnit.DAYS
|
durationUnit = DurationUnit.DAYS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/** Whether or not to use the new post-quantum ratcheting. */
|
||||||
|
@JvmStatic
|
||||||
|
@get:JvmName("usePqRatchet")
|
||||||
|
val usePqRatchet: UsePqRatchet by remoteValue(
|
||||||
|
key = "global.usePqRatchet",
|
||||||
|
hotSwappable = true
|
||||||
|
) { value ->
|
||||||
|
if (value.asBoolean(false)) UsePqRatchet.YES else UsePqRatchet.NO
|
||||||
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.signal.libsignal.protocol.InvalidRegistrationIdException;
|
|||||||
import org.signal.libsignal.protocol.NoSessionException;
|
import org.signal.libsignal.protocol.NoSessionException;
|
||||||
import org.signal.libsignal.protocol.SessionBuilder;
|
import org.signal.libsignal.protocol.SessionBuilder;
|
||||||
import org.signal.libsignal.protocol.SignalProtocolAddress;
|
import org.signal.libsignal.protocol.SignalProtocolAddress;
|
||||||
|
import org.signal.libsignal.protocol.UsePqRatchet;
|
||||||
import org.signal.libsignal.protocol.groups.GroupSessionBuilder;
|
import org.signal.libsignal.protocol.groups.GroupSessionBuilder;
|
||||||
import org.signal.libsignal.protocol.logging.Log;
|
import org.signal.libsignal.protocol.logging.Log;
|
||||||
import org.signal.libsignal.protocol.message.DecryptionErrorMessage;
|
import org.signal.libsignal.protocol.message.DecryptionErrorMessage;
|
||||||
@@ -182,6 +183,7 @@ public class SignalServiceMessageSender {
|
|||||||
private final Scheduler scheduler;
|
private final Scheduler scheduler;
|
||||||
private final long maxEnvelopeSize;
|
private final long maxEnvelopeSize;
|
||||||
private final BooleanSupplier useRestFallback;
|
private final BooleanSupplier useRestFallback;
|
||||||
|
private final UsePqRatchet usePqRatchet;
|
||||||
|
|
||||||
public SignalServiceMessageSender(PushServiceSocket pushServiceSocket,
|
public SignalServiceMessageSender(PushServiceSocket pushServiceSocket,
|
||||||
SignalServiceDataStore store,
|
SignalServiceDataStore store,
|
||||||
@@ -192,7 +194,8 @@ public class SignalServiceMessageSender {
|
|||||||
Optional<EventListener> eventListener,
|
Optional<EventListener> eventListener,
|
||||||
ExecutorService executor,
|
ExecutorService executor,
|
||||||
long maxEnvelopeSize,
|
long maxEnvelopeSize,
|
||||||
BooleanSupplier useRestFallback)
|
BooleanSupplier useRestFallback,
|
||||||
|
UsePqRatchet usePqRatchet)
|
||||||
{
|
{
|
||||||
CredentialsProvider credentialsProvider = pushServiceSocket.getCredentialsProvider();
|
CredentialsProvider credentialsProvider = pushServiceSocket.getCredentialsProvider();
|
||||||
|
|
||||||
@@ -210,6 +213,7 @@ public class SignalServiceMessageSender {
|
|||||||
this.scheduler = Schedulers.from(executor, false, false);
|
this.scheduler = Schedulers.from(executor, false, false);
|
||||||
this.keysApi = keysApi;
|
this.keysApi = keysApi;
|
||||||
this.useRestFallback = useRestFallback;
|
this.useRestFallback = useRestFallback;
|
||||||
|
this.usePqRatchet = usePqRatchet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2701,7 +2705,7 @@ public class SignalServiceMessageSender {
|
|||||||
try {
|
try {
|
||||||
SignalProtocolAddress preKeyAddress = new SignalProtocolAddress(recipient.getIdentifier(), preKey.getDeviceId());
|
SignalProtocolAddress preKeyAddress = new SignalProtocolAddress(recipient.getIdentifier(), preKey.getDeviceId());
|
||||||
SignalSessionBuilder sessionBuilder = new SignalSessionBuilder(sessionLock, new SessionBuilder(aciStore, preKeyAddress));
|
SignalSessionBuilder sessionBuilder = new SignalSessionBuilder(sessionLock, new SessionBuilder(aciStore, preKeyAddress));
|
||||||
sessionBuilder.process(preKey);
|
sessionBuilder.process(preKey, usePqRatchet);
|
||||||
} catch (org.signal.libsignal.protocol.UntrustedIdentityException e) {
|
} catch (org.signal.libsignal.protocol.UntrustedIdentityException e) {
|
||||||
throw new UntrustedIdentityException("Untrusted identity key!", recipient.getIdentifier(), preKey.getIdentityKey());
|
throw new UntrustedIdentityException("Untrusted identity key!", recipient.getIdentifier(), preKey.getIdentityKey());
|
||||||
}
|
}
|
||||||
@@ -2753,7 +2757,7 @@ public class SignalServiceMessageSender {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
SignalSessionBuilder sessionBuilder = new SignalSessionBuilder(sessionLock, new SessionBuilder(aciStore, new SignalProtocolAddress(recipient.getIdentifier(), missingDeviceId)));
|
SignalSessionBuilder sessionBuilder = new SignalSessionBuilder(sessionLock, new SessionBuilder(aciStore, new SignalProtocolAddress(recipient.getIdentifier(), missingDeviceId)));
|
||||||
sessionBuilder.process(preKey);
|
sessionBuilder.process(preKey, usePqRatchet);
|
||||||
} catch (org.signal.libsignal.protocol.UntrustedIdentityException e) {
|
} catch (org.signal.libsignal.protocol.UntrustedIdentityException e) {
|
||||||
throw new UntrustedIdentityException("Untrusted identity key!", recipient.getIdentifier(), preKey.getIdentityKey());
|
throw new UntrustedIdentityException("Untrusted identity key!", recipient.getIdentifier(), preKey.getIdentityKey());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.signal.libsignal.protocol.NoSessionException;
|
|||||||
import org.signal.libsignal.protocol.SessionCipher;
|
import org.signal.libsignal.protocol.SessionCipher;
|
||||||
import org.signal.libsignal.protocol.SignalProtocolAddress;
|
import org.signal.libsignal.protocol.SignalProtocolAddress;
|
||||||
import org.signal.libsignal.protocol.UntrustedIdentityException;
|
import org.signal.libsignal.protocol.UntrustedIdentityException;
|
||||||
|
import org.signal.libsignal.protocol.UsePqRatchet;
|
||||||
import org.signal.libsignal.protocol.groups.GroupCipher;
|
import org.signal.libsignal.protocol.groups.GroupCipher;
|
||||||
import org.signal.libsignal.protocol.logging.Log;
|
import org.signal.libsignal.protocol.logging.Log;
|
||||||
import org.signal.libsignal.protocol.message.CiphertextMessage;
|
import org.signal.libsignal.protocol.message.CiphertextMessage;
|
||||||
@@ -131,7 +132,7 @@ public class SignalServiceCipher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignalServiceCipherResult decrypt(Envelope envelope, long serverDeliveredTimestamp)
|
public SignalServiceCipherResult decrypt(Envelope envelope, long serverDeliveredTimestamp, UsePqRatchet usePqRatchet)
|
||||||
throws InvalidMetadataMessageException, InvalidMetadataVersionException,
|
throws InvalidMetadataMessageException, InvalidMetadataVersionException,
|
||||||
ProtocolInvalidKeyIdException, ProtocolLegacyMessageException,
|
ProtocolInvalidKeyIdException, ProtocolLegacyMessageException,
|
||||||
ProtocolUntrustedIdentityException, ProtocolNoSessionException,
|
ProtocolUntrustedIdentityException, ProtocolNoSessionException,
|
||||||
@@ -141,7 +142,7 @@ public class SignalServiceCipher {
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (envelope.content != null) {
|
if (envelope.content != null) {
|
||||||
Plaintext plaintext = decryptInternal(envelope, serverDeliveredTimestamp);
|
Plaintext plaintext = decryptInternal(envelope, serverDeliveredTimestamp, usePqRatchet);
|
||||||
Content content = Content.ADAPTER.decode(plaintext.getData());
|
Content content = Content.ADAPTER.decode(plaintext.getData());
|
||||||
|
|
||||||
return new SignalServiceCipherResult(
|
return new SignalServiceCipherResult(
|
||||||
@@ -163,7 +164,7 @@ public class SignalServiceCipher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Plaintext decryptInternal(Envelope envelope, long serverDeliveredTimestamp)
|
private Plaintext decryptInternal(Envelope envelope, long serverDeliveredTimestamp, UsePqRatchet usePqRatchet)
|
||||||
throws InvalidMetadataMessageException, InvalidMetadataVersionException,
|
throws InvalidMetadataMessageException, InvalidMetadataVersionException,
|
||||||
ProtocolDuplicateMessageException, ProtocolUntrustedIdentityException,
|
ProtocolDuplicateMessageException, ProtocolUntrustedIdentityException,
|
||||||
ProtocolLegacyMessageException, ProtocolInvalidKeyException,
|
ProtocolLegacyMessageException, ProtocolInvalidKeyException,
|
||||||
@@ -184,7 +185,7 @@ public class SignalServiceCipher {
|
|||||||
SignalProtocolAddress sourceAddress = new SignalProtocolAddress(envelope.sourceServiceId, envelope.sourceDevice);
|
SignalProtocolAddress sourceAddress = new SignalProtocolAddress(envelope.sourceServiceId, envelope.sourceDevice);
|
||||||
SignalSessionCipher sessionCipher = new SignalSessionCipher(sessionLock, new SessionCipher(signalProtocolStore, sourceAddress));
|
SignalSessionCipher sessionCipher = new SignalSessionCipher(sessionLock, new SessionCipher(signalProtocolStore, sourceAddress));
|
||||||
|
|
||||||
paddedMessage = sessionCipher.decrypt(new PreKeySignalMessage(envelope.content.toByteArray()));
|
paddedMessage = sessionCipher.decrypt(new PreKeySignalMessage(envelope.content.toByteArray()), usePqRatchet);
|
||||||
metadata = new SignalServiceMetadata(getSourceAddress(envelope), envelope.sourceDevice, envelope.timestamp, envelope.serverTimestamp, serverDeliveredTimestamp, false, envelope.serverGuid, Optional.empty(), envelope.destinationServiceId);
|
metadata = new SignalServiceMetadata(getSourceAddress(envelope), envelope.sourceDevice, envelope.timestamp, envelope.serverTimestamp, serverDeliveredTimestamp, false, envelope.serverGuid, Optional.empty(), envelope.destinationServiceId);
|
||||||
|
|
||||||
signalProtocolStore.clearSenderKeySharedWith(Collections.singleton(sourceAddress));
|
signalProtocolStore.clearSenderKeySharedWith(Collections.singleton(sourceAddress));
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ public class SignalSessionBuilder {
|
|||||||
this.builder = builder;
|
this.builder = builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(PreKeyBundle preKey) throws InvalidKeyException, UntrustedIdentityException {
|
public void process(PreKeyBundle preKey, UsePqRatchet usePqRatchet) throws InvalidKeyException, UntrustedIdentityException {
|
||||||
try (SignalSessionLock.Lock unused = lock.acquire()) {
|
try (SignalSessionLock.Lock unused = lock.acquire()) {
|
||||||
builder.process(preKey, UsePqRatchet.NO);
|
builder.process(preKey, usePqRatchet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ public class SignalSessionCipher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] decrypt(PreKeySignalMessage ciphertext) throws DuplicateMessageException, LegacyMessageException, InvalidMessageException, InvalidKeyIdException, InvalidKeyException, org.signal.libsignal.protocol.UntrustedIdentityException {
|
public byte[] decrypt(PreKeySignalMessage ciphertext, UsePqRatchet usePqRatchet) throws DuplicateMessageException, LegacyMessageException, InvalidMessageException, InvalidKeyIdException, InvalidKeyException, org.signal.libsignal.protocol.UntrustedIdentityException {
|
||||||
try (SignalSessionLock.Lock unused = lock.acquire()) {
|
try (SignalSessionLock.Lock unused = lock.acquire()) {
|
||||||
return cipher.decrypt(ciphertext, UsePqRatchet.NO);
|
return cipher.decrypt(ciphertext, usePqRatchet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ class SignalClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun decryptMessage(envelope: Envelope) {
|
fun decryptMessage(envelope: Envelope) {
|
||||||
cipher.decrypt(envelope, System.currentTimeMillis())
|
cipher.decrypt(envelope, System.currentTimeMillis(), UsePqRatchet.NO)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createPreKeyBundle(): PreKeyBundle {
|
private fun createPreKeyBundle(): PreKeyBundle {
|
||||||
|
|||||||
Reference in New Issue
Block a user