mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 18:40:39 +00:00
Refactor creating linked account files
This commit is contained in:
parent
dd3326f038
commit
400dcf2899
3 changed files with 64 additions and 140 deletions
|
@ -14,7 +14,6 @@ import org.asamk.signal.manager.internal.RegistrationManagerImpl;
|
|||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.asamk.signal.manager.storage.accounts.AccountsStore;
|
||||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.signal.libsignal.protocol.util.KeyHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
|
||||
|
@ -160,8 +159,6 @@ public class SignalAccountFiles {
|
|||
final var newAccountPath = accountPath == null ? accountsStore.addAccount(number, null) : accountPath;
|
||||
var aciIdentityKey = KeyUtils.generateIdentityKeyPair();
|
||||
var pniIdentityKey = KeyUtils.generateIdentityKeyPair();
|
||||
var registrationId = KeyHelper.generateRegistrationId(false);
|
||||
var pniRegistrationId = KeyHelper.generateRegistrationId(false);
|
||||
|
||||
var profileKey = KeyUtils.createProfileKey();
|
||||
var account = SignalAccount.create(pathConfig.dataPath(),
|
||||
|
@ -170,8 +167,6 @@ public class SignalAccountFiles {
|
|||
serviceEnvironment,
|
||||
aciIdentityKey,
|
||||
pniIdentityKey,
|
||||
registrationId,
|
||||
pniRegistrationId,
|
||||
profileKey,
|
||||
settings);
|
||||
|
||||
|
|
|
@ -27,12 +27,12 @@ import org.asamk.signal.manager.storage.SignalAccount;
|
|||
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.util.DeviceNameUtil;
|
||||
|
@ -59,8 +59,6 @@ public class ProvisioningManagerImpl implements ProvisioningManager {
|
|||
|
||||
private final SignalServiceAccountManager accountManager;
|
||||
private final IdentityKeyPair tempIdentityKey;
|
||||
private final int registrationId;
|
||||
private final int pniRegistrationId;
|
||||
private final String password;
|
||||
|
||||
public ProvisioningManagerImpl(
|
||||
|
@ -77,8 +75,6 @@ public class ProvisioningManagerImpl implements ProvisioningManager {
|
|||
this.accountsStore = accountsStore;
|
||||
|
||||
tempIdentityKey = KeyUtils.generateIdentityKeyPair();
|
||||
registrationId = KeyHelper.generateRegistrationId(false);
|
||||
pniRegistrationId = KeyHelper.generateRegistrationId(false);
|
||||
password = KeyUtils.createPassword();
|
||||
GroupsV2Operations groupsV2Operations;
|
||||
try {
|
||||
|
@ -114,9 +110,9 @@ public class ProvisioningManagerImpl implements ProvisioningManager {
|
|||
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) {
|
||||
|
@ -128,38 +124,42 @@ public class ProvisioningManagerImpl implements ProvisioningManager {
|
|||
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(),
|
||||
if (!accountExists) {
|
||||
account = SignalAccount.createLinkedAccount(pathConfig.dataPath(),
|
||||
accountPath,
|
||||
number,
|
||||
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);
|
||||
profileKey);
|
||||
|
||||
account.getConfigurationStore().setReadReceipts(ret.isReadReceipts());
|
||||
|
||||
logger.debug("Finishing new device registration");
|
||||
var deviceId = accountManager.finishNewDeviceRegistration(ret.getProvisioningCode(),
|
||||
new ConfirmCodeMessage(false,
|
||||
true,
|
||||
account.getAccountData(ServiceIdType.ACI).getLocalRegistrationId(),
|
||||
account.getAccountData(ServiceIdType.PNI).getLocalRegistrationId(),
|
||||
encryptedDeviceName,
|
||||
getCapabilities(false)));
|
||||
|
||||
account.finishLinking(deviceId);
|
||||
|
||||
ManagerImpl m = null;
|
||||
try {
|
||||
m = new ManagerImpl(account,
|
||||
|
|
|
@ -130,7 +130,7 @@ public class SignalAccount implements Closeable {
|
|||
private String number;
|
||||
private String username;
|
||||
private String encryptedDeviceName;
|
||||
private int deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
private int deviceId = 0;
|
||||
private String password;
|
||||
private String registrationLockPin;
|
||||
private MasterKey pinMasterKey;
|
||||
|
@ -204,8 +204,6 @@ public class SignalAccount implements Closeable {
|
|||
ServiceEnvironment serviceEnvironment,
|
||||
IdentityKeyPair aciIdentityKey,
|
||||
IdentityKeyPair pniIdentityKey,
|
||||
int registrationId,
|
||||
int pniRegistrationId,
|
||||
ProfileKey profileKey,
|
||||
final Settings settings
|
||||
) throws IOException {
|
||||
|
@ -223,160 +221,91 @@ public class SignalAccount implements Closeable {
|
|||
signalAccount.serviceEnvironment = serviceEnvironment;
|
||||
signalAccount.profileKey = profileKey;
|
||||
signalAccount.password = KeyUtils.createPassword();
|
||||
signalAccount.deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
|
||||
signalAccount.dataPath = dataPath;
|
||||
signalAccount.aciAccountData.setIdentityKeyPair(aciIdentityKey);
|
||||
signalAccount.pniAccountData.setIdentityKeyPair(pniIdentityKey);
|
||||
signalAccount.aciAccountData.setLocalRegistrationId(registrationId);
|
||||
signalAccount.pniAccountData.setLocalRegistrationId(pniRegistrationId);
|
||||
signalAccount.aciAccountData.setLocalRegistrationId(KeyHelper.generateRegistrationId(false));
|
||||
signalAccount.pniAccountData.setLocalRegistrationId(KeyHelper.generateRegistrationId(false));
|
||||
signalAccount.settings = settings;
|
||||
|
||||
signalAccount.registered = false;
|
||||
|
||||
signalAccount.previousStorageVersion = CURRENT_STORAGE_VERSION;
|
||||
signalAccount.migrateLegacyConfigs();
|
||||
signalAccount.clearAllPreKeys();
|
||||
signalAccount.save();
|
||||
|
||||
return signalAccount;
|
||||
}
|
||||
|
||||
private static SignalAccount createLinkedAccount(
|
||||
File dataPath,
|
||||
String accountPath,
|
||||
String number,
|
||||
ServiceEnvironment serviceEnvironment,
|
||||
ACI aci,
|
||||
PNI pni,
|
||||
String password,
|
||||
String encryptedDeviceName,
|
||||
int deviceId,
|
||||
IdentityKeyPair aciIdentityKey,
|
||||
IdentityKeyPair pniIdentityKey,
|
||||
int registrationId,
|
||||
int pniRegistrationId,
|
||||
ProfileKey profileKey,
|
||||
final Settings settings
|
||||
) throws IOException {
|
||||
var fileName = getFileName(dataPath, accountPath);
|
||||
IOUtils.createPrivateFile(fileName);
|
||||
|
||||
final var pair = openFileChannel(fileName, true);
|
||||
var signalAccount = new SignalAccount(pair.first(), pair.second());
|
||||
|
||||
signalAccount.dataPath = dataPath;
|
||||
signalAccount.accountPath = accountPath;
|
||||
signalAccount.serviceEnvironment = serviceEnvironment;
|
||||
signalAccount.aciAccountData.setLocalRegistrationId(registrationId);
|
||||
signalAccount.pniAccountData.setLocalRegistrationId(pniRegistrationId);
|
||||
signalAccount.settings = settings;
|
||||
signalAccount.setProvisioningData(number,
|
||||
aci,
|
||||
pni,
|
||||
password,
|
||||
encryptedDeviceName,
|
||||
deviceId,
|
||||
aciIdentityKey,
|
||||
pniIdentityKey,
|
||||
profileKey);
|
||||
|
||||
signalAccount.getRecipientTrustedResolver()
|
||||
.resolveSelfRecipientTrusted(signalAccount.getSelfRecipientAddress());
|
||||
signalAccount.previousStorageVersion = CURRENT_STORAGE_VERSION;
|
||||
signalAccount.migrateLegacyConfigs();
|
||||
signalAccount.clearAllPreKeys();
|
||||
signalAccount.save();
|
||||
|
||||
return signalAccount;
|
||||
}
|
||||
|
||||
public static SignalAccount createOrUpdateLinkedAccount(
|
||||
File dataPath,
|
||||
String accountPath,
|
||||
String number,
|
||||
ServiceEnvironment serviceEnvironment,
|
||||
ACI aci,
|
||||
PNI pni,
|
||||
String password,
|
||||
String encryptedDeviceName,
|
||||
int deviceId,
|
||||
IdentityKeyPair aciIdentityKey,
|
||||
IdentityKeyPair pniIdentityKey,
|
||||
int registrationId,
|
||||
int pniRegistrationId,
|
||||
ProfileKey profileKey,
|
||||
public static SignalAccount createLinkedAccount(
|
||||
final File dataPath,
|
||||
final String accountPath,
|
||||
final ServiceEnvironment serviceEnvironment,
|
||||
final Settings settings
|
||||
) throws IOException {
|
||||
IOUtils.createPrivateDirectories(dataPath);
|
||||
var fileName = getFileName(dataPath, accountPath);
|
||||
if (!fileName.exists()) {
|
||||
return createLinkedAccount(dataPath,
|
||||
accountPath,
|
||||
number,
|
||||
serviceEnvironment,
|
||||
aci,
|
||||
pni,
|
||||
password,
|
||||
encryptedDeviceName,
|
||||
deviceId,
|
||||
aciIdentityKey,
|
||||
pniIdentityKey,
|
||||
registrationId,
|
||||
pniRegistrationId,
|
||||
profileKey,
|
||||
settings);
|
||||
}
|
||||
IOUtils.createPrivateFile(fileName);
|
||||
|
||||
final var pair = openFileChannel(fileName, true);
|
||||
final var signalAccount = new SignalAccount(pair.first(), pair.second());
|
||||
|
||||
signalAccount.dataPath = dataPath;
|
||||
signalAccount.accountPath = accountPath;
|
||||
signalAccount.serviceEnvironment = serviceEnvironment;
|
||||
signalAccount.aciAccountData.setLocalRegistrationId(KeyHelper.generateRegistrationId(false));
|
||||
signalAccount.pniAccountData.setLocalRegistrationId(KeyHelper.generateRegistrationId(false));
|
||||
signalAccount.settings = settings;
|
||||
|
||||
signalAccount.previousStorageVersion = CURRENT_STORAGE_VERSION;
|
||||
|
||||
final var signalAccount = load(dataPath, accountPath, true, settings);
|
||||
signalAccount.setProvisioningData(number,
|
||||
aci,
|
||||
pni,
|
||||
password,
|
||||
encryptedDeviceName,
|
||||
deviceId,
|
||||
aciIdentityKey,
|
||||
pniIdentityKey,
|
||||
profileKey);
|
||||
signalAccount.getRecipientTrustedResolver()
|
||||
.resolveSelfRecipientTrusted(signalAccount.getSelfRecipientAddress());
|
||||
signalAccount.aciAccountData.getSessionStore().archiveAllSessions();
|
||||
signalAccount.pniAccountData.getSessionStore().archiveAllSessions();
|
||||
signalAccount.getSenderKeyStore().deleteAll();
|
||||
signalAccount.clearAllPreKeys();
|
||||
return signalAccount;
|
||||
}
|
||||
|
||||
private void setProvisioningData(
|
||||
public void setProvisioningData(
|
||||
final String number,
|
||||
final ACI aci,
|
||||
final PNI pni,
|
||||
final String password,
|
||||
final String encryptedDeviceName,
|
||||
final int deviceId,
|
||||
final IdentityKeyPair aciIdentity,
|
||||
final IdentityKeyPair pniIdentity,
|
||||
final ProfileKey profileKey
|
||||
) {
|
||||
this.deviceId = 0;
|
||||
this.number = number;
|
||||
this.aciAccountData.setServiceId(aci);
|
||||
this.pniAccountData.setServiceId(pni);
|
||||
getRecipientTrustedResolver().resolveSelfRecipientTrusted(getSelfRecipientAddress());
|
||||
this.password = password;
|
||||
this.profileKey = profileKey;
|
||||
getProfileStore().storeSelfProfileKey(getSelfRecipientId(), getProfileKey());
|
||||
this.encryptedDeviceName = encryptedDeviceName;
|
||||
this.deviceId = deviceId;
|
||||
this.aciAccountData.setIdentityKeyPair(aciIdentity);
|
||||
this.pniAccountData.setIdentityKeyPair(pniIdentity);
|
||||
this.registered = true;
|
||||
this.registered = false;
|
||||
this.isMultiDevice = true;
|
||||
getKeyValueStore().storeEntry(lastReceiveTimestamp, 0L);
|
||||
this.pinMasterKey = null;
|
||||
getKeyValueStore().storeEntry(storageManifestVersion, -1L);
|
||||
this.setStorageManifest(null);
|
||||
this.storageKey = null;
|
||||
getSenderKeyStore().deleteAll();
|
||||
trustSelfIdentity(ServiceIdType.ACI);
|
||||
trustSelfIdentity(ServiceIdType.PNI);
|
||||
aciAccountData.getSessionStore().archiveAllSessions();
|
||||
pniAccountData.getSessionStore().archiveAllSessions();
|
||||
clearAllPreKeys();
|
||||
getKeyValueStore().storeEntry(lastRecipientsRefresh, null);
|
||||
save();
|
||||
}
|
||||
|
||||
public void finishLinking(final int deviceId) {
|
||||
this.registered = true;
|
||||
this.deviceId = deviceId;
|
||||
save();
|
||||
}
|
||||
|
||||
public void finishRegistration(
|
||||
|
@ -476,7 +405,7 @@ public class SignalAccount implements Closeable {
|
|||
return false;
|
||||
}
|
||||
var f = getFileName(dataPath, account);
|
||||
return !(!f.exists() || f.isDirectory());
|
||||
return f.exists() && !f.isDirectory() && f.length() > 0L;
|
||||
}
|
||||
|
||||
private void load(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue