/// <summary> /// Build a new session from a {@link org.whispersystems.libsignal.state.PreKeyBundle} retrieved from /// a server. /// </summary> /// @param preKey A PreKey for the destination recipient, retrieved from a server. /// @throws InvalidKeyException when the {@link org.whispersystems.libsignal.state.PreKeyBundle} is /// badly formatted. /// @throws org.whispersystems.libsignal.UntrustedIdentityException when the sender's /// {@link IdentityKey} is not /// trusted. /// public void Process(PreKeyBundle preKey) { lock (SessionCipher.SessionLock) { if (!_identityKeyStore.IsTrustedIdentity(_remoteAddress, preKey.GetIdentityKey(), Direction.Sending)) { throw new UntrustedIdentityException(_remoteAddress.Name, preKey.GetIdentityKey()); } if (preKey.GetSignedPreKey() != null && !Curve.VerifySignature(preKey.GetIdentityKey().GetPublicKey(), preKey.GetSignedPreKey().Serialize(), preKey.GetSignedPreKeySignature())) { throw new InvalidKeyException("Invalid signature on device key!"); } if (preKey.GetSignedPreKey() == null) { throw new InvalidKeyException("No signed prekey!"); } SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress); EcKeyPair ourBaseKey = Curve.GenerateKeyPair(); IEcPublicKey theirSignedPreKey = preKey.GetSignedPreKey(); IEcPublicKey test = preKey.GetPreKey(); May <IEcPublicKey> theirOneTimePreKey = (test == null) ? May <IEcPublicKey> .NoValue : new May <IEcPublicKey>(test); May <uint> theirOneTimePreKeyId = theirOneTimePreKey.HasValue ? new May <uint>(preKey.GetPreKeyId()) : May <uint> .NoValue; AliceSignalProtocolParameters.Builder parameters = AliceSignalProtocolParameters.NewBuilder(); parameters.SetOurBaseKey(ourBaseKey) .SetOurIdentityKey(_identityKeyStore.GetIdentityKeyPair()) .SetTheirIdentityKey(preKey.GetIdentityKey()) .SetTheirSignedPreKey(theirSignedPreKey) .SetTheirRatchetKey(theirSignedPreKey) .SetTheirOneTimePreKey(theirOneTimePreKey); if (!sessionRecord.IsFresh()) { sessionRecord.ArchiveCurrentState(); } RatchetingSession.InitializeSession(sessionRecord.GetSessionState(), parameters.Create()); sessionRecord.GetSessionState().SetUnacknowledgedPreKeyMessage(theirOneTimePreKeyId, preKey.GetSignedPreKeyId(), ourBaseKey.GetPublicKey()); sessionRecord.GetSessionState().SetLocalRegistrationId(_identityKeyStore.GetLocalRegistrationId()); sessionRecord.GetSessionState().SetRemoteRegistrationId(preKey.GetRegistrationId()); sessionRecord.GetSessionState().SetAliceBaseKey(ourBaseKey.GetPublicKey().Serialize()); _identityKeyStore.SaveIdentity(_remoteAddress, preKey.GetIdentityKey()); _sessionStore.StoreSession(_remoteAddress, sessionRecord); } }
/** * Build a new session from a {@link org.whispersystems.libsignal.state.PreKeyBundle} retrieved from * a server. * * @param preKey A PreKey for the destination recipient, retrieved from a server. * @throws InvalidKeyException when the {@link org.whispersystems.libsignal.state.PreKeyBundle} is * badly formatted. * @throws org.whispersystems.libsignal.UntrustedIdentityException when the sender's * {@link IdentityKey} is not * trusted. */ public void process(PreKeyBundle preKey) { lock (SessionCipher.SESSION_LOCK) { if (!identityKeyStore.IsTrustedIdentity(remoteAddress.getName(), preKey.getIdentityKey())) { throw new UntrustedIdentityException(remoteAddress.getName(), preKey.getIdentityKey()); } if (preKey.getSignedPreKey() != null && !Curve.verifySignature(preKey.getIdentityKey().getPublicKey(), preKey.getSignedPreKey().serialize(), preKey.getSignedPreKeySignature())) { throw new InvalidKeyException("Invalid signature on device key!"); } if (preKey.getSignedPreKey() == null) { throw new InvalidKeyException("No signed prekey!"); } SessionRecord sessionRecord = sessionStore.LoadSession(remoteAddress); ECKeyPair ourBaseKey = Curve.generateKeyPair(); ECPublicKey theirSignedPreKey = preKey.getSignedPreKey(); ECPublicKey test = preKey.getPreKey(); May <ECPublicKey> theirOneTimePreKey = (test == null) ? May <ECPublicKey> .NoValue : new May <ECPublicKey>(test); May <uint> theirOneTimePreKeyId = theirOneTimePreKey.HasValue ? new May <uint>(preKey.getPreKeyId()) : May <uint> .NoValue; AliceSignalProtocolParameters.Builder parameters = AliceSignalProtocolParameters.newBuilder(); parameters.setOurBaseKey(ourBaseKey) .setOurIdentityKey(identityKeyStore.GetIdentityKeyPair()) .setTheirIdentityKey(preKey.getIdentityKey()) .setTheirSignedPreKey(theirSignedPreKey) .setTheirRatchetKey(theirSignedPreKey) .setTheirOneTimePreKey(theirOneTimePreKey); if (!sessionRecord.isFresh()) { sessionRecord.archiveCurrentState(); } RatchetingSession.initializeSession(sessionRecord.getSessionState(), parameters.create()); sessionRecord.getSessionState().setUnacknowledgedPreKeyMessage(theirOneTimePreKeyId, preKey.getSignedPreKeyId(), ourBaseKey.getPublicKey()); sessionRecord.getSessionState().setLocalRegistrationId(identityKeyStore.GetLocalRegistrationId()); sessionRecord.getSessionState().setRemoteRegistrationId(preKey.getRegistrationId()); sessionRecord.getSessionState().setAliceBaseKey(ourBaseKey.getPublicKey().serialize()); sessionStore.StoreSession(remoteAddress, sessionRecord); identityKeyStore.SaveIdentity(remoteAddress.getName(), preKey.getIdentityKey()); } }