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
2c44b65e9f
commit
f3b2df62da
21 changed files with 273 additions and 120 deletions
|
@ -12,6 +12,10 @@
|
||||||
"name":"java.lang.Boolean",
|
"name":"java.lang.Boolean",
|
||||||
"methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]
|
"methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"java.lang.Class",
|
||||||
|
"methods":[{"name":"getCanonicalName","parameterTypes":[] }]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"java.lang.ClassLoader",
|
"name":"java.lang.ClassLoader",
|
||||||
"methods":[
|
"methods":[
|
||||||
|
@ -30,6 +34,10 @@
|
||||||
{
|
{
|
||||||
"name":"java.lang.NoSuchMethodError"
|
"name":"java.lang.NoSuchMethodError"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"java.lang.Throwable",
|
||||||
|
"methods":[{"name":"getMessage","parameterTypes":[] }]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"java.lang.UnsatisfiedLinkError",
|
"name":"java.lang.UnsatisfiedLinkError",
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
|
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
|
||||||
|
@ -115,6 +123,9 @@
|
||||||
"name":"org.whispersystems.libsignal.InvalidKeyException",
|
"name":"org.whispersystems.libsignal.InvalidKeyException",
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
|
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"org.whispersystems.libsignal.InvalidKeyIdException"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.libsignal.InvalidMessageException",
|
"name":"org.whispersystems.libsignal.InvalidMessageException",
|
||||||
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
|
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
|
||||||
|
|
|
@ -2023,11 +2023,6 @@
|
||||||
"queryAllDeclaredMethods":true,
|
"queryAllDeclaredMethods":true,
|
||||||
"queryAllDeclaredConstructors":true
|
"queryAllDeclaredConstructors":true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name":"org.whispersystems.signalservice.api.push.AccountIdentifier",
|
|
||||||
"allDeclaredFields":true,
|
|
||||||
"queryAllDeclaredMethods":true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.api.push.SignedPreKeyEntity",
|
"name":"org.whispersystems.signalservice.api.push.SignedPreKeyEntity",
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
|
@ -2314,16 +2309,19 @@
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.push.ProvisioningProtos$ProvisionMessage",
|
"name":"org.whispersystems.signalservice.internal.push.ProvisioningProtos$ProvisionMessage",
|
||||||
"fields":[
|
"fields":[
|
||||||
|
{"name":"aciIdentityKeyPrivate_"},
|
||||||
|
{"name":"aciIdentityKeyPublic_"},
|
||||||
|
{"name":"aci_"},
|
||||||
{"name":"bitField0_"},
|
{"name":"bitField0_"},
|
||||||
{"name":"identityKeyPrivate_"},
|
|
||||||
{"name":"identityKeyPublic_"},
|
|
||||||
{"name":"number_"},
|
{"name":"number_"},
|
||||||
|
{"name":"pniIdentityKeyPrivate_"},
|
||||||
|
{"name":"pniIdentityKeyPublic_"},
|
||||||
|
{"name":"pni_"},
|
||||||
{"name":"profileKey_"},
|
{"name":"profileKey_"},
|
||||||
{"name":"provisioningCode_"},
|
{"name":"provisioningCode_"},
|
||||||
{"name":"provisioningVersion_"},
|
{"name":"provisioningVersion_"},
|
||||||
{"name":"readReceipts_"},
|
{"name":"readReceipts_"},
|
||||||
{"name":"userAgent_"},
|
{"name":"userAgent_"}
|
||||||
{"name":"uuid_"}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2686,6 +2684,7 @@
|
||||||
"fields":[
|
"fields":[
|
||||||
{"name":"bitField0_"},
|
{"name":"bitField0_"},
|
||||||
{"name":"content_"},
|
{"name":"content_"},
|
||||||
|
{"name":"destinationUuid_"},
|
||||||
{"name":"legacyMessage_"},
|
{"name":"legacyMessage_"},
|
||||||
{"name":"relay_"},
|
{"name":"relay_"},
|
||||||
{"name":"serverGuid_"},
|
{"name":"serverGuid_"},
|
||||||
|
@ -2852,6 +2851,14 @@
|
||||||
{"name":"type_"}
|
{"name":"type_"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"org.whispersystems.signalservice.internal.push.SignalServiceProtos$SyncMessage$PniIdentity",
|
||||||
|
"fields":[
|
||||||
|
{"name":"bitField0_"},
|
||||||
|
{"name":"privateKey_"},
|
||||||
|
{"name":"publicKey_"}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"org.whispersystems.signalservice.internal.push.SignalServiceProtos$SyncMessage$Read",
|
"name":"org.whispersystems.signalservice.internal.push.SignalServiceProtos$SyncMessage$Read",
|
||||||
"fields":[
|
"fields":[
|
||||||
|
|
|
@ -14,7 +14,7 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.github.turasa", "signal-service-java", "2.15.3_unofficial_41")
|
implementation("com.github.turasa", "signal-service-java", "2.15.3_unofficial_42")
|
||||||
implementation("com.fasterxml.jackson.core", "jackson-databind", "2.13.1")
|
implementation("com.fasterxml.jackson.core", "jackson-databind", "2.13.1")
|
||||||
implementation("com.google.protobuf", "protobuf-javalite", "3.11.4")
|
implementation("com.google.protobuf", "protobuf-javalite", "3.11.4")
|
||||||
implementation("org.bouncycastle", "bcprov-jdk15on", "1.70")
|
implementation("org.bouncycastle", "bcprov-jdk15on", "1.70")
|
||||||
|
|
|
@ -278,7 +278,7 @@ class ManagerImpl implements Manager {
|
||||||
public List<Device> getLinkedDevices() throws IOException {
|
public List<Device> getLinkedDevices() throws IOException {
|
||||||
var devices = dependencies.getAccountManager().getDevices();
|
var devices = dependencies.getAccountManager().getDevices();
|
||||||
account.setMultiDevice(devices.size() > 1);
|
account.setMultiDevice(devices.size() > 1);
|
||||||
var identityKey = account.getIdentityKeyPair().getPrivateKey();
|
var identityKey = account.getAciIdentityKeyPair().getPrivateKey();
|
||||||
return devices.stream().map(d -> {
|
return devices.stream().map(d -> {
|
||||||
String deviceName = d.getName();
|
String deviceName = d.getName();
|
||||||
if (deviceName != null) {
|
if (deviceName != null) {
|
||||||
|
@ -568,7 +568,7 @@ class ManagerImpl implements Manager {
|
||||||
final var recipientId = context.getRecipientHelper().resolveRecipient(m.recipient());
|
final var recipientId = context.getRecipientHelper().resolveRecipient(m.recipient());
|
||||||
mentions.add(new SignalServiceDataMessage.Mention(context.getRecipientHelper()
|
mentions.add(new SignalServiceDataMessage.Mention(context.getRecipientHelper()
|
||||||
.resolveSignalServiceAddress(recipientId)
|
.resolveSignalServiceAddress(recipientId)
|
||||||
.getAci(), m.start(), m.length()));
|
.getServiceId(), m.start(), m.length()));
|
||||||
}
|
}
|
||||||
return mentions;
|
return mentions;
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ class ProvisioningManagerImpl implements ProvisioningManager {
|
||||||
groupsV2Operations = null;
|
groupsV2Operations = null;
|
||||||
}
|
}
|
||||||
accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||||
new DynamicCredentialsProvider(null, null, password, SignalServiceAddress.DEFAULT_DEVICE_ID),
|
new DynamicCredentialsProvider(null, null, null, password, SignalServiceAddress.DEFAULT_DEVICE_ID),
|
||||||
userAgent,
|
userAgent,
|
||||||
groupsV2Operations,
|
groupsV2Operations,
|
||||||
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
|
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
|
||||||
|
@ -97,6 +97,7 @@ class ProvisioningManagerImpl implements ProvisioningManager {
|
||||||
var ret = accountManager.getNewDeviceRegistration(tempIdentityKey);
|
var ret = accountManager.getNewDeviceRegistration(tempIdentityKey);
|
||||||
var number = ret.getNumber();
|
var number = ret.getNumber();
|
||||||
var aci = ret.getAci();
|
var aci = ret.getAci();
|
||||||
|
var pni = ret.getPni();
|
||||||
|
|
||||||
logger.info("Received link information from {}, linking in progress ...", number);
|
logger.info("Received link information from {}, linking in progress ...", number);
|
||||||
|
|
||||||
|
@ -117,7 +118,7 @@ class ProvisioningManagerImpl implements ProvisioningManager {
|
||||||
|
|
||||||
var encryptedDeviceName = deviceName == null
|
var encryptedDeviceName = deviceName == null
|
||||||
? null
|
? null
|
||||||
: DeviceNameUtil.encryptDeviceName(deviceName, ret.getIdentity().getPrivateKey());
|
: DeviceNameUtil.encryptDeviceName(deviceName, ret.getAciIdentity().getPrivateKey());
|
||||||
|
|
||||||
logger.debug("Finishing new device registration");
|
logger.debug("Finishing new device registration");
|
||||||
var deviceId = accountManager.finishNewDeviceRegistration(ret.getProvisioningCode(),
|
var deviceId = accountManager.finishNewDeviceRegistration(ret.getProvisioningCode(),
|
||||||
|
@ -135,10 +136,12 @@ class ProvisioningManagerImpl implements ProvisioningManager {
|
||||||
accountPath,
|
accountPath,
|
||||||
number,
|
number,
|
||||||
aci,
|
aci,
|
||||||
|
pni,
|
||||||
password,
|
password,
|
||||||
encryptedDeviceName,
|
encryptedDeviceName,
|
||||||
deviceId,
|
deviceId,
|
||||||
ret.getIdentity(),
|
ret.getAciIdentity(),
|
||||||
|
ret.getPniIdentity(),
|
||||||
registrationId,
|
registrationId,
|
||||||
profileKey,
|
profileKey,
|
||||||
TrustNewIdentity.ON_FIRST_USE);
|
TrustNewIdentity.ON_FIRST_USE);
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
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.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.internal.ServiceResponse;
|
import org.whispersystems.signalservice.internal.ServiceResponse;
|
||||||
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
|
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
|
||||||
|
@ -79,7 +80,7 @@ class RegistrationManagerImpl implements RegistrationManager {
|
||||||
this.accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
this.accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||||
new DynamicCredentialsProvider(
|
new DynamicCredentialsProvider(
|
||||||
// Using empty UUID, because registering doesn't work otherwise
|
// Using empty UUID, because registering doesn't work otherwise
|
||||||
null, account.getNumber(), account.getPassword(), SignalServiceAddress.DEFAULT_DEVICE_ID),
|
null, null, account.getNumber(), account.getPassword(), SignalServiceAddress.DEFAULT_DEVICE_ID),
|
||||||
userAgent,
|
userAgent,
|
||||||
groupsV2Operations,
|
groupsV2Operations,
|
||||||
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
|
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
|
||||||
|
@ -116,7 +117,8 @@ 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());
|
||||||
account.finishRegistration(aci, masterKey, pin);
|
final var pni = PNI.parseOrNull(response.getPni());
|
||||||
|
account.finishRegistration(aci, pni, masterKey, pin);
|
||||||
accountFileUpdater.updateAccountIdentifiers(account.getNumber(), aci);
|
accountFileUpdater.updateAccountIdentifiers(account.getNumber(), aci);
|
||||||
|
|
||||||
ManagerImpl m = null;
|
ManagerImpl m = null;
|
||||||
|
|
|
@ -125,14 +125,16 @@ public class SignalAccountFiles {
|
||||||
final var accountPath = accountsStore.getPathByNumber(number);
|
final var accountPath = accountsStore.getPathByNumber(number);
|
||||||
if (accountPath == null || !SignalAccount.accountFileExists(pathConfig.dataPath(), accountPath)) {
|
if (accountPath == null || !SignalAccount.accountFileExists(pathConfig.dataPath(), accountPath)) {
|
||||||
final var newAccountPath = accountPath == null ? accountsStore.addAccount(number, null) : accountPath;
|
final var newAccountPath = accountPath == null ? accountsStore.addAccount(number, null) : accountPath;
|
||||||
var identityKey = KeyUtils.generateIdentityKeyPair();
|
var aciIdentityKey = KeyUtils.generateIdentityKeyPair();
|
||||||
|
var pniIdentityKey = KeyUtils.generateIdentityKeyPair();
|
||||||
var registrationId = KeyHelper.generateRegistrationId(false);
|
var registrationId = KeyHelper.generateRegistrationId(false);
|
||||||
|
|
||||||
var profileKey = KeyUtils.createProfileKey();
|
var profileKey = KeyUtils.createProfileKey();
|
||||||
var account = SignalAccount.create(pathConfig.dataPath(),
|
var account = SignalAccount.create(pathConfig.dataPath(),
|
||||||
newAccountPath,
|
newAccountPath,
|
||||||
number,
|
number,
|
||||||
identityKey,
|
aciIdentityKey,
|
||||||
|
pniIdentityKey,
|
||||||
registrationId,
|
registrationId,
|
||||||
profileKey,
|
profileKey,
|
||||||
trustNewIdentity);
|
trustNewIdentity);
|
||||||
|
|
|
@ -88,6 +88,7 @@ public class SignalDependencies {
|
||||||
|
|
||||||
public SignalServiceAccountManager createUnauthenticatedAccountManager(String number, String password) {
|
public SignalServiceAccountManager createUnauthenticatedAccountManager(String number, String password) {
|
||||||
return new SignalServiceAccountManager(getServiceEnvironmentConfig().getSignalServiceConfiguration(),
|
return new SignalServiceAccountManager(getServiceEnvironmentConfig().getSignalServiceConfiguration(),
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
number,
|
number,
|
||||||
SignalServiceAddress.DEFAULT_DEVICE_ID,
|
SignalServiceAddress.DEFAULT_DEVICE_ID,
|
||||||
|
|
|
@ -17,10 +17,8 @@ public class RetrieveStorageDataAction implements HandleAction {
|
||||||
public void execute(Context context) throws Throwable {
|
public void execute(Context context) throws Throwable {
|
||||||
if (context.getAccount().getStorageKey() != null) {
|
if (context.getAccount().getStorageKey() != null) {
|
||||||
context.getStorageHelper().readDataFromStorage();
|
context.getStorageHelper().readDataFromStorage();
|
||||||
} else {
|
} else if (!context.getAccount().isMasterDevice()) {
|
||||||
if (!context.getAccount().isMasterDevice()) {
|
context.getSyncHelper().requestSyncKeys();
|
||||||
context.getSyncHelper().requestAllSyncData();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package org.asamk.signal.manager.actions;
|
||||||
|
|
||||||
|
import org.asamk.signal.manager.helper.Context;
|
||||||
|
|
||||||
|
public class SendPniIdentityKeyAction implements HandleAction {
|
||||||
|
|
||||||
|
private static final SendPniIdentityKeyAction INSTANCE = new SendPniIdentityKeyAction();
|
||||||
|
|
||||||
|
private SendPniIdentityKeyAction() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SendPniIdentityKeyAction create() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Context context) throws Throwable {
|
||||||
|
context.getSyncHelper().sendPniIdentity();
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.InvalidKeyException;
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
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.exceptions.AuthorizationFailedException;
|
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
||||||
import org.whispersystems.signalservice.api.util.DeviceNameUtil;
|
import org.whispersystems.signalservice.api.util.DeviceNameUtil;
|
||||||
|
|
||||||
|
@ -55,9 +56,12 @@ public class AccountHelper {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
context.getPreKeyHelper().refreshPreKeysIfNecessary();
|
context.getPreKeyHelper().refreshPreKeysIfNecessary();
|
||||||
if (account.getAci() == null) {
|
if (account.getAci() == null || account.getPni() == null) {
|
||||||
checkWhoAmiI();
|
checkWhoAmiI();
|
||||||
}
|
}
|
||||||
|
if (!account.isMasterDevice() && account.getPniIdentityKeyPair() == null) {
|
||||||
|
context.getSyncHelper().requestSyncPniIdentity();
|
||||||
|
}
|
||||||
updateAccountAttributes();
|
updateAccountAttributes();
|
||||||
} catch (AuthorizationFailedException e) {
|
} catch (AuthorizationFailedException e) {
|
||||||
account.setRegistered(false);
|
account.setRegistered(false);
|
||||||
|
@ -69,16 +73,18 @@ public class AccountHelper {
|
||||||
final var whoAmI = dependencies.getAccountManager().getWhoAmI();
|
final var whoAmI = dependencies.getAccountManager().getWhoAmI();
|
||||||
final var number = whoAmI.getNumber();
|
final var number = whoAmI.getNumber();
|
||||||
final var aci = ACI.parseOrNull(whoAmI.getAci());
|
final var aci = ACI.parseOrNull(whoAmI.getAci());
|
||||||
if (number.equals(account.getNumber()) && aci.equals(account.getAci())) {
|
final var pni = PNI.parseOrNull(whoAmI.getPni());
|
||||||
|
if (number.equals(account.getNumber()) && aci.equals(account.getAci()) && pni.equals(account.getPni())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSelfIdentifiers(number, aci);
|
updateSelfIdentifiers(number, aci, pni);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSelfIdentifiers(final String number, final ACI aci) {
|
private void updateSelfIdentifiers(final String number, final ACI aci, final PNI pni) {
|
||||||
account.setNumber(number);
|
account.setNumber(number);
|
||||||
account.setAci(aci);
|
account.setAci(aci);
|
||||||
|
account.setPni(pni);
|
||||||
account.getRecipientStore().resolveSelfRecipientTrusted(account.getSelfRecipientAddress());
|
account.getRecipientStore().resolveSelfRecipientTrusted(account.getSelfRecipientAddress());
|
||||||
// TODO check and update remote storage
|
// TODO check and update remote storage
|
||||||
context.getUnidentifiedAccessHelper().rotateSenderCertificates();
|
context.getUnidentifiedAccessHelper().rotateSenderCertificates();
|
||||||
|
@ -103,11 +109,11 @@ public class AccountHelper {
|
||||||
(verificationCode1, registrationLock) -> dependencies.getAccountManager()
|
(verificationCode1, registrationLock) -> dependencies.getAccountManager()
|
||||||
.changeNumber(verificationCode1, newNumber, registrationLock));
|
.changeNumber(verificationCode1, newNumber, registrationLock));
|
||||||
// TODO handle response
|
// TODO handle response
|
||||||
updateSelfIdentifiers(newNumber, account.getAci());
|
updateSelfIdentifiers(newNumber, account.getAci(), PNI.parseOrThrow(result.first().getPni()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDeviceName(String deviceName) {
|
public void setDeviceName(String deviceName) {
|
||||||
final var privateKey = account.getIdentityKeyPair().getPrivateKey();
|
final var privateKey = account.getAciIdentityKeyPair().getPrivateKey();
|
||||||
final var encryptedDeviceName = DeviceNameUtil.encryptDeviceName(deviceName, privateKey);
|
final var encryptedDeviceName = DeviceNameUtil.encryptDeviceName(deviceName, privateKey);
|
||||||
account.setEncryptedDeviceName(encryptedDeviceName);
|
account.setEncryptedDeviceName(encryptedDeviceName);
|
||||||
}
|
}
|
||||||
|
@ -127,15 +133,15 @@ public class AccountHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addDevice(DeviceLinkInfo deviceLinkInfo) throws IOException, InvalidDeviceLinkException {
|
public void addDevice(DeviceLinkInfo deviceLinkInfo) throws IOException, InvalidDeviceLinkException {
|
||||||
var identityKeyPair = account.getIdentityKeyPair();
|
|
||||||
var verificationCode = dependencies.getAccountManager().getNewDeviceVerificationCode();
|
var verificationCode = dependencies.getAccountManager().getNewDeviceVerificationCode();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dependencies.getAccountManager()
|
dependencies.getAccountManager()
|
||||||
.addDevice(deviceLinkInfo.deviceIdentifier(),
|
.addDevice(deviceLinkInfo.deviceIdentifier(),
|
||||||
deviceLinkInfo.deviceKey(),
|
deviceLinkInfo.deviceKey(),
|
||||||
identityKeyPair,
|
account.getAciIdentityKeyPair(),
|
||||||
Optional.of(account.getProfileKey().serialize()),
|
account.getPniIdentityKeyPair(),
|
||||||
|
account.getProfileKey(),
|
||||||
verificationCode);
|
verificationCode);
|
||||||
} catch (InvalidKeyException e) {
|
} catch (InvalidKeyException e) {
|
||||||
throw new InvalidDeviceLinkException("Invalid device link", e);
|
throw new InvalidDeviceLinkException("Invalid device link", e);
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException;
|
import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException;
|
import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ACI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||||
|
|
||||||
|
@ -150,7 +151,7 @@ class GroupV2Helper {
|
||||||
final var memberList = new ArrayList<>(members);
|
final var memberList = new ArrayList<>(members);
|
||||||
final var credentials = context.getProfileHelper().getRecipientProfileKeyCredential(memberList).stream();
|
final var credentials = context.getProfileHelper().getRecipientProfileKeyCredential(memberList).stream();
|
||||||
final var uuids = memberList.stream()
|
final var uuids = memberList.stream()
|
||||||
.map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getAci().uuid());
|
.map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getServiceId().uuid());
|
||||||
var candidates = Utils.zip(uuids,
|
var candidates = Utils.zip(uuids,
|
||||||
credentials,
|
credentials,
|
||||||
(uuid, credential) -> new GroupCandidate(uuid, Optional.fromNullable(credential)))
|
(uuid, credential) -> new GroupCandidate(uuid, Optional.fromNullable(credential)))
|
||||||
|
@ -218,7 +219,7 @@ class GroupV2Helper {
|
||||||
final var memberList = new ArrayList<>(newMembers);
|
final var memberList = new ArrayList<>(newMembers);
|
||||||
final var credentials = context.getProfileHelper().getRecipientProfileKeyCredential(memberList).stream();
|
final var credentials = context.getProfileHelper().getRecipientProfileKeyCredential(memberList).stream();
|
||||||
final var uuids = memberList.stream()
|
final var uuids = memberList.stream()
|
||||||
.map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getAci().uuid());
|
.map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getServiceId().uuid());
|
||||||
var candidates = Utils.zip(uuids,
|
var candidates = Utils.zip(uuids,
|
||||||
credentials,
|
credentials,
|
||||||
(uuid, credential) -> new GroupCandidate(uuid, Optional.fromNullable(credential)))
|
(uuid, credential) -> new GroupCandidate(uuid, Optional.fromNullable(credential)))
|
||||||
|
@ -245,8 +246,8 @@ class GroupV2Helper {
|
||||||
|
|
||||||
final var adminUuids = membersToMakeAdmin.stream()
|
final var adminUuids = membersToMakeAdmin.stream()
|
||||||
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
|
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
|
||||||
.map(SignalServiceAddress::getAci)
|
.map(SignalServiceAddress::getServiceId)
|
||||||
.map(ACI::uuid)
|
.map(ServiceId::uuid)
|
||||||
.toList();
|
.toList();
|
||||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||||
return commitChange(groupInfoV2,
|
return commitChange(groupInfoV2,
|
||||||
|
@ -258,8 +259,8 @@ class GroupV2Helper {
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
final var memberUuids = members.stream()
|
final var memberUuids = members.stream()
|
||||||
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
|
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
|
||||||
.map(SignalServiceAddress::getAci)
|
.map(SignalServiceAddress::getServiceId)
|
||||||
.map(ACI::uuid)
|
.map(ServiceId::uuid)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
return ejectMembers(groupInfoV2, memberUuids);
|
return ejectMembers(groupInfoV2, memberUuids);
|
||||||
}
|
}
|
||||||
|
@ -270,8 +271,8 @@ class GroupV2Helper {
|
||||||
var pendingMembersList = groupInfoV2.getGroup().getPendingMembersList();
|
var pendingMembersList = groupInfoV2.getGroup().getPendingMembersList();
|
||||||
final var memberUuids = members.stream()
|
final var memberUuids = members.stream()
|
||||||
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
|
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
|
||||||
.map(SignalServiceAddress::getAci)
|
.map(SignalServiceAddress::getServiceId)
|
||||||
.map(ACI::uuid)
|
.map(ServiceId::uuid)
|
||||||
.map(uuid -> DecryptedGroupUtil.findPendingByUuid(pendingMembersList, uuid))
|
.map(uuid -> DecryptedGroupUtil.findPendingByUuid(pendingMembersList, uuid))
|
||||||
.filter(Optional::isPresent)
|
.filter(Optional::isPresent)
|
||||||
.map(Optional::get)
|
.map(Optional::get)
|
||||||
|
@ -343,7 +344,7 @@ class GroupV2Helper {
|
||||||
|
|
||||||
change.setSourceUuid(context.getRecipientHelper()
|
change.setSourceUuid(context.getRecipientHelper()
|
||||||
.resolveSignalServiceAddress(selfRecipientId)
|
.resolveSignalServiceAddress(selfRecipientId)
|
||||||
.getAci()
|
.getServiceId()
|
||||||
.toByteString());
|
.toByteString());
|
||||||
|
|
||||||
return commitChange(groupSecretParams, decryptedGroupJoinInfo.getRevision(), change, groupLinkPassword);
|
return commitChange(groupSecretParams, decryptedGroupJoinInfo.getRevision(), change, groupLinkPassword);
|
||||||
|
@ -360,7 +361,7 @@ class GroupV2Helper {
|
||||||
|
|
||||||
final var change = groupOperations.createAcceptInviteChange(profileKeyCredential);
|
final var change = groupOperations.createAcceptInviteChange(profileKeyCredential);
|
||||||
|
|
||||||
final var aci = context.getRecipientHelper().resolveSignalServiceAddress(selfRecipientId).getAci();
|
final var aci = context.getRecipientHelper().resolveSignalServiceAddress(selfRecipientId).getServiceId();
|
||||||
change.setSourceUuid(aci.toByteString());
|
change.setSourceUuid(aci.toByteString());
|
||||||
|
|
||||||
return commitChange(groupInfoV2, change);
|
return commitChange(groupInfoV2, change);
|
||||||
|
@ -372,7 +373,7 @@ class GroupV2Helper {
|
||||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||||
final var address = context.getRecipientHelper().resolveSignalServiceAddress(recipientId);
|
final var address = context.getRecipientHelper().resolveSignalServiceAddress(recipientId);
|
||||||
final var newRole = admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT;
|
final var newRole = admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT;
|
||||||
final var change = groupOperations.createChangeMemberRole(address.getAci().uuid(), newRole);
|
final var change = groupOperations.createChangeMemberRole(address.getServiceId().uuid(), newRole);
|
||||||
return commitChange(groupInfoV2, change);
|
return commitChange(groupInfoV2, change);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class IdentityHelper {
|
||||||
) {
|
) {
|
||||||
return Utils.computeSafetyNumber(capabilities.isUuid(),
|
return Utils.computeSafetyNumber(capabilities.isUuid(),
|
||||||
account.getSelfAddress(),
|
account.getSelfAddress(),
|
||||||
account.getIdentityKeyPair().getPublicKey(),
|
account.getAciIdentityKeyPair().getPublicKey(),
|
||||||
theirAddress,
|
theirAddress,
|
||||||
theirIdentityKey);
|
theirIdentityKey);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.asamk.signal.manager.actions.RetrieveProfileAction;
|
||||||
import org.asamk.signal.manager.actions.RetrieveStorageDataAction;
|
import org.asamk.signal.manager.actions.RetrieveStorageDataAction;
|
||||||
import org.asamk.signal.manager.actions.SendGroupInfoAction;
|
import org.asamk.signal.manager.actions.SendGroupInfoAction;
|
||||||
import org.asamk.signal.manager.actions.SendGroupInfoRequestAction;
|
import org.asamk.signal.manager.actions.SendGroupInfoRequestAction;
|
||||||
|
import org.asamk.signal.manager.actions.SendPniIdentityKeyAction;
|
||||||
import org.asamk.signal.manager.actions.SendReceiptAction;
|
import org.asamk.signal.manager.actions.SendReceiptAction;
|
||||||
import org.asamk.signal.manager.actions.SendRetryMessageRequestAction;
|
import org.asamk.signal.manager.actions.SendRetryMessageRequestAction;
|
||||||
import org.asamk.signal.manager.actions.SendSyncBlockedListAction;
|
import org.asamk.signal.manager.actions.SendSyncBlockedListAction;
|
||||||
|
@ -31,6 +32,7 @@ import org.asamk.signal.manager.storage.groups.GroupInfoV1;
|
||||||
import org.asamk.signal.manager.storage.recipients.Profile;
|
import org.asamk.signal.manager.storage.recipients.Profile;
|
||||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||||
import org.asamk.signal.manager.storage.stickers.Sticker;
|
import org.asamk.signal.manager.storage.stickers.Sticker;
|
||||||
|
import org.asamk.signal.manager.util.KeyUtils;
|
||||||
import org.signal.libsignal.metadata.ProtocolInvalidKeyException;
|
import org.signal.libsignal.metadata.ProtocolInvalidKeyException;
|
||||||
import org.signal.libsignal.metadata.ProtocolInvalidKeyIdException;
|
import org.signal.libsignal.metadata.ProtocolInvalidKeyIdException;
|
||||||
import org.signal.libsignal.metadata.ProtocolInvalidMessageException;
|
import org.signal.libsignal.metadata.ProtocolInvalidMessageException;
|
||||||
|
@ -340,6 +342,9 @@ public final class IncomingMessageHandler {
|
||||||
if (rm.isConfigurationRequest()) {
|
if (rm.isConfigurationRequest()) {
|
||||||
actions.add(SendSyncConfigurationAction.create());
|
actions.add(SendSyncConfigurationAction.create());
|
||||||
}
|
}
|
||||||
|
if (rm.isPniIdentityRequest()) {
|
||||||
|
actions.add(SendPniIdentityKeyAction.create());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (syncMessage.getGroups().isPresent()) {
|
if (syncMessage.getGroups().isPresent()) {
|
||||||
logger.warn("Received a group v1 sync message, that can't be handled anymore, ignoring.");
|
logger.warn("Received a group v1 sync message, that can't be handled anymore, ignoring.");
|
||||||
|
@ -440,6 +445,11 @@ public final class IncomingMessageHandler {
|
||||||
.get());
|
.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (syncMessage.getPniIdentity().isPresent()) {
|
||||||
|
final var pniIdentity = syncMessage.getPniIdentity().get();
|
||||||
|
account.setPniIdentityKeyPair(KeyUtils.getIdentityKeyPair(pniIdentity.getPublicKey().toByteArray(),
|
||||||
|
pniIdentity.getPrivateKey().toByteArray()));
|
||||||
|
}
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.IdentityKeyPair;
|
import org.whispersystems.libsignal.IdentityKeyPair;
|
||||||
import org.whispersystems.libsignal.state.PreKeyRecord;
|
import org.whispersystems.libsignal.state.PreKeyRecord;
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -28,17 +29,32 @@ public class PreKeyHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshPreKeysIfNecessary() throws IOException {
|
public void refreshPreKeysIfNecessary() throws IOException {
|
||||||
if (dependencies.getAccountManager().getPreKeysCount() < ServiceConfig.PREKEY_MINIMUM_COUNT) {
|
refreshPreKeysIfNecessary(ServiceIdType.ACI);
|
||||||
refreshPreKeys();
|
refreshPreKeysIfNecessary(ServiceIdType.PNI);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refreshPreKeysIfNecessary(ServiceIdType serviceIdType) throws IOException {
|
||||||
|
if (dependencies.getAccountManager().getPreKeysCount(serviceIdType) < ServiceConfig.PREKEY_MINIMUM_COUNT) {
|
||||||
|
refreshPreKeys(serviceIdType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshPreKeys() throws IOException {
|
public void refreshPreKeys() throws IOException {
|
||||||
|
refreshPreKeys(ServiceIdType.ACI);
|
||||||
|
refreshPreKeys(ServiceIdType.PNI);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refreshPreKeys(ServiceIdType serviceIdType) throws IOException {
|
||||||
|
if (serviceIdType != ServiceIdType.ACI) {
|
||||||
|
// TODO implement
|
||||||
|
return;
|
||||||
|
}
|
||||||
var oneTimePreKeys = generatePreKeys();
|
var oneTimePreKeys = generatePreKeys();
|
||||||
final var identityKeyPair = account.getIdentityKeyPair();
|
final var identityKeyPair = account.getAciIdentityKeyPair();
|
||||||
var signedPreKeyRecord = generateSignedPreKey(identityKeyPair);
|
var signedPreKeyRecord = generateSignedPreKey(identityKeyPair);
|
||||||
|
|
||||||
dependencies.getAccountManager().setPreKeys(identityKeyPair.getPublicKey(), signedPreKeyRecord, oneTimePreKeys);
|
dependencies.getAccountManager()
|
||||||
|
.setPreKeys(serviceIdType, identityKeyPair.getPublicKey(), signedPreKeyRecord, oneTimePreKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PreKeyRecord> generatePreKeys() {
|
private List<PreKeyRecord> generatePreKeys() {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package org.asamk.signal.manager.helper;
|
package org.asamk.signal.manager.helper;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
|
||||||
import org.asamk.signal.manager.api.TrustLevel;
|
import org.asamk.signal.manager.api.TrustLevel;
|
||||||
import org.asamk.signal.manager.storage.SignalAccount;
|
import org.asamk.signal.manager.storage.SignalAccount;
|
||||||
import org.asamk.signal.manager.storage.groups.GroupInfoV1;
|
import org.asamk.signal.manager.storage.groups.GroupInfoV1;
|
||||||
|
@ -49,11 +51,20 @@ public class SyncHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestAllSyncData() {
|
public void requestAllSyncData() {
|
||||||
requestSyncGroups();
|
requestSyncData(SignalServiceProtos.SyncMessage.Request.Type.GROUPS);
|
||||||
requestSyncContacts();
|
requestSyncData(SignalServiceProtos.SyncMessage.Request.Type.CONTACTS);
|
||||||
requestSyncBlocked();
|
requestSyncData(SignalServiceProtos.SyncMessage.Request.Type.BLOCKED);
|
||||||
requestSyncConfiguration();
|
requestSyncData(SignalServiceProtos.SyncMessage.Request.Type.CONFIGURATION);
|
||||||
requestSyncKeys();
|
requestSyncKeys();
|
||||||
|
requestSyncPniIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestSyncKeys() {
|
||||||
|
requestSyncData(SignalServiceProtos.SyncMessage.Request.Type.KEYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestSyncPniIdentity() {
|
||||||
|
requestSyncData(SignalServiceProtos.SyncMessage.Request.Type.PNI_IDENTITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendSyncFetchProfileMessage() {
|
public void sendSyncFetchProfileMessage() {
|
||||||
|
@ -217,6 +228,15 @@ public class SyncHelper {
|
||||||
context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forConfiguration(configurationMessage));
|
context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forConfiguration(configurationMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendPniIdentity() {
|
||||||
|
final var pniIdentityKeyPair = account.getPniIdentityKeyPair();
|
||||||
|
var pniIdentity = SignalServiceProtos.SyncMessage.PniIdentity.newBuilder()
|
||||||
|
.setPrivateKey(ByteString.copyFrom(pniIdentityKeyPair.getPrivateKey().serialize()))
|
||||||
|
.setPublicKey(ByteString.copyFrom(pniIdentityKeyPair.getPublicKey().serialize()))
|
||||||
|
.build();
|
||||||
|
context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forPniIdentity(pniIdentity));
|
||||||
|
}
|
||||||
|
|
||||||
public void handleSyncDeviceContacts(final InputStream input) throws IOException {
|
public void handleSyncDeviceContacts(final InputStream input) throws IOException {
|
||||||
final var s = new DeviceContactsInputStream(input);
|
final var s = new DeviceContactsInputStream(input);
|
||||||
DeviceContact c;
|
DeviceContact c;
|
||||||
|
@ -270,42 +290,8 @@ public class SyncHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requestSyncGroups() {
|
private void requestSyncData(final SignalServiceProtos.SyncMessage.Request.Type type) {
|
||||||
var r = SignalServiceProtos.SyncMessage.Request.newBuilder()
|
var r = SignalServiceProtos.SyncMessage.Request.newBuilder().setType(type).build();
|
||||||
.setType(SignalServiceProtos.SyncMessage.Request.Type.GROUPS)
|
|
||||||
.build();
|
|
||||||
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
|
|
||||||
context.getSendHelper().sendSyncMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void requestSyncContacts() {
|
|
||||||
var r = SignalServiceProtos.SyncMessage.Request.newBuilder()
|
|
||||||
.setType(SignalServiceProtos.SyncMessage.Request.Type.CONTACTS)
|
|
||||||
.build();
|
|
||||||
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
|
|
||||||
context.getSendHelper().sendSyncMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void requestSyncBlocked() {
|
|
||||||
var r = SignalServiceProtos.SyncMessage.Request.newBuilder()
|
|
||||||
.setType(SignalServiceProtos.SyncMessage.Request.Type.BLOCKED)
|
|
||||||
.build();
|
|
||||||
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
|
|
||||||
context.getSendHelper().sendSyncMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void requestSyncConfiguration() {
|
|
||||||
var r = SignalServiceProtos.SyncMessage.Request.newBuilder()
|
|
||||||
.setType(SignalServiceProtos.SyncMessage.Request.Type.CONFIGURATION)
|
|
||||||
.build();
|
|
||||||
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
|
|
||||||
context.getSendHelper().sendSyncMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void requestSyncKeys() {
|
|
||||||
var r = SignalServiceProtos.SyncMessage.Request.newBuilder()
|
|
||||||
.setType(SignalServiceProtos.SyncMessage.Request.Type.KEYS)
|
|
||||||
.build();
|
|
||||||
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
|
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
|
||||||
context.getSendHelper().sendSyncMessage(message);
|
context.getSendHelper().sendSyncMessage(message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,9 @@ import org.whispersystems.signalservice.api.SignalServiceDataStore;
|
||||||
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;
|
||||||
import org.whispersystems.signalservice.api.push.AccountIdentifier;
|
|
||||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||||
|
import org.whispersystems.signalservice.api.push.PNI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.storage.StorageKey;
|
import org.whispersystems.signalservice.api.storage.StorageKey;
|
||||||
import org.whispersystems.signalservice.api.util.CredentialsProvider;
|
import org.whispersystems.signalservice.api.util.CredentialsProvider;
|
||||||
|
@ -94,6 +95,7 @@ public class SignalAccount implements Closeable {
|
||||||
private String accountPath;
|
private String accountPath;
|
||||||
private String number;
|
private String number;
|
||||||
private ACI aci;
|
private ACI aci;
|
||||||
|
private PNI pni;
|
||||||
private String encryptedDeviceName;
|
private String encryptedDeviceName;
|
||||||
private int deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
private int deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||||
private boolean isMultiDevice = false;
|
private boolean isMultiDevice = false;
|
||||||
|
@ -105,7 +107,8 @@ public class SignalAccount implements Closeable {
|
||||||
private ProfileKey profileKey;
|
private ProfileKey profileKey;
|
||||||
private int preKeyIdOffset = 1;
|
private int preKeyIdOffset = 1;
|
||||||
private int nextSignedPreKeyId = 1;
|
private int nextSignedPreKeyId = 1;
|
||||||
private IdentityKeyPair identityKeyPair;
|
private IdentityKeyPair aciIdentityKeyPair;
|
||||||
|
private IdentityKeyPair pniIdentityKeyPair;
|
||||||
private int localRegistrationId;
|
private int localRegistrationId;
|
||||||
private TrustNewIdentity trustNewIdentity;
|
private TrustNewIdentity trustNewIdentity;
|
||||||
private long lastReceiveTimestamp = 0;
|
private long lastReceiveTimestamp = 0;
|
||||||
|
@ -161,7 +164,8 @@ public class SignalAccount implements Closeable {
|
||||||
File dataPath,
|
File dataPath,
|
||||||
String accountPath,
|
String accountPath,
|
||||||
String number,
|
String number,
|
||||||
IdentityKeyPair identityKey,
|
IdentityKeyPair aciIdentityKey,
|
||||||
|
IdentityKeyPair pniIdentityKey,
|
||||||
int registrationId,
|
int registrationId,
|
||||||
ProfileKey profileKey,
|
ProfileKey profileKey,
|
||||||
final TrustNewIdentity trustNewIdentity
|
final TrustNewIdentity trustNewIdentity
|
||||||
|
@ -180,7 +184,8 @@ public class SignalAccount implements Closeable {
|
||||||
signalAccount.profileKey = profileKey;
|
signalAccount.profileKey = profileKey;
|
||||||
|
|
||||||
signalAccount.dataPath = dataPath;
|
signalAccount.dataPath = dataPath;
|
||||||
signalAccount.identityKeyPair = identityKey;
|
signalAccount.aciIdentityKeyPair = aciIdentityKey;
|
||||||
|
signalAccount.pniIdentityKeyPair = pniIdentityKey;
|
||||||
signalAccount.localRegistrationId = registrationId;
|
signalAccount.localRegistrationId = registrationId;
|
||||||
signalAccount.trustNewIdentity = trustNewIdentity;
|
signalAccount.trustNewIdentity = trustNewIdentity;
|
||||||
signalAccount.groupStore = new GroupStore(getGroupCachePath(dataPath, accountPath),
|
signalAccount.groupStore = new GroupStore(getGroupCachePath(dataPath, accountPath),
|
||||||
|
@ -203,10 +208,12 @@ public class SignalAccount implements Closeable {
|
||||||
String accountPath,
|
String accountPath,
|
||||||
String number,
|
String number,
|
||||||
ACI aci,
|
ACI aci,
|
||||||
|
PNI pni,
|
||||||
String password,
|
String password,
|
||||||
String encryptedDeviceName,
|
String encryptedDeviceName,
|
||||||
int deviceId,
|
int deviceId,
|
||||||
IdentityKeyPair identityKey,
|
IdentityKeyPair aciIdentityKey,
|
||||||
|
IdentityKeyPair pniIdentityKey,
|
||||||
int registrationId,
|
int registrationId,
|
||||||
ProfileKey profileKey,
|
ProfileKey profileKey,
|
||||||
final TrustNewIdentity trustNewIdentity
|
final TrustNewIdentity trustNewIdentity
|
||||||
|
@ -218,17 +225,27 @@ public class SignalAccount implements Closeable {
|
||||||
accountPath,
|
accountPath,
|
||||||
number,
|
number,
|
||||||
aci,
|
aci,
|
||||||
|
pni,
|
||||||
password,
|
password,
|
||||||
encryptedDeviceName,
|
encryptedDeviceName,
|
||||||
deviceId,
|
deviceId,
|
||||||
identityKey,
|
aciIdentityKey,
|
||||||
|
pniIdentityKey,
|
||||||
registrationId,
|
registrationId,
|
||||||
profileKey,
|
profileKey,
|
||||||
trustNewIdentity);
|
trustNewIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
final var signalAccount = load(dataPath, accountPath, true, trustNewIdentity);
|
final var signalAccount = load(dataPath, accountPath, true, trustNewIdentity);
|
||||||
signalAccount.setProvisioningData(number, aci, password, encryptedDeviceName, deviceId, profileKey);
|
signalAccount.setProvisioningData(number,
|
||||||
|
aci,
|
||||||
|
pni,
|
||||||
|
password,
|
||||||
|
encryptedDeviceName,
|
||||||
|
deviceId,
|
||||||
|
aciIdentityKey,
|
||||||
|
pniIdentityKey,
|
||||||
|
profileKey);
|
||||||
signalAccount.getRecipientStore().resolveSelfRecipientTrusted(signalAccount.getSelfRecipientAddress());
|
signalAccount.getRecipientStore().resolveSelfRecipientTrusted(signalAccount.getSelfRecipientAddress());
|
||||||
signalAccount.getSessionStore().archiveAllSessions();
|
signalAccount.getSessionStore().archiveAllSessions();
|
||||||
signalAccount.getSenderKeyStore().deleteAll();
|
signalAccount.getSenderKeyStore().deleteAll();
|
||||||
|
@ -253,10 +270,12 @@ public class SignalAccount implements Closeable {
|
||||||
String accountPath,
|
String accountPath,
|
||||||
String number,
|
String number,
|
||||||
ACI aci,
|
ACI aci,
|
||||||
|
PNI pni,
|
||||||
String password,
|
String password,
|
||||||
String encryptedDeviceName,
|
String encryptedDeviceName,
|
||||||
int deviceId,
|
int deviceId,
|
||||||
IdentityKeyPair identityKey,
|
IdentityKeyPair aciIdentityKey,
|
||||||
|
IdentityKeyPair pniIdentityKey,
|
||||||
int registrationId,
|
int registrationId,
|
||||||
ProfileKey profileKey,
|
ProfileKey profileKey,
|
||||||
final TrustNewIdentity trustNewIdentity
|
final TrustNewIdentity trustNewIdentity
|
||||||
|
@ -267,11 +286,18 @@ public class SignalAccount implements Closeable {
|
||||||
final var pair = openFileChannel(fileName, true);
|
final var pair = openFileChannel(fileName, true);
|
||||||
var signalAccount = new SignalAccount(pair.first(), pair.second());
|
var signalAccount = new SignalAccount(pair.first(), pair.second());
|
||||||
|
|
||||||
signalAccount.setProvisioningData(number, aci, password, encryptedDeviceName, deviceId, profileKey);
|
signalAccount.setProvisioningData(number,
|
||||||
|
aci,
|
||||||
|
pni,
|
||||||
|
password,
|
||||||
|
encryptedDeviceName,
|
||||||
|
deviceId,
|
||||||
|
aciIdentityKey,
|
||||||
|
pniIdentityKey,
|
||||||
|
profileKey);
|
||||||
|
|
||||||
signalAccount.dataPath = dataPath;
|
signalAccount.dataPath = dataPath;
|
||||||
signalAccount.accountPath = accountPath;
|
signalAccount.accountPath = accountPath;
|
||||||
signalAccount.identityKeyPair = identityKey;
|
|
||||||
signalAccount.localRegistrationId = registrationId;
|
signalAccount.localRegistrationId = registrationId;
|
||||||
signalAccount.trustNewIdentity = trustNewIdentity;
|
signalAccount.trustNewIdentity = trustNewIdentity;
|
||||||
signalAccount.groupStore = new GroupStore(getGroupCachePath(dataPath, accountPath),
|
signalAccount.groupStore = new GroupStore(getGroupCachePath(dataPath, accountPath),
|
||||||
|
@ -283,6 +309,7 @@ public class SignalAccount implements Closeable {
|
||||||
signalAccount.getRecipientStore().resolveSelfRecipientTrusted(signalAccount.getSelfRecipientAddress());
|
signalAccount.getRecipientStore().resolveSelfRecipientTrusted(signalAccount.getSelfRecipientAddress());
|
||||||
signalAccount.previousStorageVersion = CURRENT_STORAGE_VERSION;
|
signalAccount.previousStorageVersion = CURRENT_STORAGE_VERSION;
|
||||||
signalAccount.migrateLegacyConfigs();
|
signalAccount.migrateLegacyConfigs();
|
||||||
|
signalAccount.clearAllPreKeys();
|
||||||
signalAccount.save();
|
signalAccount.save();
|
||||||
|
|
||||||
return signalAccount;
|
return signalAccount;
|
||||||
|
@ -291,17 +318,23 @@ public class SignalAccount implements Closeable {
|
||||||
private void setProvisioningData(
|
private void setProvisioningData(
|
||||||
final String number,
|
final String number,
|
||||||
final ACI aci,
|
final ACI aci,
|
||||||
|
final PNI pni,
|
||||||
final String password,
|
final String password,
|
||||||
final String encryptedDeviceName,
|
final String encryptedDeviceName,
|
||||||
final int deviceId,
|
final int deviceId,
|
||||||
|
final IdentityKeyPair aciIdentity,
|
||||||
|
final IdentityKeyPair pniIdentity,
|
||||||
final ProfileKey profileKey
|
final ProfileKey profileKey
|
||||||
) {
|
) {
|
||||||
this.number = number;
|
this.number = number;
|
||||||
this.aci = aci;
|
this.aci = aci;
|
||||||
|
this.pni = pni;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.profileKey = profileKey;
|
this.profileKey = profileKey;
|
||||||
this.encryptedDeviceName = encryptedDeviceName;
|
this.encryptedDeviceName = encryptedDeviceName;
|
||||||
this.deviceId = deviceId;
|
this.deviceId = deviceId;
|
||||||
|
this.aciIdentityKeyPair = aciIdentity;
|
||||||
|
this.pniIdentityKeyPair = pniIdentity;
|
||||||
this.registered = true;
|
this.registered = true;
|
||||||
this.isMultiDevice = true;
|
this.isMultiDevice = true;
|
||||||
this.lastReceiveTimestamp = 0;
|
this.lastReceiveTimestamp = 0;
|
||||||
|
@ -330,6 +363,9 @@ public class SignalAccount implements Closeable {
|
||||||
}
|
}
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
if (isMasterDevice() && getPniIdentityKeyPair() == null) {
|
||||||
|
setPniIdentityKeyPair(KeyUtils.generateIdentityKeyPair());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mergeRecipients(RecipientId recipientId, RecipientId toBeMergedRecipientId) {
|
private void mergeRecipients(RecipientId recipientId, RecipientId toBeMergedRecipientId) {
|
||||||
|
@ -440,7 +476,14 @@ public class SignalAccount implements Closeable {
|
||||||
try {
|
try {
|
||||||
aci = ACI.parseOrThrow(rootNode.get("uuid").asText());
|
aci = ACI.parseOrThrow(rootNode.get("uuid").asText());
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
throw new IOException("Config file contains an invalid uuid, needs to be a valid UUID", e);
|
throw new IOException("Config file contains an invalid aci/uuid, needs to be a valid UUID", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rootNode.hasNonNull("pni")) {
|
||||||
|
try {
|
||||||
|
pni = PNI.parseOrThrow(rootNode.get("pni").asText());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new IOException("Config file contains an invalid pni, needs to be a valid UUID", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rootNode.hasNonNull("deviceName")) {
|
if (rootNode.hasNonNull("deviceName")) {
|
||||||
|
@ -459,11 +502,16 @@ public class SignalAccount implements Closeable {
|
||||||
if (rootNode.hasNonNull("registrationId")) {
|
if (rootNode.hasNonNull("registrationId")) {
|
||||||
registrationId = rootNode.get("registrationId").asInt();
|
registrationId = rootNode.get("registrationId").asInt();
|
||||||
}
|
}
|
||||||
IdentityKeyPair identityKeyPair = null;
|
IdentityKeyPair aciIdentityKeyPair = null;
|
||||||
if (rootNode.hasNonNull("identityPrivateKey") && rootNode.hasNonNull("identityKey")) {
|
if (rootNode.hasNonNull("identityPrivateKey") && rootNode.hasNonNull("identityKey")) {
|
||||||
final var publicKeyBytes = Base64.getDecoder().decode(rootNode.get("identityKey").asText());
|
final var publicKeyBytes = Base64.getDecoder().decode(rootNode.get("identityKey").asText());
|
||||||
final var privateKeyBytes = Base64.getDecoder().decode(rootNode.get("identityPrivateKey").asText());
|
final var privateKeyBytes = Base64.getDecoder().decode(rootNode.get("identityPrivateKey").asText());
|
||||||
identityKeyPair = KeyUtils.getIdentityKeyPair(publicKeyBytes, privateKeyBytes);
|
aciIdentityKeyPair = KeyUtils.getIdentityKeyPair(publicKeyBytes, privateKeyBytes);
|
||||||
|
}
|
||||||
|
if (rootNode.hasNonNull("pniIdentityPrivateKey") && rootNode.hasNonNull("pniIdentityKey")) {
|
||||||
|
final var publicKeyBytes = Base64.getDecoder().decode(rootNode.get("pniIdentityKey").asText());
|
||||||
|
final var privateKeyBytes = Base64.getDecoder().decode(rootNode.get("pniIdentityPrivateKey").asText());
|
||||||
|
pniIdentityKeyPair = KeyUtils.getIdentityKeyPair(publicKeyBytes, privateKeyBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rootNode.hasNonNull("registrationLockPin")) {
|
if (rootNode.hasNonNull("registrationLockPin")) {
|
||||||
|
@ -504,12 +552,12 @@ public class SignalAccount implements Closeable {
|
||||||
LegacyJsonSignalProtocolStore.class)
|
LegacyJsonSignalProtocolStore.class)
|
||||||
: null;
|
: null;
|
||||||
if (legacySignalProtocolStore != null && legacySignalProtocolStore.getLegacyIdentityKeyStore() != null) {
|
if (legacySignalProtocolStore != null && legacySignalProtocolStore.getLegacyIdentityKeyStore() != null) {
|
||||||
identityKeyPair = legacySignalProtocolStore.getLegacyIdentityKeyStore().getIdentityKeyPair();
|
aciIdentityKeyPair = legacySignalProtocolStore.getLegacyIdentityKeyStore().getIdentityKeyPair();
|
||||||
registrationId = legacySignalProtocolStore.getLegacyIdentityKeyStore().getLocalRegistrationId();
|
registrationId = legacySignalProtocolStore.getLegacyIdentityKeyStore().getLocalRegistrationId();
|
||||||
migratedLegacyConfig = true;
|
migratedLegacyConfig = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.identityKeyPair = identityKeyPair;
|
this.aciIdentityKeyPair = aciIdentityKeyPair;
|
||||||
this.localRegistrationId = registrationId;
|
this.localRegistrationId = registrationId;
|
||||||
this.trustNewIdentity = trustNewIdentity;
|
this.trustNewIdentity = trustNewIdentity;
|
||||||
|
|
||||||
|
@ -741,6 +789,7 @@ public class SignalAccount implements Closeable {
|
||||||
rootNode.put("version", CURRENT_STORAGE_VERSION)
|
rootNode.put("version", CURRENT_STORAGE_VERSION)
|
||||||
.put("username", number)
|
.put("username", number)
|
||||||
.put("uuid", aci == null ? null : aci.toString())
|
.put("uuid", aci == null ? null : aci.toString())
|
||||||
|
.put("pni", pni == null ? null : pni.toString())
|
||||||
.put("deviceName", encryptedDeviceName)
|
.put("deviceName", encryptedDeviceName)
|
||||||
.put("deviceId", deviceId)
|
.put("deviceId", deviceId)
|
||||||
.put("isMultiDevice", isMultiDevice)
|
.put("isMultiDevice", isMultiDevice)
|
||||||
|
@ -748,8 +797,18 @@ public class SignalAccount implements Closeable {
|
||||||
.put("password", password)
|
.put("password", password)
|
||||||
.put("registrationId", localRegistrationId)
|
.put("registrationId", localRegistrationId)
|
||||||
.put("identityPrivateKey",
|
.put("identityPrivateKey",
|
||||||
Base64.getEncoder().encodeToString(identityKeyPair.getPrivateKey().serialize()))
|
Base64.getEncoder().encodeToString(aciIdentityKeyPair.getPrivateKey().serialize()))
|
||||||
.put("identityKey", Base64.getEncoder().encodeToString(identityKeyPair.getPublicKey().serialize()))
|
.put("identityKey",
|
||||||
|
Base64.getEncoder().encodeToString(aciIdentityKeyPair.getPublicKey().serialize()))
|
||||||
|
.put("pniIdentityPrivateKey",
|
||||||
|
pniIdentityKeyPair == null
|
||||||
|
? null
|
||||||
|
: Base64.getEncoder()
|
||||||
|
.encodeToString(pniIdentityKeyPair.getPrivateKey().serialize()))
|
||||||
|
.put("pniIdentityKey",
|
||||||
|
pniIdentityKeyPair == null
|
||||||
|
? null
|
||||||
|
: Base64.getEncoder().encodeToString(pniIdentityKeyPair.getPublicKey().serialize()))
|
||||||
.put("registrationLockPin", registrationLockPin)
|
.put("registrationLockPin", registrationLockPin)
|
||||||
.put("pinMasterKey",
|
.put("pinMasterKey",
|
||||||
pinMasterKey == null ? null : Base64.getEncoder().encodeToString(pinMasterKey.serialize()))
|
pinMasterKey == null ? null : Base64.getEncoder().encodeToString(pinMasterKey.serialize()))
|
||||||
|
@ -820,8 +879,14 @@ public class SignalAccount implements Closeable {
|
||||||
public SignalServiceDataStore getSignalServiceDataStore() {
|
public SignalServiceDataStore getSignalServiceDataStore() {
|
||||||
return new SignalServiceDataStore() {
|
return new SignalServiceDataStore() {
|
||||||
@Override
|
@Override
|
||||||
public SignalServiceAccountDataStore get(final AccountIdentifier accountIdentifier) {
|
public SignalServiceAccountDataStore get(final ServiceId accountIdentifier) {
|
||||||
return getSignalServiceAccountDataStore();
|
if (accountIdentifier.equals(aci)) {
|
||||||
|
return getSignalServiceAccountDataStore();
|
||||||
|
} else if (accountIdentifier.equals(pni)) {
|
||||||
|
throw new AssertionError("PNI not to be used yet!");
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("No matching store found for " + accountIdentifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -831,7 +896,7 @@ public class SignalAccount implements Closeable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SignalServiceAccountDataStore pni() {
|
public SignalServiceAccountDataStore pni() {
|
||||||
return getSignalServiceAccountDataStore();
|
throw new AssertionError("PNI not to be used yet!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -870,7 +935,7 @@ public class SignalAccount implements Closeable {
|
||||||
return getOrCreate(() -> identityKeyStore,
|
return getOrCreate(() -> identityKeyStore,
|
||||||
() -> identityKeyStore = new IdentityKeyStore(getIdentitiesPath(dataPath, accountPath),
|
() -> identityKeyStore = new IdentityKeyStore(getIdentitiesPath(dataPath, accountPath),
|
||||||
getRecipientStore(),
|
getRecipientStore(),
|
||||||
identityKeyPair,
|
aciIdentityKeyPair,
|
||||||
localRegistrationId,
|
localRegistrationId,
|
||||||
trustNewIdentity));
|
trustNewIdentity));
|
||||||
}
|
}
|
||||||
|
@ -937,6 +1002,11 @@ public class SignalAccount implements Closeable {
|
||||||
return aci;
|
return aci;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PNI getPni() {
|
||||||
|
return pni;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getE164() {
|
public String getE164() {
|
||||||
return number;
|
return number;
|
||||||
|
@ -972,6 +1042,15 @@ public class SignalAccount implements Closeable {
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PNI getPni() {
|
||||||
|
return pni;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPni(final PNI pni) {
|
||||||
|
this.pni = pni;
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
public SignalServiceAddress getSelfAddress() {
|
public SignalServiceAddress getSelfAddress() {
|
||||||
return new SignalServiceAddress(aci, number);
|
return new SignalServiceAddress(aci, number);
|
||||||
}
|
}
|
||||||
|
@ -1001,8 +1080,17 @@ public class SignalAccount implements Closeable {
|
||||||
return deviceId == SignalServiceAddress.DEFAULT_DEVICE_ID;
|
return deviceId == SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentityKeyPair getIdentityKeyPair() {
|
public IdentityKeyPair getAciIdentityKeyPair() {
|
||||||
return identityKeyPair;
|
return aciIdentityKeyPair;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdentityKeyPair getPniIdentityKeyPair() {
|
||||||
|
return pniIdentityKeyPair;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPniIdentityKeyPair(final IdentityKeyPair identityKeyPair) {
|
||||||
|
pniIdentityKeyPair = identityKeyPair;
|
||||||
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLocalRegistrationId() {
|
public int getLocalRegistrationId() {
|
||||||
|
@ -1118,7 +1206,7 @@ public class SignalAccount implements Closeable {
|
||||||
return configurationStore.getPhoneNumberUnlisted() == null || !configurationStore.getPhoneNumberUnlisted();
|
return configurationStore.getPhoneNumberUnlisted() == null || !configurationStore.getPhoneNumberUnlisted();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finishRegistration(final ACI aci, final MasterKey masterKey, final String pin) {
|
public void finishRegistration(final ACI aci, final PNI pni, final MasterKey masterKey, final String pin) {
|
||||||
this.pinMasterKey = masterKey;
|
this.pinMasterKey = masterKey;
|
||||||
this.storageManifestVersion = -1;
|
this.storageManifestVersion = -1;
|
||||||
this.storageKey = null;
|
this.storageKey = null;
|
||||||
|
@ -1127,6 +1215,7 @@ public class SignalAccount implements Closeable {
|
||||||
this.isMultiDevice = false;
|
this.isMultiDevice = false;
|
||||||
this.registered = true;
|
this.registered = true;
|
||||||
this.aci = aci;
|
this.aci = aci;
|
||||||
|
this.pni = pni;
|
||||||
this.registrationLockPin = pin;
|
this.registrationLockPin = pin;
|
||||||
this.lastReceiveTimestamp = 0;
|
this.lastReceiveTimestamp = 0;
|
||||||
save();
|
save();
|
||||||
|
@ -1135,7 +1224,7 @@ public class SignalAccount implements Closeable {
|
||||||
getSessionStore().archiveAllSessions();
|
getSessionStore().archiveAllSessions();
|
||||||
getSenderKeyStore().deleteAll();
|
getSenderKeyStore().deleteAll();
|
||||||
final var recipientId = getRecipientStore().resolveSelfRecipientTrusted(getSelfRecipientAddress());
|
final var recipientId = getRecipientStore().resolveSelfRecipientTrusted(getSelfRecipientAddress());
|
||||||
final var publicKey = getIdentityKeyPair().getPublicKey();
|
final var publicKey = getAciIdentityKeyPair().getPublicKey();
|
||||||
getIdentityKeyStore().saveIdentity(recipientId, publicKey, new Date());
|
getIdentityKeyStore().saveIdentity(recipientId, publicKey, new Date());
|
||||||
getIdentityKeyStore().setIdentityTrustLevel(recipientId, publicKey, TrustLevel.TRUSTED_VERIFIED);
|
getIdentityKeyStore().setIdentityTrustLevel(recipientId, publicKey, TrustLevel.TRUSTED_VERIFIED);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ public record RecipientAddress(Optional<UUID> uuid, Optional<String> number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientAddress(SignalServiceAddress address) {
|
public RecipientAddress(SignalServiceAddress address) {
|
||||||
this(Optional.of(address.getAci().uuid()), Optional.ofNullable(address.getNumber().orNull()));
|
this(Optional.of(address.getServiceId().uuid()), Optional.ofNullable(address.getNumber().orNull()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientAddress(UUID uuid) {
|
public RecipientAddress(UUID uuid) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.asamk.signal.manager.storage.recipients;
|
package org.asamk.signal.manager.storage.recipients;
|
||||||
|
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
public interface RecipientResolver {
|
public interface RecipientResolver {
|
||||||
|
@ -11,7 +11,7 @@ public interface RecipientResolver {
|
||||||
|
|
||||||
RecipientId resolveRecipient(SignalServiceAddress address);
|
RecipientId resolveRecipient(SignalServiceAddress address);
|
||||||
|
|
||||||
RecipientId resolveRecipient(ACI aci);
|
RecipientId resolveRecipient(ServiceId aci);
|
||||||
|
|
||||||
RecipientId resolveRecipient(long recipientId);
|
RecipientId resolveRecipient(long recipientId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import org.signal.zkgroup.profiles.ProfileKeyCredential;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ACI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||||
|
|
||||||
|
@ -171,8 +172,8 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RecipientId resolveRecipient(ACI aci) {
|
public RecipientId resolveRecipient(ServiceId serviceId) {
|
||||||
return resolveRecipient(new RecipientAddress(aci.uuid()), false, false);
|
return resolveRecipient(new RecipientAddress(serviceId.uuid()), false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -65,8 +65,8 @@ public class Utils {
|
||||||
if (isUuidCapable) {
|
if (isUuidCapable) {
|
||||||
// Version 2: UUID user
|
// Version 2: UUID user
|
||||||
version = 2;
|
version = 2;
|
||||||
ownId = ownAddress.getAci().toByteArray();
|
ownId = ownAddress.getServiceId().toByteArray();
|
||||||
theirId = theirAddress.getAci().toByteArray();
|
theirId = theirAddress.getServiceId().toByteArray();
|
||||||
} else {
|
} else {
|
||||||
// Version 1: E164 user
|
// Version 1: E164 user
|
||||||
version = 1;
|
version = 1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue