Update libsignal-service

This commit is contained in:
AsamK 2026-10-06 22:34:26 +02:00
parent ebf24ee0b0
commit 9b6c098137
13 changed files with 106 additions and 72 deletions

View File

@ -4,7 +4,7 @@ coroutines = "1.11.0"
junit = "6.1.3"
micronaut-json-schema = "2.3.1"
micronaut-core = "5.2.14"
signal-service = "2.15.3_unofficial_153"
signal-service = "2.15.3_unofficial_154"
[libraries]
bouncycastle = "org.bouncycastle:bcprov-jdk18on:1.86"

View File

@ -6,7 +6,7 @@ import org.asamk.signal.manager.api.NonNormalizedPhoneNumberException;
import org.asamk.signal.manager.api.PinLockMissingException;
import org.asamk.signal.manager.api.PinLockedException;
import org.asamk.signal.manager.api.RateLimitException;
import org.asamk.signal.manager.api.TotpRequiredException;
import org.asamk.signal.manager.api.TwoFactorRequired;
import org.asamk.signal.manager.api.VerificationMethodNotAvailableException;
import java.io.Closeable;
@ -18,7 +18,7 @@ public interface RegistrationManager extends Closeable {
boolean voiceVerification,
String captcha,
final boolean forceRegister
) throws IOException, CaptchaRequiredException, NonNormalizedPhoneNumberException, RateLimitException, TotpRequiredException, VerificationMethodNotAvailableException;
) throws IOException, CaptchaRequiredException, NonNormalizedPhoneNumberException, RateLimitException, TwoFactorRequired, VerificationMethodNotAvailableException;
void verifyAccount(
String verificationCode,
@ -29,7 +29,7 @@ public interface RegistrationManager extends Closeable {
String recoveryKey,
boolean forceRegister,
Integer totp
) throws IOException, RateLimitException, TotpRequiredException;
) throws IOException, RateLimitException, TwoFactorRequired;
void deleteLocalAccountData() throws IOException;

View File

