mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 10:30:38 +00:00
Update libsignal-service-java
This commit is contained in:
parent
c8e35991b9
commit
e57e5b090e
8 changed files with 165 additions and 46 deletions
|
@ -956,7 +956,7 @@
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
"allDeclaredMethods":true,
|
"allDeclaredMethods":true,
|
||||||
"allDeclaredConstructors":true,
|
"allDeclaredConstructors":true,
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
"methods":[{"name":"<init>","parameterTypes":[] }, {"name":"getId","parameterTypes":[] }, {"name":"getJsonrpc","parameterTypes":[] }, {"name":"getMethod","parameterTypes":[] }, {"name":"getParams","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"org.asamk.signal.jsonrpc.JsonRpcResponse",
|
"name":"org.asamk.signal.jsonrpc.JsonRpcResponse",
|
||||||
|
@ -1987,7 +1987,7 @@
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
"allDeclaredMethods":true,
|
"allDeclaredMethods":true,
|
||||||
"allDeclaredConstructors":true,
|
"allDeclaredConstructors":true,
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
"methods":[{"name":"<init>","parameterTypes":[] }, {"name":"getSignature","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.api.push.SignedPreKeyEntity$ByteArrayDeserializer",
|
"name":"org.whispersystems.signalservice.api.push.SignedPreKeyEntity$ByteArrayDeserializer",
|
||||||
|
@ -2015,7 +2015,8 @@
|
||||||
"name":"org.whispersystems.signalservice.internal.contacts.crypto.SignatureBodyEntity",
|
"name":"org.whispersystems.signalservice.internal.contacts.crypto.SignatureBodyEntity",
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
"allDeclaredMethods":true,
|
"allDeclaredMethods":true,
|
||||||
"allDeclaredConstructors":true
|
"allDeclaredConstructors":true,
|
||||||
|
"methods":[{"name":"<init>","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.contacts.entities.DiscoveryRequest",
|
"name":"org.whispersystems.signalservice.internal.contacts.entities.DiscoveryRequest",
|
||||||
|
@ -2033,13 +2034,15 @@
|
||||||
"name":"org.whispersystems.signalservice.internal.contacts.entities.KeyBackupRequest",
|
"name":"org.whispersystems.signalservice.internal.contacts.entities.KeyBackupRequest",
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
"allDeclaredMethods":true,
|
"allDeclaredMethods":true,
|
||||||
"allDeclaredConstructors":true
|
"allDeclaredConstructors":true,
|
||||||
|
"methods":[{"name":"getData","parameterTypes":[] }, {"name":"getIv","parameterTypes":[] }, {"name":"getMac","parameterTypes":[] }, {"name":"getRequestId","parameterTypes":[] }, {"name":"getType","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.contacts.entities.KeyBackupResponse",
|
"name":"org.whispersystems.signalservice.internal.contacts.entities.KeyBackupResponse",
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
"allDeclaredMethods":true,
|
"allDeclaredMethods":true,
|
||||||
"allDeclaredConstructors":true
|
"allDeclaredConstructors":true,
|
||||||
|
"methods":[{"name":"<init>","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.contacts.entities.MultiRemoteAttestationResponse",
|
"name":"org.whispersystems.signalservice.internal.contacts.entities.MultiRemoteAttestationResponse",
|
||||||
|
@ -2057,19 +2060,22 @@
|
||||||
"name":"org.whispersystems.signalservice.internal.contacts.entities.RemoteAttestationRequest",
|
"name":"org.whispersystems.signalservice.internal.contacts.entities.RemoteAttestationRequest",
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
"allDeclaredMethods":true,
|
"allDeclaredMethods":true,
|
||||||
"allDeclaredConstructors":true
|
"allDeclaredConstructors":true,
|
||||||
|
"methods":[{"name":"getClientPublic","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.contacts.entities.RemoteAttestationResponse",
|
"name":"org.whispersystems.signalservice.internal.contacts.entities.RemoteAttestationResponse",
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
"allDeclaredMethods":true,
|
"allDeclaredMethods":true,
|
||||||
"allDeclaredConstructors":true
|
"allDeclaredConstructors":true,
|
||||||
|
"methods":[{"name":"<init>","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.contacts.entities.TokenResponse",
|
"name":"org.whispersystems.signalservice.internal.contacts.entities.TokenResponse",
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
"allDeclaredMethods":true,
|
"allDeclaredMethods":true,
|
||||||
"allDeclaredConstructors":true
|
"allDeclaredConstructors":true,
|
||||||
|
"methods":[{"name":"<init>","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.devices.DeviceNameProtos$DeviceName",
|
"name":"org.whispersystems.signalservice.internal.devices.DeviceNameProtos$DeviceName",
|
||||||
|
@ -2113,7 +2119,8 @@
|
||||||
"name":"org.whispersystems.signalservice.internal.push.AuthCredentials",
|
"name":"org.whispersystems.signalservice.internal.push.AuthCredentials",
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
"allDeclaredMethods":true,
|
"allDeclaredMethods":true,
|
||||||
"allDeclaredConstructors":true
|
"allDeclaredConstructors":true,
|
||||||
|
"methods":[{"name":"<init>","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.push.CdsiAuthResponse",
|
"name":"org.whispersystems.signalservice.internal.push.CdsiAuthResponse",
|
||||||
|
@ -2154,6 +2161,12 @@
|
||||||
"allDeclaredConstructors":true,
|
"allDeclaredConstructors":true,
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
"methods":[{"name":"<init>","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"org.whispersystems.signalservice.internal.push.GcmRegistrationId",
|
||||||
|
"allDeclaredFields":true,
|
||||||
|
"queryAllDeclaredMethods":true,
|
||||||
|
"queryAllDeclaredConstructors":true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.push.GetAciByUsernameResponse",
|
"name":"org.whispersystems.signalservice.internal.push.GetAciByUsernameResponse",
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
|
@ -2231,7 +2244,7 @@
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
"allDeclaredMethods":true,
|
"allDeclaredMethods":true,
|
||||||
"allDeclaredConstructors":true,
|
"allDeclaredConstructors":true,
|
||||||
"methods":[{"name":"<init>","parameterTypes":[] }]
|
"methods":[{"name":"<init>","parameterTypes":[] }, {"name":"getKeyId","parameterTypes":[] }, {"name":"getPublicKey","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.push.PreKeyEntity$ECPublicKeyDeserializer",
|
"name":"org.whispersystems.signalservice.internal.push.PreKeyEntity$ECPublicKeyDeserializer",
|
||||||
|
@ -2317,7 +2330,7 @@
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
"queryAllDeclaredMethods":true,
|
"queryAllDeclaredMethods":true,
|
||||||
"queryAllDeclaredConstructors":true,
|
"queryAllDeclaredConstructors":true,
|
||||||
"methods":[{"name":"getAccountAttributes","parameterTypes":[] }, {"name":"getRecoveryPassword","parameterTypes":[] }, {"name":"getSessionId","parameterTypes":[] }, {"name":"getSkipDeviceTransfer","parameterTypes":[] }]
|
"methods":[{"name":"getAccountAttributes","parameterTypes":[] }, {"name":"getAciIdentityKey","parameterTypes":[] }, {"name":"getAciPqLastResortPreKey","parameterTypes":[] }, {"name":"getAciSignedPreKey","parameterTypes":[] }, {"name":"getGcmToken","parameterTypes":[] }, {"name":"getPniIdentityKey","parameterTypes":[] }, {"name":"getPniPqLastResortPreKey","parameterTypes":[] }, {"name":"getPniSignedPreKey","parameterTypes":[] }, {"name":"getRecoveryPassword","parameterTypes":[] }, {"name":"getSessionId","parameterTypes":[] }, {"name":"getSkipDeviceTransfer","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.push.ReserveUsernameRequest",
|
"name":"org.whispersystems.signalservice.internal.push.ReserveUsernameRequest",
|
||||||
|
@ -2646,7 +2659,8 @@
|
||||||
"name":"org.whispersystems.signalservice.internal.push.VerifyAccountResponse",
|
"name":"org.whispersystems.signalservice.internal.push.VerifyAccountResponse",
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
"allDeclaredMethods":true,
|
"allDeclaredMethods":true,
|
||||||
"allDeclaredConstructors":true
|
"allDeclaredConstructors":true,
|
||||||
|
"methods":[{"name":"<init>","parameterTypes":[] }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.push.WhoAmIResponse",
|
"name":"org.whispersystems.signalservice.internal.push.WhoAmIResponse",
|
||||||
|
|
|
@ -113,7 +113,7 @@ public class AccountHelper {
|
||||||
account.setNumber(number);
|
account.setNumber(number);
|
||||||
account.setAci(aci);
|
account.setAci(aci);
|
||||||
account.setPni(pni);
|
account.setPni(pni);
|
||||||
if (account.isPrimaryDevice() && account.getPniIdentityKeyPair() == null && account.getPni() != null) {
|
if (account.isPrimaryDevice() && account.getPniIdentityKeyPair() == null) {
|
||||||
account.setPniIdentityKeyPair(KeyUtils.generateIdentityKeyPair());
|
account.setPniIdentityKeyPair(KeyUtils.generateIdentityKeyPair());
|
||||||
}
|
}
|
||||||
account.getRecipientTrustedResolver().resolveSelfRecipientTrusted(account.getSelfRecipientAddress());
|
account.getRecipientTrustedResolver().resolveSelfRecipientTrusted(account.getSelfRecipientAddress());
|
||||||
|
|
|
@ -38,18 +38,21 @@ public class PreKeyHelper {
|
||||||
public void refreshPreKeysIfNecessary(ServiceIdType serviceIdType) throws IOException {
|
public void refreshPreKeysIfNecessary(ServiceIdType serviceIdType) throws IOException {
|
||||||
final var preKeyCounts = dependencies.getAccountManager().getPreKeyCounts(serviceIdType);
|
final var preKeyCounts = dependencies.getAccountManager().getPreKeyCounts(serviceIdType);
|
||||||
if (preKeyCounts.getEcCount() < ServiceConfig.PREKEY_MINIMUM_COUNT) {
|
if (preKeyCounts.getEcCount() < ServiceConfig.PREKEY_MINIMUM_COUNT) {
|
||||||
|
logger.debug("Refreshing {} ec pre keys, because only {} of {} pre keys remain",
|
||||||
|
serviceIdType,
|
||||||
|
preKeyCounts.getEcCount(),
|
||||||
|
ServiceConfig.PREKEY_MINIMUM_COUNT);
|
||||||
refreshPreKeys(serviceIdType);
|
refreshPreKeys(serviceIdType);
|
||||||
}
|
}
|
||||||
if (preKeyCounts.getKyberCount() < ServiceConfig.PREKEY_MINIMUM_COUNT) {
|
if (preKeyCounts.getKyberCount() < ServiceConfig.PREKEY_MINIMUM_COUNT) {
|
||||||
|
logger.debug("Refreshing {} kyber pre keys, because only {} of {} pre keys remain",
|
||||||
|
serviceIdType,
|
||||||
|
preKeyCounts.getEcCount(),
|
||||||
|
ServiceConfig.PREKEY_MINIMUM_COUNT);
|
||||||
refreshKyberPreKeys(serviceIdType);
|
refreshKyberPreKeys(serviceIdType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshPreKeys() throws IOException {
|
|
||||||
refreshPreKeys(ServiceIdType.ACI);
|
|
||||||
refreshPreKeys(ServiceIdType.PNI);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshPreKeys(ServiceIdType serviceIdType) throws IOException {
|
private void refreshPreKeys(ServiceIdType serviceIdType) throws IOException {
|
||||||
final var identityKeyPair = account.getIdentityKeyPair(serviceIdType);
|
final var identityKeyPair = account.getIdentityKeyPair(serviceIdType);
|
||||||
if (identityKeyPair == null) {
|
if (identityKeyPair == null) {
|
||||||
|
@ -86,7 +89,7 @@ public class PreKeyHelper {
|
||||||
private List<PreKeyRecord> generatePreKeys(ServiceIdType serviceIdType) {
|
private List<PreKeyRecord> generatePreKeys(ServiceIdType serviceIdType) {
|
||||||
final var offset = account.getPreKeyIdOffset(serviceIdType);
|
final var offset = account.getPreKeyIdOffset(serviceIdType);
|
||||||
|
|
||||||
var records = KeyUtils.generatePreKeyRecords(offset, ServiceConfig.PREKEY_BATCH_SIZE);
|
var records = KeyUtils.generatePreKeyRecords(offset);
|
||||||
account.addPreKeys(serviceIdType, records);
|
account.addPreKeys(serviceIdType, records);
|
||||||
|
|
||||||
return records;
|
return records;
|
||||||
|
@ -95,7 +98,7 @@ public class PreKeyHelper {
|
||||||
private SignedPreKeyRecord generateSignedPreKey(ServiceIdType serviceIdType, IdentityKeyPair identityKeyPair) {
|
private SignedPreKeyRecord generateSignedPreKey(ServiceIdType serviceIdType, IdentityKeyPair identityKeyPair) {
|
||||||
final var signedPreKeyId = account.getNextSignedPreKeyId(serviceIdType);
|
final var signedPreKeyId = account.getNextSignedPreKeyId(serviceIdType);
|
||||||
|
|
||||||
var record = KeyUtils.generateSignedPreKeyRecord(identityKeyPair, signedPreKeyId);
|
var record = KeyUtils.generateSignedPreKeyRecord(signedPreKeyId, identityKeyPair);
|
||||||
account.addSignedPreKey(serviceIdType, record);
|
account.addSignedPreKey(serviceIdType, record);
|
||||||
|
|
||||||
return record;
|
return record;
|
||||||
|
@ -139,9 +142,7 @@ public class PreKeyHelper {
|
||||||
) {
|
) {
|
||||||
final var offset = account.getKyberPreKeyIdOffset(serviceIdType);
|
final var offset = account.getKyberPreKeyIdOffset(serviceIdType);
|
||||||
|
|
||||||
var records = KeyUtils.generateKyberPreKeyRecords(offset,
|
var records = KeyUtils.generateKyberPreKeyRecords(offset, identityKeyPair.getPrivateKey());
|
||||||
ServiceConfig.PREKEY_BATCH_SIZE,
|
|
||||||
identityKeyPair.getPrivateKey());
|
|
||||||
account.addKyberPreKeys(serviceIdType, records);
|
account.addKyberPreKeys(serviceIdType, records);
|
||||||
|
|
||||||
return records;
|
return records;
|
||||||
|
|
|
@ -378,7 +378,7 @@ public class ManagerImpl implements Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
void refreshPreKeys() throws IOException {
|
void refreshPreKeys() throws IOException {
|
||||||
context.getPreKeyHelper().refreshPreKeys();
|
context.getPreKeyHelper().refreshPreKeysIfNecessary();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -29,16 +29,19 @@ import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
||||||
import org.asamk.signal.manager.helper.AccountFileUpdater;
|
import org.asamk.signal.manager.helper.AccountFileUpdater;
|
||||||
import org.asamk.signal.manager.helper.PinHelper;
|
import org.asamk.signal.manager.helper.PinHelper;
|
||||||
import org.asamk.signal.manager.storage.SignalAccount;
|
import org.asamk.signal.manager.storage.SignalAccount;
|
||||||
|
import org.asamk.signal.manager.util.KeyUtils;
|
||||||
import org.asamk.signal.manager.util.NumberVerificationUtils;
|
import org.asamk.signal.manager.util.NumberVerificationUtils;
|
||||||
import org.asamk.signal.manager.util.Utils;
|
import org.asamk.signal.manager.util.Utils;
|
||||||
import org.signal.libsignal.usernames.BaseUsernameException;
|
import org.signal.libsignal.usernames.BaseUsernameException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
|
import org.whispersystems.signalservice.api.account.PreKeyCollection;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
|
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ACI;
|
||||||
import org.whispersystems.signalservice.api.push.PNI;
|
import org.whispersystems.signalservice.api.push.PNI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException;
|
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
|
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
|
||||||
|
@ -48,6 +51,8 @@ import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import static org.asamk.signal.manager.config.ServiceConfig.PREKEY_MAXIMUM_ID;
|
||||||
|
|
||||||
public class RegistrationManagerImpl implements RegistrationManager {
|
public class RegistrationManagerImpl implements RegistrationManager {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(RegistrationManagerImpl.class);
|
private final static Logger logger = LoggerFactory.getLogger(RegistrationManagerImpl.class);
|
||||||
|
@ -138,12 +143,21 @@ public class RegistrationManagerImpl implements RegistrationManager {
|
||||||
public void verifyAccount(
|
public void verifyAccount(
|
||||||
String verificationCode, String pin
|
String verificationCode, String pin
|
||||||
) throws IOException, PinLockedException, IncorrectPinException {
|
) throws IOException, PinLockedException, IncorrectPinException {
|
||||||
var sessionId = account.getSessionId(account.getNumber());
|
if (account.getPniIdentityKeyPair() == null) {
|
||||||
final var result = NumberVerificationUtils.verifyNumber(sessionId,
|
account.setPniIdentityKeyPair(KeyUtils.generateIdentityKeyPair());
|
||||||
|
}
|
||||||
|
|
||||||
|
final var aciPreKeys = generatePreKeysForType(ServiceIdType.ACI);
|
||||||
|
final var pniPreKeys = generatePreKeysForType(ServiceIdType.PNI);
|
||||||
|
final var result = NumberVerificationUtils.verifyNumber(account.getSessionId(account.getNumber()),
|
||||||
verificationCode,
|
verificationCode,
|
||||||
pin,
|
pin,
|
||||||
pinHelper,
|
pinHelper,
|
||||||
this::verifyAccountWithCode);
|
(sessionId1, verificationCode1, registrationLock) -> verifyAccountWithCode(sessionId1,
|
||||||
|
verificationCode1,
|
||||||
|
registrationLock,
|
||||||
|
aciPreKeys,
|
||||||
|
pniPreKeys));
|
||||||
final var response = result.first();
|
final var response = result.first();
|
||||||
final var masterKey = result.second();
|
final var masterKey = result.second();
|
||||||
if (masterKey == null) {
|
if (masterKey == null) {
|
||||||
|
@ -153,7 +167,7 @@ public class RegistrationManagerImpl implements RegistrationManager {
|
||||||
//accountManager.setGcmId(Optional.of(GoogleCloudMessaging.getInstance(this).register(REGISTRATION_ID)));
|
//accountManager.setGcmId(Optional.of(GoogleCloudMessaging.getInstance(this).register(REGISTRATION_ID)));
|
||||||
final var aci = ACI.parseOrNull(response.getUuid());
|
final var aci = ACI.parseOrNull(response.getUuid());
|
||||||
final var pni = PNI.parseOrNull(response.getPni());
|
final var pni = PNI.parseOrNull(response.getPni());
|
||||||
account.finishRegistration(aci, pni, masterKey, pin);
|
account.finishRegistration(aci, pni, masterKey, pin, aciPreKeys, pniPreKeys);
|
||||||
accountFileUpdater.updateAccountIdentifiers(account.getNumber(), aci);
|
accountFileUpdater.updateAccountIdentifiers(account.getNumber(), aci);
|
||||||
|
|
||||||
ManagerImpl m = null;
|
ManagerImpl m = null;
|
||||||
|
@ -228,7 +242,11 @@ public class RegistrationManagerImpl implements RegistrationManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private VerifyAccountResponse verifyAccountWithCode(
|
private VerifyAccountResponse verifyAccountWithCode(
|
||||||
final String sessionId, final String verificationCode, final String registrationLock
|
final String sessionId,
|
||||||
|
final String verificationCode,
|
||||||
|
final String registrationLock,
|
||||||
|
final PreKeyCollection aciPreKeys,
|
||||||
|
final PreKeyCollection pniPreKeys
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
try {
|
try {
|
||||||
Utils.handleResponseException(accountManager.verifyAccount(verificationCode, sessionId));
|
Utils.handleResponseException(accountManager.verifyAccount(verificationCode, sessionId));
|
||||||
|
@ -238,9 +256,41 @@ public class RegistrationManagerImpl implements RegistrationManager {
|
||||||
return Utils.handleResponseException(accountManager.registerAccount(sessionId,
|
return Utils.handleResponseException(accountManager.registerAccount(sessionId,
|
||||||
null,
|
null,
|
||||||
account.getAccountAttributes(registrationLock),
|
account.getAccountAttributes(registrationLock),
|
||||||
|
aciPreKeys,
|
||||||
|
pniPreKeys,
|
||||||
|
null,
|
||||||
true));
|
true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PreKeyCollection generatePreKeysForType(ServiceIdType serviceIdType) {
|
||||||
|
final var accountData = account.getAccountData(serviceIdType);
|
||||||
|
final var keyPair = accountData.getIdentityKeyPair();
|
||||||
|
final var preKeyMetadata = accountData.getPreKeyMetadata();
|
||||||
|
|
||||||
|
final var preKeyIdOffset = preKeyMetadata.getPreKeyIdOffset();
|
||||||
|
final var oneTimeEcPreKeys = KeyUtils.generatePreKeyRecords(preKeyIdOffset);
|
||||||
|
final var nextSignedPreKeyId = preKeyMetadata.getNextSignedPreKeyId();
|
||||||
|
final var signedPreKey = KeyUtils.generateSignedPreKeyRecord(nextSignedPreKeyId, keyPair);
|
||||||
|
|
||||||
|
final var privateKey = keyPair.getPrivateKey();
|
||||||
|
final var kyberPreKeyIdOffset = preKeyMetadata.getKyberPreKeyIdOffset();
|
||||||
|
final var oneTimeKyberPreKeys = KeyUtils.generateKyberPreKeyRecords(kyberPreKeyIdOffset, privateKey);
|
||||||
|
final var lastResortKyberPreKeyId = (kyberPreKeyIdOffset + oneTimeKyberPreKeys.size()) % PREKEY_MAXIMUM_ID;
|
||||||
|
final var lastResortKyberPreKey = KeyUtils.generateKyberPreKeyRecord(lastResortKyberPreKeyId, privateKey);
|
||||||
|
|
||||||
|
return new PreKeyCollection(keyPair,
|
||||||
|
nextSignedPreKeyId,
|
||||||
|
preKeyIdOffset,
|
||||||
|
lastResortKyberPreKeyId,
|
||||||
|
kyberPreKeyIdOffset,
|
||||||
|
serviceIdType,
|
||||||
|
keyPair.getPublicKey(),
|
||||||
|
signedPreKey,
|
||||||
|
oneTimeEcPreKeys,
|
||||||
|
lastResortKyberPreKey,
|
||||||
|
oneTimeKyberPreKeys);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
if (account != null) {
|
if (account != null) {
|
||||||
|
|
|
@ -64,6 +64,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountDataStore;
|
import org.whispersystems.signalservice.api.SignalServiceAccountDataStore;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceDataStore;
|
import org.whispersystems.signalservice.api.SignalServiceDataStore;
|
||||||
import org.whispersystems.signalservice.api.account.AccountAttributes;
|
import org.whispersystems.signalservice.api.account.AccountAttributes;
|
||||||
|
import org.whispersystems.signalservice.api.account.PreKeyCollection;
|
||||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
||||||
import org.whispersystems.signalservice.api.kbs.MasterKey;
|
import org.whispersystems.signalservice.api.kbs.MasterKey;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ACI;
|
||||||
|
@ -299,6 +300,26 @@ public class SignalAccount implements Closeable {
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setPreKeys(ServiceIdType serviceIdType, PreKeyCollection preKeyCollection) {
|
||||||
|
final var accountData = getAccountData(serviceIdType);
|
||||||
|
final var preKeyMetadata = accountData.getPreKeyMetadata();
|
||||||
|
preKeyMetadata.nextSignedPreKeyId = preKeyCollection.getNextSignedPreKeyId();
|
||||||
|
preKeyMetadata.preKeyIdOffset = preKeyCollection.getEcOneTimePreKeyIdOffset();
|
||||||
|
preKeyMetadata.kyberPreKeyIdOffset = preKeyCollection.getOneTimeKyberPreKeyIdOffset();
|
||||||
|
preKeyMetadata.activeLastResortKyberPreKeyId = preKeyCollection.getLastResortKyberPreKeyId();
|
||||||
|
|
||||||
|
accountData.getPreKeyStore().removeAllPreKeys();
|
||||||
|
accountData.getSignedPreKeyStore().removeAllSignedPreKeys();
|
||||||
|
accountData.getKyberPreKeyStore().removeAllKyberPreKeys();
|
||||||
|
|
||||||
|
addPreKeys(serviceIdType, preKeyCollection.getOneTimeEcPreKeys());
|
||||||
|
addSignedPreKey(serviceIdType, preKeyCollection.getSignedPreKey());
|
||||||
|
addKyberPreKeys(serviceIdType, preKeyCollection.getOneTimeKyberPreKeys());
|
||||||
|
addLastResortKyberPreKey(serviceIdType, preKeyCollection.getLastResortKyberPreKey());
|
||||||
|
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
private static SignalAccount createLinkedAccount(
|
private static SignalAccount createLinkedAccount(
|
||||||
File dataPath,
|
File dataPath,
|
||||||
String accountPath,
|
String accountPath,
|
||||||
|
@ -394,7 +415,7 @@ public class SignalAccount implements Closeable {
|
||||||
setProfileKey(KeyUtils.createProfileKey());
|
setProfileKey(KeyUtils.createProfileKey());
|
||||||
}
|
}
|
||||||
getProfileStore().storeProfileKey(getSelfRecipientId(), getProfileKey());
|
getProfileStore().storeProfileKey(getSelfRecipientId(), getProfileKey());
|
||||||
if (isPrimaryDevice() && getPniIdentityKeyPair() == null && getPni() != null) {
|
if (isPrimaryDevice() && getPniIdentityKeyPair() == null) {
|
||||||
setPniIdentityKeyPair(KeyUtils.generateIdentityKeyPair());
|
setPniIdentityKeyPair(KeyUtils.generateIdentityKeyPair());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1053,6 +1074,10 @@ public class SignalAccount implements Closeable {
|
||||||
public void addPreKeys(ServiceIdType serviceIdType, List<PreKeyRecord> records) {
|
public void addPreKeys(ServiceIdType serviceIdType, List<PreKeyRecord> records) {
|
||||||
final var accountData = getAccountData(serviceIdType);
|
final var accountData = getAccountData(serviceIdType);
|
||||||
final var preKeyMetadata = accountData.getPreKeyMetadata();
|
final var preKeyMetadata = accountData.getPreKeyMetadata();
|
||||||
|
logger.debug("Adding {} {} pre keys with offset {}",
|
||||||
|
records.size(),
|
||||||
|
serviceIdType,
|
||||||
|
preKeyMetadata.preKeyIdOffset);
|
||||||
for (var record : records) {
|
for (var record : records) {
|
||||||
if (preKeyMetadata.preKeyIdOffset != record.getId()) {
|
if (preKeyMetadata.preKeyIdOffset != record.getId()) {
|
||||||
logger.error("Invalid pre key id {}, expected {}", record.getId(), preKeyMetadata.preKeyIdOffset);
|
logger.error("Invalid pre key id {}, expected {}", record.getId(), preKeyMetadata.preKeyIdOffset);
|
||||||
|
@ -1067,6 +1092,7 @@ public class SignalAccount implements Closeable {
|
||||||
public void addSignedPreKey(ServiceIdType serviceIdType, SignedPreKeyRecord record) {
|
public void addSignedPreKey(ServiceIdType serviceIdType, SignedPreKeyRecord record) {
|
||||||
final var accountData = getAccountData(serviceIdType);
|
final var accountData = getAccountData(serviceIdType);
|
||||||
final var preKeyMetadata = accountData.getPreKeyMetadata();
|
final var preKeyMetadata = accountData.getPreKeyMetadata();
|
||||||
|
logger.debug("Adding {} signed pre key with offset {}", serviceIdType, preKeyMetadata.nextSignedPreKeyId);
|
||||||
if (preKeyMetadata.nextSignedPreKeyId != record.getId()) {
|
if (preKeyMetadata.nextSignedPreKeyId != record.getId()) {
|
||||||
logger.error("Invalid signed pre key id {}, expected {}",
|
logger.error("Invalid signed pre key id {}, expected {}",
|
||||||
record.getId(),
|
record.getId(),
|
||||||
|
@ -1088,6 +1114,10 @@ public class SignalAccount implements Closeable {
|
||||||
public void addKyberPreKeys(ServiceIdType serviceIdType, List<KyberPreKeyRecord> records) {
|
public void addKyberPreKeys(ServiceIdType serviceIdType, List<KyberPreKeyRecord> records) {
|
||||||
final var accountData = getAccountData(serviceIdType);
|
final var accountData = getAccountData(serviceIdType);
|
||||||
final var preKeyMetadata = accountData.getPreKeyMetadata();
|
final var preKeyMetadata = accountData.getPreKeyMetadata();
|
||||||
|
logger.debug("Adding {} {} kyber pre keys with offset {}",
|
||||||
|
records.size(),
|
||||||
|
serviceIdType,
|
||||||
|
preKeyMetadata.kyberPreKeyIdOffset);
|
||||||
for (var record : records) {
|
for (var record : records) {
|
||||||
if (preKeyMetadata.kyberPreKeyIdOffset != record.getId()) {
|
if (preKeyMetadata.kyberPreKeyIdOffset != record.getId()) {
|
||||||
logger.error("Invalid kyber pre key id {}, expected {}",
|
logger.error("Invalid kyber pre key id {}, expected {}",
|
||||||
|
@ -1104,6 +1134,9 @@ public class SignalAccount implements Closeable {
|
||||||
public void addLastResortKyberPreKey(ServiceIdType serviceIdType, KyberPreKeyRecord record) {
|
public void addLastResortKyberPreKey(ServiceIdType serviceIdType, KyberPreKeyRecord record) {
|
||||||
final var accountData = getAccountData(serviceIdType);
|
final var accountData = getAccountData(serviceIdType);
|
||||||
final var preKeyMetadata = accountData.getPreKeyMetadata();
|
final var preKeyMetadata = accountData.getPreKeyMetadata();
|
||||||
|
logger.debug("Adding {} last resort kyber pre key with offset {}",
|
||||||
|
serviceIdType,
|
||||||
|
preKeyMetadata.kyberPreKeyIdOffset);
|
||||||
if (preKeyMetadata.kyberPreKeyIdOffset != record.getId()) {
|
if (preKeyMetadata.kyberPreKeyIdOffset != record.getId()) {
|
||||||
logger.error("Invalid last resort kyber pre key id {}, expected {}",
|
logger.error("Invalid last resort kyber pre key id {}, expected {}",
|
||||||
record.getId(),
|
record.getId(),
|
||||||
|
@ -1606,7 +1639,14 @@ public class SignalAccount implements Closeable {
|
||||||
return phoneNumberUnlisted == null || !phoneNumberUnlisted;
|
return phoneNumberUnlisted == null || !phoneNumberUnlisted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finishRegistration(final ACI aci, final PNI pni, final MasterKey masterKey, final String pin) {
|
public void finishRegistration(
|
||||||
|
final ACI aci,
|
||||||
|
final PNI pni,
|
||||||
|
final MasterKey masterKey,
|
||||||
|
final String pin,
|
||||||
|
final PreKeyCollection aciPreKeys,
|
||||||
|
final PreKeyCollection pniPreKeys
|
||||||
|
) {
|
||||||
this.pinMasterKey = masterKey;
|
this.pinMasterKey = masterKey;
|
||||||
this.storageManifestVersion = -1;
|
this.storageManifestVersion = -1;
|
||||||
this.setStorageManifest(null);
|
this.setStorageManifest(null);
|
||||||
|
@ -1621,17 +1661,14 @@ public class SignalAccount implements Closeable {
|
||||||
this.lastReceiveTimestamp = 0;
|
this.lastReceiveTimestamp = 0;
|
||||||
save();
|
save();
|
||||||
|
|
||||||
clearAllPreKeys();
|
setPreKeys(ServiceIdType.ACI, aciPreKeys);
|
||||||
|
setPreKeys(ServiceIdType.PNI, pniPreKeys);
|
||||||
aciAccountData.getSessionStore().archiveAllSessions();
|
aciAccountData.getSessionStore().archiveAllSessions();
|
||||||
pniAccountData.getSessionStore().archiveAllSessions();
|
pniAccountData.getSessionStore().archiveAllSessions();
|
||||||
getSenderKeyStore().deleteAll();
|
getSenderKeyStore().deleteAll();
|
||||||
getRecipientTrustedResolver().resolveSelfRecipientTrusted(getSelfRecipientAddress());
|
getRecipientTrustedResolver().resolveSelfRecipientTrusted(getSelfRecipientAddress());
|
||||||
trustSelfIdentity(ServiceIdType.ACI);
|
trustSelfIdentity(ServiceIdType.ACI);
|
||||||
if (getPniIdentityKeyPair() == null) {
|
trustSelfIdentity(ServiceIdType.PNI);
|
||||||
setPniIdentityKeyPair(KeyUtils.generateIdentityKeyPair());
|
|
||||||
} else {
|
|
||||||
trustSelfIdentity(ServiceIdType.PNI);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trustSelfIdentity(ServiceIdType serviceIdType) {
|
private void trustSelfIdentity(ServiceIdType serviceIdType) {
|
||||||
|
@ -1699,12 +1736,28 @@ public class SignalAccount implements Closeable {
|
||||||
void call();
|
void call();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class PreKeyMetadata {
|
public static class PreKeyMetadata {
|
||||||
|
|
||||||
private int preKeyIdOffset = 1;
|
private int preKeyIdOffset = 1;
|
||||||
private int nextSignedPreKeyId = 1;
|
private int nextSignedPreKeyId = 1;
|
||||||
private int kyberPreKeyIdOffset = 1;
|
private int kyberPreKeyIdOffset = 1;
|
||||||
private int activeLastResortKyberPreKeyId = -1;
|
private int activeLastResortKyberPreKeyId = -1;
|
||||||
|
|
||||||
|
public int getPreKeyIdOffset() {
|
||||||
|
return preKeyIdOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNextSignedPreKeyId() {
|
||||||
|
return nextSignedPreKeyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKyberPreKeyIdOffset() {
|
||||||
|
return kyberPreKeyIdOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActiveLastResortKyberPreKeyId() {
|
||||||
|
return activeLastResortKyberPreKeyId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AccountData {
|
public class AccountData {
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.asamk.signal.manager.config.ServiceConfig.PREKEY_BATCH_SIZE;
|
||||||
import static org.asamk.signal.manager.config.ServiceConfig.PREKEY_MAXIMUM_ID;
|
import static org.asamk.signal.manager.config.ServiceConfig.PREKEY_MAXIMUM_ID;
|
||||||
|
|
||||||
public class KeyUtils {
|
public class KeyUtils {
|
||||||
|
@ -47,9 +48,9 @@ public class KeyUtils {
|
||||||
return new IdentityKeyPair(djbIdentityKey, djbPrivateKey);
|
return new IdentityKeyPair(djbIdentityKey, djbPrivateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<PreKeyRecord> generatePreKeyRecords(final int offset, final int batchSize) {
|
public static List<PreKeyRecord> generatePreKeyRecords(final int offset) {
|
||||||
var records = new ArrayList<PreKeyRecord>(batchSize);
|
var records = new ArrayList<PreKeyRecord>(PREKEY_BATCH_SIZE);
|
||||||
for (var i = 0; i < batchSize; i++) {
|
for (var i = 0; i < PREKEY_BATCH_SIZE; i++) {
|
||||||
var preKeyId = (offset + i) % PREKEY_MAXIMUM_ID;
|
var preKeyId = (offset + i) % PREKEY_MAXIMUM_ID;
|
||||||
var keyPair = Curve.generateKeyPair();
|
var keyPair = Curve.generateKeyPair();
|
||||||
var record = new PreKeyRecord(preKeyId, keyPair);
|
var record = new PreKeyRecord(preKeyId, keyPair);
|
||||||
|
@ -60,7 +61,7 @@ public class KeyUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SignedPreKeyRecord generateSignedPreKeyRecord(
|
public static SignedPreKeyRecord generateSignedPreKeyRecord(
|
||||||
final IdentityKeyPair identityKeyPair, final int signedPreKeyId
|
final int signedPreKeyId, final IdentityKeyPair identityKeyPair
|
||||||
) {
|
) {
|
||||||
var keyPair = Curve.generateKeyPair();
|
var keyPair = Curve.generateKeyPair();
|
||||||
byte[] signature;
|
byte[] signature;
|
||||||
|
@ -73,10 +74,10 @@ public class KeyUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<KyberPreKeyRecord> generateKyberPreKeyRecords(
|
public static List<KyberPreKeyRecord> generateKyberPreKeyRecords(
|
||||||
final int offset, final int batchSize, final ECPrivateKey privateKey
|
final int offset, final ECPrivateKey privateKey
|
||||||
) {
|
) {
|
||||||
var records = new ArrayList<KyberPreKeyRecord>(batchSize);
|
var records = new ArrayList<KyberPreKeyRecord>(PREKEY_BATCH_SIZE);
|
||||||
for (var i = 0; i < batchSize; i++) {
|
for (var i = 0; i < PREKEY_BATCH_SIZE; i++) {
|
||||||
var preKeyId = (offset + i) % PREKEY_MAXIMUM_ID;
|
var preKeyId = (offset + i) % PREKEY_MAXIMUM_ID;
|
||||||
records.add(generateKyberPreKeyRecord(preKeyId, privateKey));
|
records.add(generateKyberPreKeyRecord(preKeyId, privateKey));
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ dependencyResolutionManagement {
|
||||||
library("logback", "ch.qos.logback", "logback-classic").version("1.4.8")
|
library("logback", "ch.qos.logback", "logback-classic").version("1.4.8")
|
||||||
|
|
||||||
|
|
||||||
library("signalservice", "com.github.turasa", "signal-service-java").version("2.15.3_unofficial_73")
|
library("signalservice", "com.github.turasa", "signal-service-java").version("2.15.3_unofficial_74")
|
||||||
library("protobuf", "com.google.protobuf", "protobuf-javalite").version("3.23.0")
|
library("protobuf", "com.google.protobuf", "protobuf-javalite").version("3.23.0")
|
||||||
library("sqlite", "org.xerial", "sqlite-jdbc").version("3.42.0.0")
|
library("sqlite", "org.xerial", "sqlite-jdbc").version("3.42.0.0")
|
||||||
library("hikari", "com.zaxxer", "HikariCP").version("5.0.1")
|
library("hikari", "com.zaxxer", "HikariCP").version("5.0.1")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue