mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 18:40:39 +00:00
Implement account reregistration with recovery password
This commit is contained in:
parent
fb85e1a068
commit
9f6b6cb657
2 changed files with 90 additions and 38 deletions
|
@ -39,6 +39,7 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
|||
import org.whispersystems.signalservice.api.account.PreKeyCollection;
|
||||
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.kbs.MasterKey;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||
|
@ -111,6 +112,11 @@ public class RegistrationManagerImpl implements RegistrationManager {
|
|||
}
|
||||
|
||||
try {
|
||||
final var recoveryPassword = account.getRecoveryPassword();
|
||||
if (recoveryPassword != null && account.isPrimaryDevice() && attemptReregisterAccount(recoveryPassword)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (account.getAci() != null && attemptReactivateAccount()) {
|
||||
return;
|
||||
}
|
||||
|
@ -156,43 +162,7 @@ public class RegistrationManagerImpl implements RegistrationManager {
|
|||
pin = null;
|
||||
}
|
||||
|
||||
//accountManager.setGcmId(Optional.of(GoogleCloudMessaging.getInstance(this).register(REGISTRATION_ID)));
|
||||
final var aci = ACI.parseOrThrow(response.getUuid());
|
||||
final var pni = PNI.parseOrThrow(response.getPni());
|
||||
account.finishRegistration(aci, pni, masterKey, pin, aciPreKeys, pniPreKeys);
|
||||
accountFileUpdater.updateAccountIdentifiers(account.getNumber(), aci);
|
||||
|
||||
ManagerImpl m = null;
|
||||
try {
|
||||
m = new ManagerImpl(account, pathConfig, accountFileUpdater, serviceEnvironmentConfig, userAgent);
|
||||
account = null;
|
||||
|
||||
m.refreshPreKeys();
|
||||
if (response.isStorageCapable()) {
|
||||
m.syncRemoteStorage();
|
||||
}
|
||||
// Set an initial empty profile so user can be added to groups
|
||||
try {
|
||||
m.updateProfile(UpdateProfile.newBuilder().build());
|
||||
} catch (NoClassDefFoundError e) {
|
||||
logger.warn("Failed to set default profile: {}", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
m.refreshCurrentUsername();
|
||||
} catch (IOException | BaseUsernameException e) {
|
||||
logger.warn("Failed to refresh current username", e);
|
||||
}
|
||||
|
||||
if (newManagerListener != null) {
|
||||
newManagerListener.accept(m);
|
||||
m = null;
|
||||
}
|
||||
} finally {
|
||||
if (m != null) {
|
||||
m.close();
|
||||
}
|
||||
}
|
||||
finishAccountRegistration(response, pin, masterKey, aciPreKeys, pniPreKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -207,6 +177,34 @@ public class RegistrationManagerImpl implements RegistrationManager {
|
|||
return account.isRegistered();
|
||||
}
|
||||
|
||||
private boolean attemptReregisterAccount(final String recoveryPassword) {
|
||||
try {
|
||||
if (account.getPniIdentityKeyPair() == null) {
|
||||
account.setPniIdentityKeyPair(KeyUtils.generateIdentityKeyPair());
|
||||
}
|
||||
|
||||
final var aciPreKeys = generatePreKeysForType(account.getAccountData(ServiceIdType.ACI));
|
||||
final var pniPreKeys = generatePreKeysForType(account.getAccountData(ServiceIdType.PNI));
|
||||
final var response = Utils.handleResponseException(accountManager.registerAccount(null,
|
||||
recoveryPassword,
|
||||
account.getAccountAttributes(null),
|
||||
aciPreKeys,
|
||||
pniPreKeys,
|
||||
null,
|
||||
true));
|
||||
finishAccountRegistration(response,
|
||||
account.getRegistrationLockPin(),
|
||||
account.getPinBackedMasterKey(),
|
||||
aciPreKeys,
|
||||
pniPreKeys);
|
||||
logger.info("Reregistered existing account, verify is not necessary.");
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
logger.debug("Failed to reregister account with recovery password", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean attemptReactivateAccount() {
|
||||
try {
|
||||
final var accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.signalServiceConfiguration(),
|
||||
|
@ -254,6 +252,52 @@ public class RegistrationManagerImpl implements RegistrationManager {
|
|||
true));
|
||||
}
|
||||
|
||||
private void finishAccountRegistration(
|
||||
final VerifyAccountResponse response,
|
||||
final String pin,
|
||||
final MasterKey masterKey,
|
||||
final PreKeyCollection aciPreKeys,
|
||||
final PreKeyCollection pniPreKeys
|
||||
) throws IOException {
|
||||
//accountManager.setGcmId(Optional.of(GoogleCloudMessaging.getInstance(this).register(REGISTRATION_ID)));
|
||||
final var aci = ACI.parseOrThrow(response.getUuid());
|
||||
final var pni = PNI.parseOrThrow(response.getPni());
|
||||
account.finishRegistration(aci, pni, masterKey, pin, aciPreKeys, pniPreKeys);
|
||||
accountFileUpdater.updateAccountIdentifiers(account.getNumber(), aci);
|
||||
|
||||
ManagerImpl m = null;
|
||||
try {
|
||||
m = new ManagerImpl(account, pathConfig, accountFileUpdater, serviceEnvironmentConfig, userAgent);
|
||||
account = null;
|
||||
|
||||
m.refreshPreKeys();
|
||||
if (response.isStorageCapable()) {
|
||||
m.syncRemoteStorage();
|
||||
}
|
||||
// Set an initial empty profile so user can be added to groups
|
||||
try {
|
||||
m.updateProfile(UpdateProfile.newBuilder().build());
|
||||
} catch (NoClassDefFoundError e) {
|
||||
logger.warn("Failed to set default profile: {}", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
m.refreshCurrentUsername();
|
||||
} catch (IOException | BaseUsernameException e) {
|
||||
logger.warn("Failed to refresh current username", e);
|
||||
}
|
||||
|
||||
if (newManagerListener != null) {
|
||||
newManagerListener.accept(m);
|
||||
m = null;
|
||||
}
|
||||
} finally {
|
||||
if (m != null) {
|
||||
m.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (account != null) {
|
||||
|
|
|
@ -1351,7 +1351,7 @@ public class SignalAccount implements Closeable {
|
|||
getAccountCapabilities(),
|
||||
encryptedDeviceName,
|
||||
pniAccountData.getLocalRegistrationId(),
|
||||
null); // TODO recoveryPassword?
|
||||
getRecoveryPassword());
|
||||
}
|
||||
|
||||
public AccountAttributes.Capabilities getAccountCapabilities() {
|
||||
|
@ -1533,6 +1533,14 @@ public class SignalAccount implements Closeable {
|
|||
save();
|
||||
}
|
||||
|
||||
public String getRecoveryPassword() {
|
||||
final var masterKey = getPinBackedMasterKey();
|
||||
if (masterKey == null) {
|
||||
return null;
|
||||
}
|
||||
return masterKey.deriveRegistrationRecoveryPassword();
|
||||
}
|
||||
|
||||
public long getStorageManifestVersion() {
|
||||
return getKeyValueStore().getEntry(storageManifestVersion);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue