import org.asamk.signal.manager.storage.accounts.AccountsStore;
import org.asamk.signal.manager.util.KeyUtils;
import org.signal.libsignal.protocol.IdentityKeyPair;
-import org.signal.libsignal.protocol.util.KeyHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
-import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
+import org.whispersystems.signalservice.api.push.ServiceIdType;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
+import org.whispersystems.signalservice.api.registration.ProvisioningApi;
import org.whispersystems.signalservice.api.util.DeviceNameUtil;
-import org.whispersystems.signalservice.internal.push.ConfirmCodeMessage;
+import org.whispersystems.signalservice.internal.push.ProvisioningSocket;
+import org.whispersystems.signalservice.internal.push.PushServiceSocket;
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
-import static org.asamk.signal.manager.config.ServiceConfig.getCapabilities;
+import static org.asamk.signal.manager.util.KeyUtils.generatePreKeysForType;
public class ProvisioningManagerImpl implements ProvisioningManager {
- private final static Logger logger = LoggerFactory.getLogger(ProvisioningManagerImpl.class);
+ private static final Logger logger = LoggerFactory.getLogger(ProvisioningManagerImpl.class);
private final PathConfig pathConfig;
private final ServiceEnvironmentConfig serviceEnvironmentConfig;
private final Consumer<Manager> newManagerListener;
private final AccountsStore accountsStore;
- private final SignalServiceAccountManager accountManager;
+ private final ProvisioningApi provisioningApi;
private final IdentityKeyPair tempIdentityKey;
- private final int registrationId;
- private final int pniRegistrationId;
private final String password;
public ProvisioningManagerImpl(
this.accountsStore = accountsStore;
tempIdentityKey = KeyUtils.generateIdentityKeyPair();
- registrationId = KeyHelper.generateRegistrationId(false);
- pniRegistrationId = KeyHelper.generateRegistrationId(false);
password = KeyUtils.createPassword();
- GroupsV2Operations groupsV2Operations;
- try {
- groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration()),
- ServiceConfig.GROUP_MAX_SIZE);
- } catch (Throwable ignored) {
- groupsV2Operations = null;
- }
- accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
- new DynamicCredentialsProvider(null, null, null, password, SignalServiceAddress.DEFAULT_DEVICE_ID),
+ final var clientZkOperations = ClientZkOperations.create(serviceEnvironmentConfig.signalServiceConfiguration());
+ final var credentialsProvider = new DynamicCredentialsProvider(null,
+ null,
+ null,
+ password,
+ SignalServiceAddress.DEFAULT_DEVICE_ID);
+ final var pushServiceSocket = new PushServiceSocket(serviceEnvironmentConfig.signalServiceConfiguration(),
+ credentialsProvider,
userAgent,
- groupsV2Operations,
+ clientZkOperations.getProfileOperations(),
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
+ final var provisioningSocket = new ProvisioningSocket(serviceEnvironmentConfig.signalServiceConfiguration(),
+ userAgent);
+ this.provisioningApi = new ProvisioningApi(pushServiceSocket, provisioningSocket, credentialsProvider);
}
@Override
public URI getDeviceLinkUri() throws TimeoutException, IOException {
- var deviceUuid = accountManager.getNewDeviceUuid();
+ var deviceUuid = provisioningApi.getNewDeviceUuid();
return new DeviceLinkUrl(deviceUuid, tempIdentityKey.getPublicKey().getPublicKey()).createDeviceLinkUri();
}
@Override
public String finishDeviceLink(String deviceName) throws IOException, TimeoutException, UserAlreadyExistsException {
- var ret = accountManager.getNewDeviceRegistration(tempIdentityKey);
+ var ret = provisioningApi.getNewDeviceRegistration(tempIdentityKey);
var number = ret.getNumber();
var aci = ret.getAci();
var pni = ret.getPni();
if (accountPath == null) {
accountPath = accountsStore.getPathByNumber(number);
}
- if (accountPath != null
- && SignalAccount.accountFileExists(pathConfig.dataPath(), accountPath)
- && !canRelinkExistingAccount(accountPath)) {
+ final var accountExists = accountPath != null && SignalAccount.accountFileExists(pathConfig.dataPath(),
+ accountPath);
+ if (accountExists && !canRelinkExistingAccount(accountPath)) {
throw new UserAlreadyExistsException(number, SignalAccount.getFileName(pathConfig.dataPath(), accountPath));
}
if (accountPath == null) {
var encryptedDeviceName = deviceName == null
? null
: DeviceNameUtil.encryptDeviceName(deviceName, ret.getAciIdentity().getPrivateKey());
-
- logger.debug("Finishing new device registration");
- var deviceId = accountManager.finishNewDeviceRegistration(ret.getProvisioningCode(),
- new ConfirmCodeMessage(false,
- true,
- registrationId,
- pniRegistrationId,
- encryptedDeviceName,
- getCapabilities(false)));
-
// Create new account with the synced identity
var profileKey = ret.getProfileKey() == null ? KeyUtils.createProfileKey() : ret.getProfileKey();
SignalAccount account = null;
try {
- account = SignalAccount.createOrUpdateLinkedAccount(pathConfig.dataPath(),
- accountPath,
- number,
- serviceEnvironmentConfig.getType(),
+ if (!accountExists) {
+ account = SignalAccount.createLinkedAccount(pathConfig.dataPath(),
+ accountPath,
+ serviceEnvironmentConfig.type(),
+ Settings.DEFAULT);
+ } else {
+ account = SignalAccount.load(pathConfig.dataPath(), accountPath, true, Settings.DEFAULT);
+ }
+
+ account.setProvisioningData(number,
aci,
pni,
password,
encryptedDeviceName,
- deviceId,
ret.getAciIdentity(),
ret.getPniIdentity(),
- registrationId,
- pniRegistrationId,
profileKey,
- Settings.DEFAULT);
+ ret.getMasterKey(),
+ ret.getAccountEntropyPool(),
+ ret.getMediaRootBackupKey());
+
account.getConfigurationStore().setReadReceipts(ret.isReadReceipts());
+ final var aciPreKeys = generatePreKeysForType(account.getAccountData(ServiceIdType.ACI));
+ final var pniPreKeys = generatePreKeysForType(account.getAccountData(ServiceIdType.PNI));
+
+ logger.debug("Finishing new device registration");
+ var deviceId = provisioningApi.finishNewDeviceRegistration(ret.getProvisioningCode(),
+ account.getAccountAttributes(null),
+ aciPreKeys,
+ pniPreKeys);
+
+ account.finishLinking(deviceId, aciPreKeys, pniPreKeys);
+
ManagerImpl m = null;
try {
m = new ManagerImpl(account,
}
if (signalAccount.isRegistered()
&& signalAccount.getServiceEnvironment() != null
- && signalAccount.getServiceEnvironment() != serviceEnvironmentConfig.getType()) {
+ && signalAccount.getServiceEnvironment() != serviceEnvironmentConfig.type()) {
logger.debug("Account is registered in another environment: {}.",
signalAccount.getServiceEnvironment());
return false;