Beispiel #1
0
        public byte[] Decrypt(byte[] senderKeyMessageBytes, IDecryptionCallback callback)
        {
            lock(LOCK)
            {
                try
                {
                    var record = _senderKeyStore.LoadSenderKey(_senderKeyId);

                    if(record.IsEmpty)
                    {
                        throw new Exception("No sender key for: " + _senderKeyId);
                    }

                    var senderKeyMessage = new SenderKeyMessage(senderKeyMessageBytes);
                    var senderKeyState = record.GetSenderKeyState(senderKeyMessage.KeyId);

                    senderKeyMessage.VerifySignature(senderKeyState.SigningKeyPublic);

                    var senderKey = GetSenderKey(senderKeyState, senderKeyMessage.Iteration);

                    byte[] plaintext = GetPlainText(senderKey.Iv, senderKey.CipherKey, senderKeyMessage.CipherText);

                    callback.HandlePlaintext(plaintext);

                    _senderKeyStore.StoreSenderKey(_senderKeyId, record);

                    return plaintext;
                }
                catch(Exception e)
                {
                    throw new InvalidMessageException(e);
                }
            }
        }
        /**
         * Decrypt a SenderKey group message.
         *
         * @param senderKeyMessageBytes The received ciphertext.
         * @param callback   A callback that is triggered after decryption is complete,
         *                    but before the updated session state has been committed to the session
         *                    DB.  This allows some implementations to store the committed plaintext
         *                    to a DB first, in case they are concerned with a crash happening between
         *                    the time the session state is updated but before they're able to store
         *                    the plaintext to disk.
         * @return Plaintext
         * @throws LegacyMessageException
         * @throws InvalidMessageException
         * @throws DuplicateMessageException
         */
        public byte[] Decrypt(byte[] senderKeyMessageBytes, IDecryptionCallback callback)
        {
            lock (Lock)
            {
                try
                {
                    SenderKeyRecord record = _senderKeyStore.LoadSenderKey(_senderKeyId);

                    if (record.IsEmpty())
                    {
                        throw new NoSessionException("No sender key for: " + _senderKeyId);
                    }

                    SenderKeyMessage senderKeyMessage = new SenderKeyMessage(senderKeyMessageBytes);
                    SenderKeyState   senderKeyState   = record.GetSenderKeyState(senderKeyMessage.GetKeyId());

                    senderKeyMessage.VerifySignature(senderKeyState.GetSigningKeyPublic());

                    SenderMessageKey senderKey = GetSenderKey(senderKeyState, senderKeyMessage.GetIteration());

                    byte[] plaintext = GetPlainText(senderKey.GetIv(), senderKey.GetCipherKey(), senderKeyMessage.GetCipherText());

                    callback.HandlePlaintext(plaintext);

                    _senderKeyStore.StoreSenderKey(_senderKeyId, record);

                    return(plaintext);
                }
                catch (Exception e) when(e is InvalidKeyException || e is InvalidKeyIdException)
                {
                    throw new InvalidMessageException(e);
                }
            }
        }
Beispiel #3
0
        /**
         * Decrypt a message.
         *
         * @param  ciphertext The {@link SignalMessage} to decrypt.
         * @param  callback   A callback that is triggered after decryption is complete,
         *                    but before the updated session state has been committed to the session
         *                    DB.  This allows some implementations to store the committed plaintext
         *                    to a DB first, in case they are concerned with a crash happening between
         *                    the time the session state is updated but before they're able to store
         *                    the plaintext to disk.
         *
         * @return The plaintext.
         * @throws InvalidMessageException if the input is not valid ciphertext.
         * @throws DuplicateMessageException if the input is a message that has already been received.
         * @throws LegacyMessageException if the input is a message formatted by a protocol version that
         *                                is no longer supported.
         * @throws NoSessionException if there is no established session for this contact.
         */
        public byte[] Decrypt(SignalMessage ciphertext, IDecryptionCallback callback)

        {
            lock (SessionLock)
            {
                if (!_sessionStore.ContainsSession(_remoteAddress))
                {
                    throw new NoSessionException($"No session for: {_remoteAddress}");
                }

                SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress);
                byte[]        plaintext     = Decrypt(sessionRecord, ciphertext);

                callback.HandlePlaintext(plaintext);

                _sessionStore.StoreSession(_remoteAddress, sessionRecord);

                return(plaintext);
            }
        }
