import org.asamk.signal.manager.helper.AccountFileUpdater;
import org.asamk.signal.manager.helper.PinHelper;
import org.asamk.signal.manager.storage.SignalAccount;
+import org.asamk.signal.manager.util.KeyUtils;
import org.asamk.signal.manager.util.NumberVerificationUtils;
import org.asamk.signal.manager.util.Utils;
import org.signal.libsignal.usernames.BaseUsernameException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.push.ACI;
import org.whispersystems.signalservice.api.push.PNI;
+import org.whispersystems.signalservice.api.push.ServiceIdType;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException;
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
import java.io.IOException;
import java.util.function.Consumer;
+import static org.asamk.signal.manager.config.ServiceConfig.PREKEY_MAXIMUM_ID;
+
public class RegistrationManagerImpl implements RegistrationManager {
private final static Logger logger = LoggerFactory.getLogger(RegistrationManagerImpl.class);
public void verifyAccount(
String verificationCode, String pin
) throws IOException, PinLockedException, IncorrectPinException {
- var sessionId = account.getSessionId(account.getNumber());
- final var result = NumberVerificationUtils.verifyNumber(sessionId,
+ if (account.getPniIdentityKeyPair() == null) {
+ account.setPniIdentityKeyPair(KeyUtils.generateIdentityKeyPair());
+ }
+
+ final var aciPreKeys = generatePreKeysForType(ServiceIdType.ACI);
+ final var pniPreKeys = generatePreKeysForType(ServiceIdType.PNI);
+ final var result = NumberVerificationUtils.verifyNumber(account.getSessionId(account.getNumber()),
verificationCode,
pin,
pinHelper,
- this::verifyAccountWithCode);
+ (sessionId1, verificationCode1, registrationLock) -> verifyAccountWithCode(sessionId1,
+ verificationCode1,
+ registrationLock,
+ aciPreKeys,
+ pniPreKeys));
final var response = result.first();
final var masterKey = result.second();
if (masterKey == null) {
//accountManager.setGcmId(Optional.of(GoogleCloudMessaging.getInstance(this).register(REGISTRATION_ID)));
final var aci = ACI.parseOrNull(response.getUuid());
final var pni = PNI.parseOrNull(response.getPni());
- account.finishRegistration(aci, pni, masterKey, pin);
+ account.finishRegistration(aci, pni, masterKey, pin, aciPreKeys, pniPreKeys);
accountFileUpdater.updateAccountIdentifiers(account.getNumber(), aci);
ManagerImpl m = null;
}
private VerifyAccountResponse verifyAccountWithCode(
- final String sessionId, final String verificationCode, final String registrationLock
+ final String sessionId,
+ final String verificationCode,
+ final String registrationLock,
+ final PreKeyCollection aciPreKeys,
+ final PreKeyCollection pniPreKeys
) throws IOException {
try {
Utils.handleResponseException(accountManager.verifyAccount(verificationCode, sessionId));
return Utils.handleResponseException(accountManager.registerAccount(sessionId,
null,
account.getAccountAttributes(registrationLock),
+ aciPreKeys,
+ pniPreKeys,
+ null,
true));
}
+ private PreKeyCollection generatePreKeysForType(ServiceIdType serviceIdType) {
+ final var accountData = account.getAccountData(serviceIdType);
+ final var keyPair = accountData.getIdentityKeyPair();
+ final var preKeyMetadata = accountData.getPreKeyMetadata();
+
+ final var preKeyIdOffset = preKeyMetadata.getPreKeyIdOffset();
+ final var oneTimeEcPreKeys = KeyUtils.generatePreKeyRecords(preKeyIdOffset);
+ final var nextSignedPreKeyId = preKeyMetadata.getNextSignedPreKeyId();
+ final var signedPreKey = KeyUtils.generateSignedPreKeyRecord(nextSignedPreKeyId, keyPair);
+
+ final var privateKey = keyPair.getPrivateKey();
+ final var kyberPreKeyIdOffset = preKeyMetadata.getKyberPreKeyIdOffset();
+ final var oneTimeKyberPreKeys = KeyUtils.generateKyberPreKeyRecords(kyberPreKeyIdOffset, privateKey);
+ final var lastResortKyberPreKeyId = (kyberPreKeyIdOffset + oneTimeKyberPreKeys.size()) % PREKEY_MAXIMUM_ID;
+ final var lastResortKyberPreKey = KeyUtils.generateKyberPreKeyRecord(lastResortKyberPreKeyId, privateKey);
+
+ return new PreKeyCollection(keyPair,
+ nextSignedPreKeyId,
+ preKeyIdOffset,
+ lastResortKyberPreKeyId,
+ kyberPreKeyIdOffset,
+ serviceIdType,
+ keyPair.getPublicKey(),
+ signedPreKey,
+ oneTimeEcPreKeys,
+ lastResortKyberPreKey,
+ oneTimeKyberPreKeys);
+ }
+
@Override
public void close() {
if (account != null) {