Beispiel #1
0
        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;
        }
Beispiel #3
0
        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();
        }
Beispiel #4
0
        /**
         * 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);
            }
        }