@ -2,9 +2,9 @@ package org.asamk.signal.manager.api;
import java.io.IOException;
public class TotpRequiredException extends IOException {
public class TwoFactorRequired extends IOException {
public TotpRequiredException() {
public TwoFactorRequired() {
super("A TOTP token is required or the supplied token is incorrect");
}
}

View File

@ -3,7 +3,6 @@ package org.asamk.signal.manager.config;
import org.signal.libsignal.net.Network.Environment;
import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.ecc.ECPublicKey;
import org.signal.network.config.HttpProxy;
import org.signal.network.config.SignalCdnUrl;
import org.signal.network.config.SignalCdsiUrl;
import org.signal.network.config.SignalProxy;
@ -44,7 +43,6 @@ class LiveConfig {
private static final Optional<Dns> dns = Optional.empty();
private static final Optional<SignalProxy> proxy = Optional.empty();
private static final Optional<HttpProxy> systemProxy = Optional.empty();
private static final byte[] zkGroupServerPublicParams = Base64.getDecoder()
.decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X36nOoGPs54XsEGzPdEV+itQNGUFEjY6X9Uv+Acuks7NpyGvCoKxGwgKgE5XyJ+nNKlyHHOLb6N1NuHyBrZrgtY/JYJHRooo5CEqYKBqdFnmbTVGEkCvJKxLnjwKWf+fEPoWeQFj5ObDjcKMZf2Jm2Ae69x+ikU5gBXsRmoF94GXTLfN0/vLt98KDPnxwAQL9j5V1jGOY8jQl6MLxEs56cwXN0dqCnImzVH3TZT1cJ8SW1BRX6qIVxEzjsSGx3yxF3suAilPMqGRp4ffyopjMD1JXiKR2RwLKzizUe5e8XyGOy9fplzhw3jVzTRyUZTRSZKkMLWcQ/gv0E4aONNqs4P+NameAZYOD12qRkxosQQP5uux6B2nRyZ7sAV54DgFyLiRcq1FvwKw2EPQdk4HDoePrO/RNUbyNddnM/mMgj4FW65xCoT1LmjrIjsv/Ggdlx46ueczhMgtBunx1/w8k8V+l8LVZ8gAT6wkU5J+DPQalQguMg12Jzug3q4TbdHiGCmD9EunCwOmsLuLJkz6EcSYXtrlDEnAM+hicw7iergYLLlMXpfTdGxJCWJmP4zqUFeTTmsmhsjGBt7NiEB/9pFFEB3pSbf4iiUukw63Eo8Aqnf4iwob6X1QviCWuc8t0LUlT9vALgh/f2DPVOOmR0RW6bgRvc7DSF20V/omg+YBw==");
@ -72,7 +70,6 @@ class LiveConfig {
interceptors,
dns,
proxy,
systemProxy,
zkGroupServerPublicParams,
genericServerPublicParams,
backupServerPublicParams,

View File

@ -3,7 +3,6 @@ package org.asamk.signal.manager.config;
import org.signal.libsignal.net.Network;
import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.ecc.ECPublicKey;
import org.signal.network.config.HttpProxy;
import org.signal.network.config.SignalCdnUrl;
import org.signal.network.config.SignalCdsiUrl;
import org.signal.network.config.SignalProxy;
@ -44,7 +43,6 @@ class StagingConfig {
private static final Optional<Dns> dns = Optional.empty();
private static final Optional<SignalProxy> proxy = Optional.empty();
private static final Optional<HttpProxy> systemProxy = Optional.empty();
private static final byte[] zkGroupServerPublicParams = Base64.getDecoder()
.decode("ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdlukrpzzsCIvEwjwQlJYVPOQPj4V0F4UXXBdHSLK05uoPBCQG8G9rYIGedYsClJXnbrgGYG3eMTG5hnx4X4ntARBgELuMWWUEEfSK0mjXg+/2lPmWcTZWR9nkqgQQP0tbzuiPm74H2wMO4u1Wafe+UwyIlIT9L7KLS19Aw8r4sPrXZSSsOZ6s7M1+rTJN0bI5CKY2PX29y5Ok3jSWufIKcgKOnWoP67d5b2du2ZVJjpjfibNIHbT/cegy/sBLoFwtHogVYUewANUAXIaMPyCLRArsKhfJ5wBtTminG/PAvuBdJ70Z/bXVPf8TVsR292zQ65xwvWTejROW6AZX6aqucUjlENAErBme1YHmOSpU6tr6doJ66dPzVAWIanmO/5mgjNEDeK7DDqQdB1xd03HT2Qs2TxY3kCK8aAb/0iM0HQiXjxZ9HIgYhbtvGEnDKW5ILSUydqH/KBhW4Pb0jZWnqN/YgbWDKeJxnDbYcUob5ZY5Lt5ZCMKuaGUvCJRrCtuugSMaqjowCGRempsDdJEt+cMaalhZ6gczklJB/IbdwENW9KeVFPoFNFzhxWUIS5ML9riVYhAtE6JE5jX0xiHNVIIPthb458cfA8daR0nYfYAUKogQArm0iBezOO+mPk5vCNWI+wwkyFCqNDXz/qxl1gAntuCJtSfq9OC3NkdhQlgYQ==");
@ -72,7 +70,6 @@ class StagingConfig {
interceptors,
dns,
proxy,
systemProxy,
zkGroupServerPublicParams,
genericServerPublicParams,
backupServerPublicParams,

View File

@ -560,9 +560,9 @@ public class AccountHelper {
final List<DeviceInfo> devices = handleResponseExceptionSuspend(cont -> dependencies.getLinkDeviceApi()
.getDevices(cont));
final var deviceId = account.getDeviceId();
final var device = devices.stream().filter(d -> d.id == deviceId).findFirst();
final var device = devices.stream().filter(d -> d.getId() == deviceId).findFirst();
if (device.isPresent()) {
account.setEncryptedDeviceName(device.get().name);
account.setEncryptedDeviceName(device.get().getName());
}
}

View File

@ -365,7 +365,7 @@ public final class ProfileHelper {
}
if (recipientId.equals(account.getSelfRecipientId())) {
final var isUnrestricted = encryptedProfile.isUnrestrictedUnidentifiedAccess();
final var isUnrestricted = encryptedProfile.getUnrestrictedUnidentifiedAccess();
if (account.isUnrestrictedUnidentifiedAccess() != isUnrestricted) {
account.setUnrestrictedUnidentifiedAccess(isUnrestricted);
}

View File

@ -555,7 +555,8 @@ public class SendHelper {
recipients,
unidentifiedAccess,
groupSendEndorsements,
message),
message,
null),
recipientIds,
groupInfo,
false);

View File

@ -25,7 +25,7 @@ import org.asamk.signal.manager.api.NonNormalizedPhoneNumberException;
import org.asamk.signal.manager.api.PinLockMissingException;
import org.asamk.signal.manager.api.PinLockedException;
import org.asamk.signal.manager.api.RateLimitException;
import org.asamk.signal.manager.api.TotpRequiredException;
import org.asamk.signal.manager.api.TwoFactorRequired;
import org.asamk.signal.manager.api.UpdateProfile;
import org.asamk.signal.manager.api.VerificationMethodNotAvailableException;
import org.asamk.signal.manager.config.ServiceConfig;
@ -123,7 +123,7 @@ public class RegistrationManagerImpl implements RegistrationManager {
boolean voiceVerification,
String captcha,
final boolean forceRegister
) throws IOException, CaptchaRequiredException, NonNormalizedPhoneNumberException, RateLimitException, TotpRequiredException, VerificationMethodNotAvailableException {
) throws IOException, CaptchaRequiredException, NonNormalizedPhoneNumberException, RateLimitException, TwoFactorRequired, VerificationMethodNotAvailableException {
if (account.isRegistered()
&& account.getServiceEnvironment() != null
&& account.getServiceEnvironment() != serviceEnvironmentConfig.type()) {
@ -212,7 +212,7 @@ public class RegistrationManagerImpl implements RegistrationManager {
final String recoveryKey,
final boolean forceRegister,
final Integer totp
) throws IOException, RateLimitException, TotpRequiredException {
) throws IOException, RateLimitException, TwoFactorRequired {
if (account.getAci() == null) {
throw new IOException("Recovery-key registration requires an ACI account identifier");
}
@ -228,13 +228,13 @@ public class RegistrationManagerImpl implements RegistrationManager {
private boolean attemptRecoverAccount(
final Integer totp
) throws IOException, RateLimitException, TotpRequiredException {
) throws IOException, RateLimitException, TwoFactorRequired {
final var accountEntropyPool = account.getAccountEntropyPool();
try {
recoverAccount(totp, false, accountEntropyPool);
logger.info("Reregistered existing account using its ACI and Account Entropy Pool.");
return true;
} catch (TotpRequiredException | RateLimitException e) {
} catch (TwoFactorRequired | RateLimitException e) {
throw e;
} catch (RecoveryRequestFailedException e) {
logger.debug("Failed to reregister account using its ACI and Account Entropy Pool", e);
@ -246,7 +246,7 @@ public class RegistrationManagerImpl implements RegistrationManager {
final Integer totp,
final boolean includeRegistrationLock,
final AccountEntropyPool accountEntropyPool
) throws IOException, RateLimitException, TotpRequiredException {
) throws IOException, RateLimitException, TwoFactorRequired {
if (account.getPniIdentityKeyPair() == null) {
account.setPniIdentityKeyPair(KeyUtils.generateIdentityKeyPair());
}
@ -273,6 +273,7 @@ public class RegistrationManagerImpl implements RegistrationManager {
true,
account.getAci(),
totp,
null,
cont));
} catch (BadRequestException e) {
switch (e.getError()) {
@ -283,7 +284,7 @@ public class RegistrationManagerImpl implements RegistrationManager {
recoverAccount(totp, true, accountEntropyPool);
return;
}
case RegisterAccountError.TotpMissingOrIncorrect ignored -> throw new TotpRequiredException();
case RegisterAccountError.TwoFactorRequired ignored -> throw new TwoFactorRequired();
case RegisterAccountError.RegistrationRecoveryPasswordIncorrect ignored ->
throw new RecoveryRequestFailedException("Account key or recovery key is incorrect", e);
case RegisterAccountError.RateLimited ignored -> throw new RateLimitException(null);
@ -416,7 +417,7 @@ public class RegistrationManagerImpl implements RegistrationManager {
account.finishRegistration(aci, pni, masterKey, pin, aciPreKeys, pniPreKeys);
accountFileUpdater.updateAccountIdentifiers(account.getNumber(), aci);
finishManagerRegistration(response.isStorageCapable());
finishManagerRegistration(response.getStorageCapable());
}
private void finishManagerRegistration(final boolean storageCapable) throws IOException {

View File

@ -65,7 +65,7 @@ public class ProfileUtils {
final SignalServiceProfile encryptedProfile,
final ProfileCipher profileCipher
) {
if (encryptedProfile.isUnrestrictedUnidentifiedAccess()) {
if (encryptedProfile.getUnrestrictedUnidentifiedAccess()) {
return Profile.UnidentifiedAccessMode.UNRESTRICTED;
}
@ -81,11 +81,13 @@ public class ProfileUtils {
public static HashSet<Profile.Capability> getCapabilities(final SignalServiceProfile encryptedProfile) {
final var capabilities = new HashSet<Profile.Capability>();
if (encryptedProfile.getCapabilities().isStorage()) {
capabilities.add(Profile.Capability.storage);
}
if (encryptedProfile.getCapabilities().isStorageServiceEncryptionV2()) {
capabilities.add(Profile.Capability.storageServiceEncryptionV2Capability);
if (encryptedProfile.getCapabilities() != null) {
if (encryptedProfile.getCapabilities().getStorage()) {
capabilities.add(Profile.Capability.storage);
}
if (encryptedProfile.getCapabilities().getStorageServiceEncryptionV2()) {
capabilities.add(Profile.Capability.storageServiceEncryptionV2Capability);
}
}
return capabilities;

View File

@ -15,7 +15,7 @@ import org.asamk.signal.manager.RegistrationManager;
import org.asamk.signal.manager.api.CaptchaRequiredException;
import org.asamk.signal.manager.api.NonNormalizedPhoneNumberException;
import org.asamk.signal.manager.api.RateLimitException;
import org.asamk.signal.manager.api.TotpRequiredException;
import org.asamk.signal.manager.api.TwoFactorRequired;
import org.asamk.signal.manager.api.VerificationMethodNotAvailableException;
import org.asamk.signal.output.JsonWriter;
import org.asamk.signal.util.CommandUtil;
@ -111,7 +111,7 @@ public class RegisterCommand implements RegistrationCommand, JsonRpcRegistration
} catch (RateLimitException e) {
final var message = CommandUtil.getRateLimitMessage(e);
throw new RateLimitErrorException(message, e);
} catch (TotpRequiredException e) {
} catch (TwoFactorRequired e) {
throw new UserErrorException("A TOTP token is required; rerun register with --totp TOKEN");
} catch (IOException e) {
throw new IOErrorException("Failed to register: %s (%s)".formatted(e.getMessage(),
@ -130,7 +130,7 @@ public class RegisterCommand implements RegistrationCommand, JsonRpcRegistration
throw new UserErrorException(message);
} catch (NonNormalizedPhoneNumberException e) {
throw new UserErrorException("Failed to register: " + e.getMessage(), e);
} catch (TotpRequiredException e) {
} catch (TwoFactorRequired e) {
throw new UserErrorException(
"A TOTP token is required; rerun register with --recovery-key RECOVERY-KEY --totp TOKEN");
} catch (IOException e) {

View File

@ -5,7 +5,7 @@ import org.asamk.signal.manager.RegistrationManager;
import org.asamk.signal.manager.api.CaptchaRequiredException;
import org.asamk.signal.manager.api.IncorrectPinException;
import org.asamk.signal.manager.api.PinLockedException;
import org.asamk.signal.manager.api.TotpRequiredException;
import org.asamk.signal.manager.api.TwoFactorRequired;
import org.freedesktop.dbus.connections.impl.DBusConnection;
import java.io.IOException;
@ -59,7 +59,7 @@ public class DbusRegistrationManagerImpl implements RegistrationManager {
final String recoveryKey,
final boolean forceRegister,
final Integer totp
) throws IOException, TotpRequiredException {
) throws IOException, TwoFactorRequired {
throw new IOException("Recovery-key registration is not supported over D-Bus");
}

View File

@ -1415,6 +1415,9 @@
}
]
},
{
"type": "java.math.BigDecimal"
},
{
"type": "java.math.BigInteger"
},
@ -1771,6 +1774,9 @@
{
"type": "kotlin.Any"
},
{
"type": "kotlin.Array"
},
{
"type": "kotlin.Boolean"
},
@ -1946,42 +1952,7 @@
},
{
"type": "kotlin.reflect.jvm.internal.impl.resolve.scopes.DescriptorKindFilter",
"allPublicFields": true,
"fields": [
{
"name": "ALL"
},
{
"name": "CALLABLES"
},
{
"name": "CLASSIFIERS"
},
{
"name": "Companion"
},
{
"name": "FUNCTIONS"
},
{
"name": "NON_SINGLETON_CLASSIFIERS"
},
{
"name": "PACKAGES"
},
{
"name": "SINGLETON_CLASSIFIERS"
},
{
"name": "TYPE_ALIASES"
},
{
"name": "VALUES"
},
{
"name": "VARIABLES"
}
]
"allPublicFields": true
},
{
"type": "kotlinx.coroutines.AwaitAll"
@ -2513,6 +2484,10 @@
"type": "org.asamk.signal.commands.ListAccountsCommand$JsonAccount",
"allDeclaredFields": true,
"methods": [
{
"name": "aci",
"parameterTypes": []
},
{
"name": "number",
"parameterTypes": []
@ -5118,6 +5093,15 @@
}
]
},
{
"type": "org.bouncycastle.jcajce.provider.asymmetric.XMSS$Mappings",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "org.bouncycastle.jcajce.provider.asymmetric.edec.SignatureSpi$Ed25519",
"methods": [
@ -7184,6 +7168,9 @@
"type": "org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential",
"allDeclaredFields": true
},
{
"type": "org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredentialResponse"
},
{
"type": "org.signal.libsignal.zkgroup.profiles.ProfileKey",
"allDeclaredFields": true
@ -8321,6 +8308,13 @@
{
"name": "<init>",
"parameterTypes": []
},
{
"name": "<init>",
"parameterTypes": [
"int",
"int"
]
}
]
},
@ -8463,6 +8457,12 @@
"allDeclaredMethods": true,
"allDeclaredConstructors": true
},
{
"type": "org.whispersystems.signalservice.api.profiles.SignalServiceProfile$Companion"
},
{
"type": "org.whispersystems.signalservice.api.profiles.SignalServiceProfile$RequestType"
},
{
"type": "org.whispersystems.signalservice.api.profiles.SignalServiceProfileWrite",
"allDeclaredFields": true,
@ -8471,7 +8471,13 @@
},
{
"type": "org.whispersystems.signalservice.api.provisioning.ProvisioningMessage",
"allDeclaredFields": true
"allDeclaredFields": true,
"methods": [
{
"name": "getBody",
"parameterTypes": []
}
]
},
{
"type": "org.whispersystems.signalservice.api.push.ServiceId",
@ -8919,6 +8925,9 @@
"allDeclaredMethods": true,
"allDeclaredConstructors": true
},
{
"type": "org.whispersystems.signalservice.internal.push.AuthCredentials$Companion"
},
{
"type": "org.whispersystems.signalservice.internal.push.ByteArrayDeserializerBase64",
"methods": [
@ -8928,6 +8937,15 @@
}
]
},
{
"type": "org.whispersystems.signalservice.internal.push.ByteArraySerializerBase64NoPadding",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "org.whispersystems.signalservice.internal.push.CdsiAuthResponse",
"allDeclaredFields": true,
@ -8935,6 +8953,13 @@
{
"name": "<init>",
"parameterTypes": []
},
{
"name": "<init>",
"parameterTypes": [
"java.lang.String",
"java.lang.String"
]
}
]
},
@ -9096,6 +9121,14 @@
"name": "<init>",
"parameterTypes": []
},
{
"name": "<init>",
"parameterTypes": [
"long",
"org.signal.libsignal.protocol.kem.KEMPublicKey",
"byte[]"
]
},
{
"name": "getKeyId",
"parameterTypes": []
@ -9182,6 +9215,9 @@
"allDeclaredMethods": true,
"allDeclaredConstructors": true
},
{
"type": "org.whispersystems.signalservice.internal.push.MismatchedDevices$Companion"
},
{
"type": "org.whispersystems.signalservice.internal.push.OneTimePreKeyCounts",
"allDeclaredFields": true,