private KeyExchangeMessage ProcessInitiate(KeyExchangeMessage message) { UInt32 flags = KeyExchangeMessage.RESPONSE_FLAG; SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress); if (message.Version >= 3 && !Curve.VerifySignature(message.IdentityKey.PublicKey, message.BaseKey.Serialize(), message.BaseKeySignature)) { throw new InvalidKeyException("Bad signature!"); } var builder = SymmetricAxolotlParameters.NewBuilder(); if (!sessionRecord.SessionState.HasPendingKeyExchange) { builder.SetOurIdentityKey(_identityKeyStore.GetIdentityKeyPair()) .SetOurBaseKey(Curve.GenerateKeyPair()) .SetOurRatchetKey(Curve.GenerateKeyPair()); } else { builder.SetOurIdentityKey(sessionRecord.SessionState.PendingKeyExchangeIdentityKey) .SetOurBaseKey(sessionRecord.SessionState.PendingKeyExchangeBaseKey) .SetOurRatchetKey(sessionRecord.SessionState.PendingKeyExchangeRatchetKey); flags |= KeyExchangeMessage.SIMULTAENOUS_INITIATE_FLAG; } builder.SetTheirBaseKey(message.BaseKey) .SetTheirRatchetKey(message.RatchetKey) .SetTheirIdentityKey(message.IdentityKey); var parameters = builder.Create(); if (!sessionRecord.IsFresh) sessionRecord.ArchiveCurrentState(); RatchetingSession.InitializeSession(sessionRecord.SessionState, (UInt32)Math.Min(message.MaxVersion, CiphertextMessage.CURRENT_VERSION), parameters); _sessionStore.StoreSession(_remoteAddress, sessionRecord); _identityKeyStore.SaveIdentity(_remoteAddress.Name, message.IdentityKey); byte[] baseKeySignature = Curve.CalculateSignature(parameters.OurIdentityKey.PrivateKey, parameters.OurBaseKey.PublicKey.Serialize()); return new KeyExchangeMessage(sessionRecord.SessionState.GetSessionVersion(), message.Sequence, flags, parameters.OurBaseKey.PublicKey, baseKeySignature, parameters.OurRatchetKey.PublicKey, parameters.OurIdentityKey.PublicKey); }
private void ProcessResponse(KeyExchangeMessage message) { var sessionRecord = _sessionStore.LoadSession(_remoteAddress); var sessionState = sessionRecord.SessionState; var hasPendingKeyExchange = sessionState.HasPendingKeyExchange; var isSimultaneousInitiateResponse = message.IsResponseForSimultaneousInitiate; if (!hasPendingKeyExchange || sessionState.PendingKeyExchangeSequence != message.Sequence) { Console.WriteLine("TAG : " + "No matching sequence for response. Is simultaneous initiate response: " + isSimultaneousInitiateResponse); if (!isSimultaneousInitiateResponse) throw new StaleKeyExchangeException(); else return; } var parameters = SymmetricAxolotlParameters.NewBuilder(); parameters.SetOurBaseKey(sessionRecord.SessionState.PendingKeyExchangeBaseKey) .SetOurRatchetKey(sessionRecord.SessionState.PendingKeyExchangeRatchetKey) .SetOurIdentityKey(sessionRecord.SessionState.PendingKeyExchangeIdentityKey) .SetTheirBaseKey(message.BaseKey) .SetTheirRatchetKey(message.RatchetKey) .SetTheirIdentityKey(message.IdentityKey); if (!sessionRecord.IsFresh) sessionRecord.ArchiveCurrentState(); RatchetingSession.InitializeSession(sessionRecord.SessionState, (UInt32)Math.Min(message.MaxVersion, CiphertextMessage.CURRENT_VERSION), parameters.Create()); if (sessionRecord.SessionState.GetSessionVersion() >= 3 && !Curve.VerifySignature(message.IdentityKey.PublicKey, message.BaseKey.Serialize(), message.BaseKeySignature)) { throw new InvalidKeyException("Base key signature doesn't match!"); } _sessionStore.StoreSession(_remoteAddress, sessionRecord); _identityKeyStore.SaveIdentity(_remoteAddress.Name, message.IdentityKey); }
public KeyExchangeMessage Process(KeyExchangeMessage message) { lock (SessionCipher.SESSION_LOCK) { if (!_identityKeyStore.IsTrustedIdentity(_remoteAddress.Name, message.IdentityKey)) { throw new UntrustedIdentityException(); } KeyExchangeMessage responseMessage = null; if (message.IsInitiate) responseMessage = ProcessInitiate(message); else ProcessResponse(message); return responseMessage; } }