Refactor creating linked account files

This commit is contained in:
AsamK 2023-10-16 18:28:08 +02:00
parent dd3326f038
commit 400dcf2899
3 changed files with 64 additions and 140 deletions

View file

@ -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);

View file

@ -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(),
accountPath,
number,
serviceEnvironmentConfig.type(),
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);
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,

View file

@ -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(