private KeyExchangeMessage ProcessInitiate(KeyExchangeMessage message) { uint flags = KeyExchangeMessage.RESPONSE_FLAG; SessionRecord sessionRecord = sessionStore.LoadSession(remoteAddress); if (message.GetVersion() >= 3 && !Curve.VerifySignature(message.GetIdentityKey().GetPublicKey(), message.GetBaseKey().Serialize(), message.GetBaseKeySignature())) { throw new InvalidKeyException("Bad signature!"); } SymmetricAxolotlParameters.Builder builder = SymmetricAxolotlParameters.NewBuilder(); if (!sessionRecord.GetSessionState().HasPendingKeyExchange()) { builder.SetOurIdentityKey(identityKeyStore.GetIdentityKeyPair()) .SetOurBaseKey(Curve.GenerateKeyPair()) .SetOurRatchetKey(Curve.GenerateKeyPair()); } else { builder.SetOurIdentityKey(sessionRecord.GetSessionState().GetPendingKeyExchangeIdentityKey()) .SetOurBaseKey(sessionRecord.GetSessionState().GetPendingKeyExchangeBaseKey()) .SetOurRatchetKey(sessionRecord.GetSessionState().GetPendingKeyExchangeRatchetKey()); flags |= KeyExchangeMessage.SIMULTAENOUS_INITIATE_FLAG; } builder.SetTheirBaseKey(message.GetBaseKey()) .SetTheirRatchetKey(message.GetRatchetKey()) .SetTheirIdentityKey(message.GetIdentityKey()); SymmetricAxolotlParameters parameters = builder.Create(); if (!sessionRecord.IsFresh()) { sessionRecord.ArchiveCurrentState(); } RatchetingSession.InitializeSession(sessionRecord.GetSessionState(), Math.Min(message.GetMaxVersion(), CipherTextMessage.CURRENT_VERSION), parameters); sessionStore.StoreSession(remoteAddress, sessionRecord); identityKeyStore.SaveIdentity(remoteAddress.GetName(), message.GetIdentityKey()); byte[] baseKeySignature = Curve.CalculateSignature(parameters.GetOurIdentityKey().GetPrivateKey(), parameters.GetOurBaseKey().GetPublicKey().Serialize()); return(new KeyExchangeMessage(sessionRecord.GetSessionState().GetSessionVersion(), message.GetSequence(), flags, parameters.GetOurBaseKey().GetPublicKey(), baseKeySignature, parameters.GetOurRatchetKey().GetPublicKey(), parameters.GetOurIdentityKey().GetPublicKey())); }
private void ProcessResponse(KeyExchangeMessage message) { SessionRecord sessionRecord = sessionStore.LoadSession(remoteAddress); SessionState sessionState = sessionRecord.GetSessionState(); bool hasPendingKeyExchange = sessionState.HasPendingKeyExchange(); bool isSimultaneousInitiateResponse = message.IsResponseForSimultaneousInitiate(); if (!hasPendingKeyExchange || sessionState.GetPendingKeyExchangeSequence() != message.GetSequence()) { //Log.w(TAG, "No matching sequence for response. Is simultaneous initiate response: " + isSimultaneousInitiateResponse); if (!isSimultaneousInitiateResponse) { throw new StaleKeyExchangeException(); } else { return; } } SymmetricAxolotlParameters.Builder parameters = SymmetricAxolotlParameters.NewBuilder(); parameters.SetOurBaseKey(sessionRecord.GetSessionState().GetPendingKeyExchangeBaseKey()) .SetOurRatchetKey(sessionRecord.GetSessionState().GetPendingKeyExchangeRatchetKey()) .SetOurIdentityKey(sessionRecord.GetSessionState().GetPendingKeyExchangeIdentityKey()) .SetTheirBaseKey(message.GetBaseKey()) .SetTheirRatchetKey(message.GetRatchetKey()) .SetTheirIdentityKey(message.GetIdentityKey()); if (!sessionRecord.IsFresh()) { sessionRecord.ArchiveCurrentState(); } RatchetingSession.InitializeSession(sessionRecord.GetSessionState(), Math.Min(message.GetMaxVersion(), CipherTextMessage.CURRENT_VERSION), parameters.Create()); if (sessionRecord.GetSessionState().GetSessionVersion() >= 3 && !Curve.VerifySignature(message.GetIdentityKey().GetPublicKey(), message.GetBaseKey().Serialize(), message.GetBaseKeySignature())) { throw new InvalidKeyException("Base key signature doesn't match!"); } sessionStore.StoreSession(remoteAddress, sessionRecord); identityKeyStore.SaveIdentity(remoteAddress.GetName(), message.GetIdentityKey()); }