private ChainKey getOrCreateChainKey(SessionState sessionState, ECPublicKey theirEphemeral) { try { if (sessionState.hasReceiverChain(theirEphemeral)) { return sessionState.getReceiverChainKey(theirEphemeral); } else { RootKey rootKey = sessionState.getRootKey(); ECKeyPair ourEphemeral = sessionState.getSenderRatchetKeyPair(); Pair<RootKey, ChainKey> receiverChain = rootKey.createChain(theirEphemeral, ourEphemeral); ECKeyPair ourNewEphemeral = Curve.generateKeyPair(); Pair<RootKey, ChainKey> senderChain = receiverChain.first().createChain(theirEphemeral, ourNewEphemeral); sessionState.setRootKey(senderChain.first()); sessionState.addReceiverChain(theirEphemeral, receiverChain.second()); sessionState.setPreviousCounter(Math.Max(sessionState.getSenderChainKey().getIndex() - 1, 0)); sessionState.setSenderChain(ourNewEphemeral, senderChain.second()); return receiverChain.second(); } } catch (InvalidKeyException e) { throw new InvalidMessageException(e); } }
public static void initializeSession(SessionState sessionState, uint sessionVersion, AliceAxolotlParameters parameters) { try { sessionState.setSessionVersion(sessionVersion); sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey()); sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey()); ECKeyPair sendingRatchetKey = Curve.generateKeyPair(); MemoryStream secrets = new MemoryStream(); if (sessionVersion >= 3) { byte[] discontinuityBytes = getDiscontinuityBytes(); secrets.Write(discontinuityBytes, 0, discontinuityBytes.Length); } byte[] agree1 = Curve.calculateAgreement(parameters.getTheirSignedPreKey(), parameters.getOurIdentityKey().getPrivateKey()); byte[] agree2 = Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(), parameters.getOurBaseKey().getPrivateKey()); byte[] agree3 = Curve.calculateAgreement(parameters.getTheirSignedPreKey(), parameters.getOurBaseKey().getPrivateKey()); secrets.Write(agree1, 0, agree1.Length); secrets.Write(agree2, 0, agree2.Length); secrets.Write(agree3, 0, agree3.Length); if (sessionVersion >= 3 && parameters.getTheirOneTimePreKey().HasValue) { byte[] agree4 = Curve.calculateAgreement(parameters.getTheirOneTimePreKey().ForceGetValue(), parameters.getOurBaseKey().getPrivateKey()); secrets.Write(agree4, 0, agree4.Length); } DerivedKeys derivedKeys = calculateDerivedKeys(sessionVersion, secrets.ToArray()); Pair<RootKey, ChainKey> sendingChain = derivedKeys.getRootKey().createChain(parameters.getTheirRatchetKey(), sendingRatchetKey); sessionState.addReceiverChain(parameters.getTheirRatchetKey(), derivedKeys.getChainKey()); sessionState.setSenderChain(sendingRatchetKey, sendingChain.second()); sessionState.setRootKey(sendingChain.first()); } catch (IOException e) { throw new Exception(e.Message); } }