Update libsignal-service

This commit is contained in:
AsamK 2026-05-23 18:46:39 +02:00
parent 44d54b3215
commit ced9560040
17 changed files with 90 additions and 23 deletions

View File

@ -3,7 +3,7 @@ slf4j = "2.0.18"
junit = "6.0.3"
micronaut-json-schema = "2.0.0"
micronaut-core = "5.0.0"
signal-service = "2.15.3_unofficial_146"
signal-service = "2.15.3_unofficial_147"
[libraries]
bouncycastle = "org.bouncycastle:bcprov-jdk18on:1.84"

View File

@ -4,7 +4,6 @@ import org.asamk.signal.manager.groups.GroupUtils;
import org.asamk.signal.manager.helper.RecipientAddressResolver;
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
import org.asamk.signal.manager.util.MimeUtils;
import org.signal.core.models.ServiceId;
import org.signal.libsignal.metadata.ProtocolException;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;

View File

@ -25,6 +25,7 @@ import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
import org.signal.libsignal.protocol.util.KeyHelper;
import org.signal.libsignal.usernames.BaseUsernameException;
import org.signal.libsignal.usernames.Username;
import org.signal.network.exceptions.NonSuccessfulResponseCodeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.account.ChangePhoneNumberRequest;
@ -37,7 +38,6 @@ import org.whispersystems.signalservice.api.push.UsernameLinkComponents;
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException;
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.signalservice.api.util.DeviceNameUtil;
import org.whispersystems.signalservice.internal.push.DeviceLimitExceededException;
import org.whispersystems.signalservice.internal.push.KyberPreKeyEntity;

View File

