private byte[] decrypt(SessionState sessionState, WhisperMessage ciphertextMessage) { if (!sessionState.hasSenderChain()) { throw new InvalidMessageException("Uninitialized session!"); } if (ciphertextMessage.getMessageVersion() != sessionState.getSessionVersion()) { throw new InvalidMessageException($"Message version {ciphertextMessage.getMessageVersion()}, but session version {sessionState.getSessionVersion()}"); } uint messageVersion = ciphertextMessage.getMessageVersion(); ECPublicKey theirEphemeral = ciphertextMessage.getSenderRatchetKey(); uint counter = ciphertextMessage.getCounter(); ChainKey chainKey = getOrCreateChainKey(sessionState, theirEphemeral); MessageKeys messageKeys = getOrCreateMessageKeys(sessionState, theirEphemeral, chainKey, counter); ciphertextMessage.verifyMac(messageVersion, sessionState.getRemoteIdentityKey(), sessionState.getLocalIdentityKey(), messageKeys.getMacKey()); byte[] plaintext = getPlaintext(messageVersion, messageKeys, ciphertextMessage.getBody()); sessionState.clearUnacknowledgedPreKeyMessage(); return(plaintext); }
public void setMessageKeys(ECPublicKey senderEphemeral, MessageKeys messageKeys) { Pair <Chain, uint> chainAndIndex = getReceiverChain(senderEphemeral); Chain chain = chainAndIndex.first(); Chain.Types.MessageKey messageKeyStructure = new Chain.Types.MessageKey { CipherKey = ByteString.CopyFrom(messageKeys.getCipherKey()), MacKey = ByteString.CopyFrom(messageKeys.getMacKey()), Index = messageKeys.getCounter(), Iv = ByteString.CopyFrom(messageKeys.getIv()) }; chain.MessageKeys.Add(messageKeyStructure); if (chain.MessageKeys.Count > MAX_MESSAGE_KEYS) { chain.MessageKeys.RemoveAt(0); } sessionStructure.ReceiverChains[(int)chainAndIndex.second()] = chain; }
public void setMessageKeys(ECPublicKey senderEphemeral, MessageKeys messageKeys) { Pair <Chain, uint> chainAndIndex = getReceiverChain(senderEphemeral); Chain chain = chainAndIndex.first(); Chain.Types.MessageKey messageKeyStructure = Chain.Types.MessageKey.CreateBuilder() .SetCipherKey(ByteString.CopyFrom(messageKeys.getCipherKey() /*.getEncoded()*/)) .SetMacKey(ByteString.CopyFrom(messageKeys.getMacKey() /*.getEncoded()*/)) .SetIndex(messageKeys.getCounter()) .SetIv(ByteString.CopyFrom(messageKeys.getIv() /*.getIV()*/)) .Build(); Chain updatedChain = chain.ToBuilder() .AddMessageKeys(messageKeyStructure) .Build(); this.sessionStructure = this.sessionStructure.ToBuilder() .SetReceiverChains((int)chainAndIndex.second(), updatedChain) // TODO: conv .Build(); }
/** * Encrypt a message. * * @param paddedMessage The plaintext message bytes, optionally padded to a constant multiple. * @return A ciphertext message encrypted to the recipient+device tuple. */ public CiphertextMessage encrypt(byte[] paddedMessage) { lock (SESSION_LOCK) { SessionRecord sessionRecord = sessionStore.loadSession(remoteAddress); SessionState sessionState = sessionRecord.getSessionState(); ChainKey chainKey = sessionState.getSenderChainKey(); MessageKeys messageKeys = chainKey.getMessageKeys(); ECPublicKey senderEphemeral = sessionState.getSenderRatchetKey(); uint previousCounter = sessionState.getPreviousCounter(); uint sessionVersion = sessionState.getSessionVersion(); byte[] ciphertextBody = getCiphertext(sessionVersion, messageKeys, paddedMessage); CiphertextMessage ciphertextMessage = new WhisperMessage(sessionVersion, messageKeys.getMacKey(), senderEphemeral, chainKey.getIndex(), previousCounter, ciphertextBody, sessionState.getLocalIdentityKey(), sessionState.getRemoteIdentityKey()); if (sessionState.hasUnacknowledgedPreKeyMessage()) { SessionState.UnacknowledgedPreKeyMessageItems items = sessionState.getUnacknowledgedPreKeyMessageItems(); uint localRegistrationId = sessionState.getLocalRegistrationId(); ciphertextMessage = new PreKeyWhisperMessage(sessionVersion, localRegistrationId, items.getPreKeyId(), items.getSignedPreKeyId(), items.getBaseKey(), sessionState.getLocalIdentityKey(), (WhisperMessage)ciphertextMessage); } sessionState.setSenderChainKey(chainKey.getNextChainKey()); sessionStore.storeSession(remoteAddress, sessionRecord); return(ciphertextMessage); } }
public void setMessageKeys(ECPublicKey senderEphemeral, MessageKeys messageKeys) { Pair <Chain, uint> chainAndIndex = getReceiverChain(senderEphemeral); Chain chain = chainAndIndex.first(); Chain.Types.MessageKey messageKeyStructure = Chain.Types.MessageKey.CreateBuilder() .SetCipherKey(ByteString.CopyFrom(messageKeys.getCipherKey())) .SetMacKey(ByteString.CopyFrom(messageKeys.getMacKey())) .SetIndex(messageKeys.getCounter()) .SetIv(ByteString.CopyFrom(messageKeys.getIv())) .Build(); Chain.Builder updatedChain = chain.ToBuilder().AddMessageKeys(messageKeyStructure); if (updatedChain.MessageKeysList.Count > MAX_MESSAGE_KEYS) { updatedChain.MessageKeysList.RemoveAt(0); } sessionStructure = sessionStructure.ToBuilder() .SetReceiverChains((int)chainAndIndex.second(), updatedChain.Build()) .Build(); }
/** * Encrypt a message. * * @param paddedMessage The plaintext message bytes, optionally padded to a constant multiple. * @return A ciphertext message encrypted to the recipient+device tuple. */ public CiphertextMessage encrypt(byte[] paddedMessage) { lock (SESSION_LOCK) { SessionRecord sessionRecord = sessionStore.LoadSession(remoteAddress); SessionState sessionState = sessionRecord.getSessionState(); ChainKey chainKey = sessionState.getSenderChainKey(); MessageKeys messageKeys = chainKey.getMessageKeys(); ECPublicKey senderEphemeral = sessionState.getSenderRatchetKey(); uint previousCounter = sessionState.getPreviousCounter(); uint sessionVersion = sessionState.getSessionVersion(); byte[] ciphertextBody = getCiphertext(messageKeys, paddedMessage); CiphertextMessage ciphertextMessage = new SignalMessage(sessionVersion, messageKeys.getMacKey(), senderEphemeral, chainKey.getIndex(), previousCounter, ciphertextBody, sessionState.getLocalIdentityKey(), sessionState.getRemoteIdentityKey()); if (sessionState.hasUnacknowledgedPreKeyMessage()) { SessionState.UnacknowledgedPreKeyMessageItems items = sessionState.getUnacknowledgedPreKeyMessageItems(); uint localRegistrationId = sessionState.GetLocalRegistrationId(); ciphertextMessage = new PreKeySignalMessage(sessionVersion, localRegistrationId, items.getPreKeyId(), items.getSignedPreKeyId(), items.getBaseKey(), sessionState.getLocalIdentityKey(), (SignalMessage)ciphertextMessage); } sessionState.setSenderChainKey(chainKey.getNextChainKey()); if (!identityKeyStore.IsTrustedIdentity(remoteAddress, sessionState.getRemoteIdentityKey(), Direction.SENDING)) { throw new UntrustedIdentityException(remoteAddress.Name, sessionState.getRemoteIdentityKey()); } identityKeyStore.SaveIdentity(remoteAddress, sessionState.getRemoteIdentityKey()); sessionStore.StoreSession(remoteAddress, sessionRecord); return(ciphertextMessage); } }