processPreKeyBundle method

Future<void> processPreKeyBundle(
  1. PreKeyBundle preKey
)

Implementation

Future<void> processPreKeyBundle(PreKeyBundle preKey) async {
  if (!await _identityKeyStore.isTrustedIdentity(
      _remoteAddress, preKey.getIdentityKey(), Direction.sending)) {
    throw UntrustedIdentityException(
        _remoteAddress.getName(), preKey.getIdentityKey());
  }

  if (preKey.getSignedPreKey() != null &&
      !Curve.verifySignature(
          preKey.getIdentityKey().publicKey,
          preKey.getSignedPreKey()!.serialize(),
          preKey.getSignedPreKeySignature())) {
    throw InvalidKeyException('Invalid signature on device key!');
  }

  if (preKey.getSignedPreKey() == null) {
    throw InvalidKeyException('No signed prekey!');
  }

  final sessionRecord = await _sessionStore.loadSession(_remoteAddress);
  final ourBaseKey = Curve.generateKeyPair();
  final theirSignedPreKey = preKey.getSignedPreKey();
  final theirOneTimePreKey = Optional.ofNullable(preKey.getPreKey());
  final theirOneTimePreKeyId = theirOneTimePreKey.isPresent
      ? Optional.ofNullable(preKey.getPreKeyId())
      : const Optional<int>.empty();

  final parameters = AliceSignalProtocolParameters(
    ourBaseKey: ourBaseKey,
    ourIdentityKey: await _identityKeyStore.getIdentityKeyPair(),
    theirIdentityKey: preKey.getIdentityKey(),
    theirSignedPreKey: theirSignedPreKey!,
    theirRatchetKey: theirSignedPreKey,
    theirOneTimePreKey: theirOneTimePreKey,
  );

  if (!sessionRecord.isFresh()) sessionRecord.archiveCurrentState();

  RatchetingSession.initializeSessionAlice(
      sessionRecord.sessionState, parameters);

  sessionRecord.sessionState.setUnacknowledgedPreKeyMessage(
      theirOneTimePreKeyId, preKey.getSignedPreKeyId(), ourBaseKey.publicKey);
  sessionRecord.sessionState.localRegistrationId =
      await _identityKeyStore.getLocalRegistrationId();
  sessionRecord.sessionState.remoteRegistrationId =
      preKey.getRegistrationId();
  sessionRecord.sessionState.aliceBaseKey = ourBaseKey.publicKey.serialize();

  await _identityKeyStore.saveIdentity(
      _remoteAddress, preKey.getIdentityKey());
  await _sessionStore.storeSession(_remoteAddress, sessionRecord);
}