Beispiel #4
0
        public byte[] Decrypt(PreKeyWhisperMessage ciphertext, IDecryptionCallback callback)
        {
            lock(SESSION_LOCK)
            {
                SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress);
                Maybe<UInt32> unsignedPreKeyId = _sessionBuilder.Process(sessionRecord, ciphertext);
                byte[] plaintext = Decrypt(sessionRecord, ciphertext.Message);

                callback.HandlePlaintext(plaintext);

                _sessionStore.StoreSession(_remoteAddress, sessionRecord);

                if(unsignedPreKeyId.HasValue)
                {
                    _preKeyStore.RemovePreKey(unsignedPreKeyId.Value);
                }

                return plaintext;
            }
        }
Beispiel #5
0
        /**
         * Decrypt a message.
         *
         * @param  ciphertext The {@link PreKeySignalMessage} to decrypt.
         * @param  callback   A callback that is triggered after decryption is complete,
         *                    but before the updated session state has been committed to the session
         *                    DB.  This allows some implementations to store the committed plaintext
         *                    to a DB first, in case they are concerned with a crash happening between
         *                    the time the session state is updated but before they're able to store
         *                    the plaintext to disk.
         *
         * @return The plaintext.
         * @throws InvalidMessageException if the input is not valid ciphertext.
         * @throws DuplicateMessageException if the input is a message that has already been received.
         * @throws LegacyMessageException if the input is a message formatted by a protocol version that
         *                                is no longer supported.
         * @throws InvalidKeyIdException when there is no local {@link org.whispersystems.libsignal.state.PreKeyRecord}
         *                               that corresponds to the PreKey ID in the message.
         * @throws InvalidKeyException when the message is formatted incorrectly.
         * @throws UntrustedIdentityException when the {@link IdentityKey} of the sender is untrusted.
         */
        public byte[] Decrypt(PreKeySignalMessage ciphertext, IDecryptionCallback callback)

        {
            lock (SessionLock)
            {
                SessionRecord sessionRecord    = _sessionStore.LoadSession(_remoteAddress);
                May <uint>    unsignedPreKeyId = _sessionBuilder.Process(sessionRecord, ciphertext);
                byte[]        plaintext        = Decrypt(sessionRecord, ciphertext.GetSignalMessage());

                callback.HandlePlaintext(plaintext);

                _sessionStore.StoreSession(_remoteAddress, sessionRecord);

                if (unsignedPreKeyId.HasValue)
                {
                    _preKeyStore.RemovePreKey(unsignedPreKeyId.ForceGetValue());
                }

                return(plaintext);
            }
        }
Beispiel #6
0
        /**
         * Decrypt a message.
         *
         * @param  ciphertext The {@link SignalMessage} to decrypt.
         * @param  callback   A callback that is triggered after decryption is complete,
         *                    but before the updated session state has been committed to the session
         *                    DB.  This allows some implementations to store the committed plaintext
         *                    to a DB first, in case they are concerned with a crash happening between
         *                    the time the session state is updated but before they're able to store
         *                    the plaintext to disk.
         *
         * @return The plaintext.
         * @throws InvalidMessageException if the input is not valid ciphertext.
         * @throws DuplicateMessageException if the input is a message that has already been received.
         * @throws LegacyMessageException if the input is a message formatted by a protocol version that
         *                                is no longer supported.
         * @throws NoSessionException if there is no established session for this contact.
         */
        public byte[] Decrypt(SignalMessage ciphertext, IDecryptionCallback callback)
        {
            lock (SessionLock)
            {
                if (!_sessionStore.ContainsSession(_remoteAddress))
                {
                    throw new NoSessionException($"No session for: {_remoteAddress}");
                }

                SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress);
                byte[]        plaintext     = Decrypt(sessionRecord, ciphertext);

                if (!_identityKeyStore.IsTrustedIdentity(_remoteAddress, sessionRecord.GetSessionState().GetRemoteIdentityKey(), Direction.Receiving))
                {
                    throw new UntrustedIdentityException(_remoteAddress.Name, sessionRecord.GetSessionState().GetRemoteIdentityKey());
                }

                callback.HandlePlaintext(plaintext);

                _sessionStore.StoreSession(_remoteAddress, sessionRecord);

                return(plaintext);
            }
        }
Beispiel #7
0
        public byte[] Decrypt(WhisperMessage ciphertext, IDecryptionCallback callback)
        {
            lock(SESSION_LOCK)
            {

                if(!_sessionStore.ContainsSession(_remoteAddress))
                {
                    throw new NoSessionException("No session for: " + _remoteAddress);
                }

                SessionRecord sessionRecord = _sessionStore.LoadSession(_remoteAddress);
                byte[] plaintext = Decrypt(sessionRecord, ciphertext);

                callback.HandlePlaintext(plaintext);

                _sessionStore.StoreSession(_remoteAddress, sessionRecord);

                return plaintext;
            }
        }