private byte[] decrypt(SessionRecord sessionRecord, WhisperMessage ciphertext) { lock (SESSION_LOCK) { IEnumerator<SessionState> previousStates = sessionRecord.getPreviousSessionStates().GetEnumerator(); //iterator LinkedList<Exception> exceptions = new LinkedList<Exception>(); try { SessionState sessionState = new SessionState(sessionRecord.getSessionState()); byte[] plaintext = decrypt(sessionState, ciphertext); sessionRecord.setState(sessionState); return plaintext; } catch (InvalidMessageException e) { exceptions.AddLast(e); // add (java default behavioir addlast) } while (previousStates.MoveNext()) //hasNext(); { try { SessionState promotedState = new SessionState(previousStates.Current); //.next() byte[] plaintext = decrypt(promotedState, ciphertext); sessionRecord.getPreviousSessionStates().Remove(previousStates.Current); // previousStates.remove() sessionRecord.promoteState(promotedState); return plaintext; } catch (InvalidMessageException e) { exceptions.AddLast(e); } } throw new InvalidMessageException("No valid sessions.", exceptions); } }
public void StoreSession(AxolotlAddress address, SessionRecord record) { sessionStore.StoreSession(address, record); }
public void StoreSession(AxolotlAddress address, SessionRecord record) { sessions[address] = record.serialize(); }
private May<uint> processV2(SessionRecord sessionRecord, PreKeyWhisperMessage message) { if (!message.getPreKeyId().HasValue) { throw new InvalidKeyIdException("V2 message requires one time prekey id!"); } if (!preKeyStore.ContainsPreKey(message.getPreKeyId().ForceGetValue()) && sessionStore.ContainsSession(remoteAddress)) { //Log.w(TAG, "We've already processed the prekey part of this V2 session, letting bundled message fall through..."); return May<uint>.NoValue; //May.absent(); } ECKeyPair ourPreKey = preKeyStore.LoadPreKey(message.getPreKeyId().ForceGetValue()).getKeyPair(); BobAxolotlParameters.Builder parameters = BobAxolotlParameters.newBuilder(); parameters.setOurIdentityKey(identityKeyStore.GetIdentityKeyPair()) .setOurSignedPreKey(ourPreKey) .setOurRatchetKey(ourPreKey) .setOurOneTimePreKey(May<ECKeyPair>.NoValue) //absent .setTheirIdentityKey(message.getIdentityKey()) .setTheirBaseKey(message.getBaseKey()); if (!sessionRecord.isFresh()) sessionRecord.archiveCurrentState(); RatchetingSession.initializeSession(sessionRecord.getSessionState(), message.getMessageVersion(), parameters.create()); sessionRecord.getSessionState().setLocalRegistrationId(identityKeyStore.GetLocalRegistrationId()); sessionRecord.getSessionState().setRemoteRegistrationId(message.getRegistrationId()); sessionRecord.getSessionState().setAliceBaseKey(message.getBaseKey().serialize()); if (message.getPreKeyId().ForceGetValue() != Medium.MAX_VALUE) { return message.getPreKeyId(); } else { return May<uint>.NoValue; // May.absent(); } }
private May<uint> processV3(SessionRecord sessionRecord, PreKeyWhisperMessage message) { if (sessionRecord.hasSessionState(message.getMessageVersion(), message.getBaseKey().serialize())) { //Log.w(TAG, "We've already setup a session for this V3 message, letting bundled message fall through..."); return May<uint>.NoValue; } ECKeyPair ourSignedPreKey = signedPreKeyStore.LoadSignedPreKey(message.getSignedPreKeyId()).getKeyPair(); BobAxolotlParameters.Builder parameters = BobAxolotlParameters.newBuilder(); parameters.setTheirBaseKey(message.getBaseKey()) .setTheirIdentityKey(message.getIdentityKey()) .setOurIdentityKey(identityKeyStore.GetIdentityKeyPair()) .setOurSignedPreKey(ourSignedPreKey) .setOurRatchetKey(ourSignedPreKey); if (message.getPreKeyId().HasValue) { parameters.setOurOneTimePreKey(new May<ECKeyPair>(preKeyStore.LoadPreKey(message.getPreKeyId().ForceGetValue()).getKeyPair())); } else { parameters.setOurOneTimePreKey(May<ECKeyPair>.NoValue); } if (!sessionRecord.isFresh()) sessionRecord.archiveCurrentState(); RatchetingSession.initializeSession(sessionRecord.getSessionState(), message.getMessageVersion(), parameters.create()); sessionRecord.getSessionState().setLocalRegistrationId(identityKeyStore.GetLocalRegistrationId()); sessionRecord.getSessionState().setRemoteRegistrationId(message.getRegistrationId()); sessionRecord.getSessionState().setAliceBaseKey(message.getBaseKey().serialize()); if (message.getPreKeyId().HasValue && message.getPreKeyId().ForceGetValue() != Medium.MAX_VALUE) { return message.getPreKeyId(); } else { return May<uint>.NoValue; } }
/** * Build a new session from a received {@link org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage}. * * After a session is constructed in this way, the embedded {@link org.whispersystems.libaxolotl.protocol.WhisperMessage} * can be decrypted. * * @param message The received {@link org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage}. * @throws org.whispersystems.libaxolotl.InvalidKeyIdException when there is no local * {@link org.whispersystems.libaxolotl.state.PreKeyRecord} * that corresponds to the PreKey ID in * the message. * @throws org.whispersystems.libaxolotl.InvalidKeyException when the message is formatted incorrectly. * @throws org.whispersystems.libaxolotl.UntrustedIdentityException when the {@link IdentityKey} of the sender is untrusted. */ /*package*/ internal May<uint> process(SessionRecord sessionRecord, PreKeyWhisperMessage message) { uint messageVersion = message.getMessageVersion(); IdentityKey theirIdentityKey = message.getIdentityKey(); May<uint> unsignedPreKeyId; if (!identityKeyStore.IsTrustedIdentity(remoteAddress.getName(), theirIdentityKey)) { throw new UntrustedIdentityException(remoteAddress.getName(), theirIdentityKey); } switch (messageVersion) { case 2: unsignedPreKeyId = processV2(sessionRecord, message); break; case 3: unsignedPreKeyId = processV3(sessionRecord, message); break; default: throw new Exception("Unknown version: " + messageVersion); } identityKeyStore.SaveIdentity(remoteAddress.getName(), theirIdentityKey); return unsignedPreKeyId; }
public void StoreSession(AxolotlAddress address, SessionRecord record) { DeleteSession(address); // TODO: sqlite-net combined private keys for insertOrReplace var session = new Session() { DeviceId = address.DeviceId, Name = address.Name, Record = record.serialize() }; conn.InsertOrReplace(session); return; }
public void storeSession(AxolotlAddress address, SessionRecord record) { if (sessions.ContainsKey(address)) //mimic HashMap update behaviour { sessions.Remove(address); } sessions.Add(address, record.serialize()); // put }