@ -126,7 +126,7 @@ public class AttachmentHelper {
final var streamLength = streamDetails.getLength();
final var ciphertextLength = AttachmentCipherStreamUtil.getCiphertextLength(PaddingInputStream.getPaddedSize(
streamLength));
return dependencies.getMessageSender().getResumableUploadSpec(ciphertextLength);
return dependencies.getCdnService().getResumableUploadSpecBlocking(ciphertextLength);
}
public SignalServiceAttachmentPointer uploadAttachment(String attachment) throws IOException, AttachmentInvalidException {

View File

@ -21,6 +21,7 @@ import org.signal.libsignal.zkgroup.groups.GroupMasterKey;
import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.signal.network.exceptions.NonSuccessfulResponseCodeException;
import org.signal.storageservice.storage.protos.groups.AccessControl;
import org.signal.storageservice.storage.protos.groups.GroupChange;
import org.signal.storageservice.storage.protos.groups.GroupChangeResponse;
@ -43,7 +44,6 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException;
import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.signalservice.internal.push.exceptions.NotInGroupException;
import java.io.IOException;

View File

@ -9,6 +9,7 @@ import org.signal.libsignal.protocol.InvalidKeyIdException;
import org.signal.libsignal.protocol.state.KyberPreKeyRecord;
import org.signal.libsignal.protocol.state.PreKeyRecord;
import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
import org.signal.network.exceptions.NonSuccessfulResponseCodeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.NetworkResultUtil;
@ -16,7 +17,6 @@ import org.whispersystems.signalservice.api.account.PreKeyUpload;
import org.whispersystems.signalservice.api.keys.OneTimePreKeyCounts;
import org.whispersystems.signalservice.api.push.ServiceIdType;
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import java.io.IOException;
import java.util.List;
@ -84,7 +84,8 @@ public class PreKeyHelper {
) throws IOException {
OneTimePreKeyCounts preKeyCounts;
try {
preKeyCounts = handleResponseException(dependencies.getKeysApi().getAvailablePreKeyCounts(serviceIdType));
preKeyCounts = handleResponseException(dependencies.getKeysApi()
.getAvailablePreKeyCountsSync(serviceIdType));
} catch (AuthorizationFailedException e) {
logger.debug("Failed to get pre key count, ignoring: " + e.getClass().getSimpleName());
preKeyCounts = new OneTimePreKeyCounts(0, 0);
@ -145,7 +146,7 @@ public class PreKeyHelper {
kyberPreKeyRecords);
var needsReset = false;
try {
NetworkResultUtil.toPreKeysLegacy(dependencies.getKeysApi().setPreKeys(preKeyUpload));
NetworkResultUtil.toPreKeysLegacy(dependencies.getKeysApi().setPreKeysSync(preKeyUpload));
try {
if (preKeyRecords != null) {
account.addPreKeys(serviceIdType, preKeyRecords);

View File

@ -21,6 +21,7 @@ import org.signal.libsignal.protocol.IdentityKey;
import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential;
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.signal.network.exceptions.PushNetworkException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.NetworkResultUtil;
@ -30,7 +31,6 @@ import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import org.whispersystems.signalservice.api.services.ProfileService;
import org.whispersystems.signalservice.api.util.ExpiringProfileCredentialUtil;

View File

@ -11,13 +11,13 @@ import org.signal.core.models.ServiceId.ACI;
import org.signal.core.models.ServiceId.PNI;
import org.signal.libsignal.usernames.BaseUsernameException;
import org.signal.libsignal.usernames.Username;
import org.signal.network.exceptions.NonSuccessfulResponseCodeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.cds.CdsiV2Service;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.CdsiInvalidArgumentException;
import org.whispersystems.signalservice.api.push.exceptions.CdsiInvalidTokenException;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import java.io.IOException;
import java.util.Collection;

View File

@ -160,7 +160,7 @@ public class SyncHelper {
try {
try (OutputStream fos = new FileOutputStream(contactsFile)) {
var out = new DeviceContactsOutputStream(fos, true, true);
var out = new DeviceContactsOutputStream(fos);
for (var contactPair : account.getContactStore().getContacts()) {
final var recipientId = contactPair.first();
final var contact = contactPair.second();

View File

@ -101,6 +101,7 @@ import org.signal.core.util.Base64;
import org.signal.core.util.Hex;
import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.usernames.BaseUsernameException;
import org.signal.network.exceptions.NonSuccessfulResponseCodeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
@ -117,7 +118,6 @@ import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMess
import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo;
import org.whispersystems.signalservice.api.push.ServiceIdType;
import org.whispersystems.signalservice.api.push.exceptions.CdsiResourceExhaustedException;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.signalservice.api.util.DeviceNameUtil;
import org.whispersystems.signalservice.api.util.StreamDetails;
import org.whispersystems.signalservice.internal.util.Util;
@ -190,6 +190,7 @@ public class ManagerImpl implements Manager {
userAgent,
account.getCredentialsProvider(),
account.getSignalServiceDataStore(),
account.getDeviceId(),
executor,
sessionLock);
final var avatarStore = new AvatarStore(pathConfig.avatarsPath());

View File

@ -231,6 +231,7 @@ public class RegistrationManagerImpl implements RegistrationManager {
userAgent,
account.getCredentialsProvider(),
account.getSignalServiceDataStore(),
0,
null,
new ReentrantSignalSessionLock());
handleResponseException(dependencies.getAccountApi()

View File

@ -5,13 +5,17 @@ import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
import org.asamk.signal.manager.util.Utils;
import org.signal.libsignal.metadata.certificate.CertificateValidator;
import org.signal.libsignal.net.Network;
import org.signal.libsignal.protocol.SignalProtocolAddress;
import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations;
import org.signal.network.api.AttachmentApi;
import org.signal.network.api.CallingApi;
import org.signal.network.api.CdsApi;
import org.signal.network.api.CertificateApi;
import org.signal.network.api.LinkDeviceApi;
import org.signal.network.api.RateLimitChallengeApi;
import org.signal.network.api.UsernameApi;
import org.signal.network.rest.SignalRestClient;
import org.signal.network.service.CdnService;
import org.signal.network.service.StorageServiceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -21,12 +25,12 @@ import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.SignalSessionLock;
import org.whispersystems.signalservice.api.account.AccountApi;
import org.whispersystems.signalservice.api.attachment.AttachmentApi;
import org.whispersystems.signalservice.api.crypto.SignalServiceCipher;
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
import org.whispersystems.signalservice.api.keys.KeysApi;
import org.whispersystems.signalservice.api.keys.PreKeyRepository;
import org.whispersystems.signalservice.api.message.MessageApi;
import org.whispersystems.signalservice.api.profiles.ProfileApi;
import org.whispersystems.signalservice.api.push.ServiceIdType;
@ -61,6 +65,7 @@ public class SignalDependencies {
private final String userAgent;
private final CredentialsProvider credentialsProvider;
private final SignalServiceDataStore dataStore;
private final int deviceId;
private final ExecutorService executor;
private final SignalSessionLock sessionLock;
@ -82,6 +87,11 @@ public class SignalDependencies {
private KeysApi keysApi;
private GroupsV2Operations groupsV2Operations;
private ClientZkOperations clientZkOperations;
private ProfileService profileService;
private ProfileApi profileApi;
private CdnService cdnService;
private PreKeyRepository preKeyRepository;
private SignalRestClient signalRestClient;
private PushServiceSocket pushServiceSocket;
private Network libSignalNetwork;
@ -91,14 +101,13 @@ public class SignalDependencies {
private SignalServiceMessageSender messageSender;
private List<SecureValueRecovery> secureValueRecovery;
private ProfileService profileService;
private ProfileApi profileApi;
SignalDependencies(
final ServiceEnvironmentConfig serviceEnvironmentConfig,
final String userAgent,
final CredentialsProvider credentialsProvider,
final SignalServiceDataStore dataStore,
final int deviceId,
final ExecutorService executor,
final SignalSessionLock sessionLock
) {
@ -106,6 +115,7 @@ public class SignalDependencies {
this.userAgent = userAgent;
this.credentialsProvider = credentialsProvider;
this.dataStore = dataStore;
this.deviceId = deviceId;
this.executor = executor;
this.sessionLock = sessionLock;
}
@ -326,12 +336,33 @@ public class SignalDependencies {
() -> messageReceiver = new SignalServiceMessageReceiver(getPushServiceSocket()));
}
private SignalRestClient getSignalRestClient() {
return getOrCreate(() -> signalRestClient,
() -> signalRestClient = new SignalRestClient(serviceEnvironmentConfig.signalServiceConfiguration(),
userAgent,
credentialsProvider,
ServiceConfig.AUTOMATIC_NETWORK_RETRY));
}
public CdnService getCdnService() {
return getOrCreate(() -> cdnService,
() -> cdnService = new CdnService(getSignalRestClient(), getAttachmentApi()));
}
public PreKeyRepository getPreKeyRepository() {
final SignalProtocolAddress localProtocolAddress = credentialsProvider.getAci().toProtocolAddress(deviceId);
return getOrCreate(() -> preKeyRepository,
() -> preKeyRepository = new PreKeyRepository(getKeysApi(),
dataStore.aci(),
localProtocolAddress,
Runnable::run));
}
public SignalServiceMessageSender getMessageSender() {
return getOrCreate(() -> messageSender,
() -> messageSender = new SignalServiceMessageSender(getPushServiceSocket(),
dataStore,
sessionLock,
getAttachmentApi(),
getMessageApi(),
getKeysApi(),
Optional.empty(),
@ -339,8 +370,7 @@ public class SignalDependencies {
ServiceConfig.MAX_ENVELOPE_SIZE,
ServiceConfig.MAX_INCREMENTAL_MACS_PER_ENVELOPE,
() -> true,
true,
true));
getPreKeyRepository()));
}
public List<SecureValueRecovery> getSecureValueRecovery() {
@ -368,7 +398,9 @@ public class SignalDependencies {
public SignalServiceCipher getCipher(ServiceIdType serviceIdType) {
final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.unidentifiedSenderTrustRoots());
final var serviceId = serviceIdType == ServiceIdType.ACI ? credentialsProvider.getAci() : credentialsProvider.getPni();
final var serviceId = serviceIdType == ServiceIdType.ACI
? credentialsProvider.getAci()
: credentialsProvider.getPni();
final var address = new SignalServiceAddress(serviceId, credentialsProvider.getE164());
final var deviceId = credentialsProvider.getDeviceId();
return new SignalServiceCipher(address,

View File

@ -1,8 +1,9 @@
package org.asamk.signal.manager.internal;
import org.jetbrains.annotations.NotNull;
import org.signal.network.util.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.util.Preconditions;
import org.whispersystems.signalservice.api.util.SleepTimer;
import org.whispersystems.signalservice.api.websocket.HealthMonitor;
import org.whispersystems.signalservice.api.websocket.SignalWebSocket;
@ -94,6 +95,11 @@ final class SignalWebSocketHealthMonitor implements HealthMonitor {
return needsKeepAlive && webSocket != null && webSocket.shouldSendKeepAlives();
}
@Override
public void onReceivedAlerts(@NotNull final String[] strings, final boolean b) {
logger.info("Received alerts: {}", String.join(", ", strings));
}
/**
* Sends periodic heartbeats/keep-alives over the WebSocket to prevent connection timeouts. If
* the WebSocket fails to get a return heartbeat after [KEEP_ALIVE_TIMEOUT] seconds, it is forced to be recreated.

View File

@ -403,7 +403,7 @@ public class SessionStore implements SignalServiceSessionStore {
}
private static boolean isActive(SessionRecord record) {
return record != null && record.hasSenderChain();
return record != null && record.hasSenderChain(0.0);
}
record Key(String address, int deviceId) {}

View File

@ -10,11 +10,11 @@ import org.asamk.signal.manager.api.RateLimitException;
import org.asamk.signal.manager.api.VerificationMethodNotAvailableException;
import org.asamk.signal.manager.helper.PinHelper;
import org.signal.core.models.MasterKey;
import org.signal.network.exceptions.NonSuccessfulResponseCodeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.push.exceptions.ChallengeRequiredException;
import org.whispersystems.signalservice.api.push.exceptions.NoSuchSessionException;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.signalservice.api.push.exceptions.TokenNotAcceptedException;
import org.whispersystems.signalservice.api.registration.RegistrationApi;
import org.whispersystems.signalservice.internal.push.LockedException;

View File

@ -7,9 +7,9 @@ import org.signal.libsignal.net.RequestResult;
import org.signal.libsignal.protocol.IdentityKey;
import org.signal.libsignal.protocol.fingerprint.Fingerprint;
import org.signal.libsignal.protocol.fingerprint.NumericFingerprintGenerator;
import org.signal.network.NetworkResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.NetworkResult;
import org.whispersystems.signalservice.api.NetworkResultUtil;
import org.whispersystems.signalservice.api.util.StreamDetails;

View File

@ -6543,6 +6543,33 @@
"type": "org.signal.libsignal.zkgroup.profiles.ProfileKey",
"allDeclaredFields": true
},
{
"type": "org.signal.network.api.SenderCertificate",
"methods": [
{
"name": "<init>",
"parameterTypes": []
},
{
"name": "setCertificate",
"parameterTypes": [
"byte[]"
]
}
]
},
{
"type": "org.signal.network.api.SenderCertificate$ByteArrayDeserializer",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "org.signal.network.api.SenderCertificate$ByteArraySerializer"
},
{
"type": "org.signal.storageservice.storage.protos.groups.AccessControl",
"fields": [