Example #1
0
        /**
         * Construct a group session for sending messages.
         *
         * @param senderKeyName The (groupId, senderId, deviceId) tuple.  In this case, 'senderId' should be the caller.
         * @return A SenderKeyDistributionMessage that is individually distributed to each member of the group.
         */

        public SenderKeyDistributionMessage Create(SenderKeyName senderKeyName)
        {
            lock (GroupCipher.LOCK)
            {
                try
                {
                    SenderKeyRecord senderKeyRecord = senderKeyStore.LoadSenderKey(senderKeyName);

                    if (senderKeyRecord.IsEmpty())
                    {
                        senderKeyRecord.SetSenderKeyState(KeyHelper.GenerateSenderKeyId(),
                                                          0,
                                                          KeyHelper.GenerateSenderKey(),
                                                          KeyHelper.GenerateSenderSigningKey());
                        senderKeyStore.StoreSenderKey(senderKeyName, senderKeyRecord);
                    }

                    SenderKeyState state = senderKeyRecord.GetSenderKeyState();

                    return(new SenderKeyDistributionMessage(state.GetKeyId(),
                                                            state.GetSenderChainKey().GetIteration(),
                                                            state.GetSenderChainKey().GetSeed(),
                                                            state.GetSigningKeyPublic()));
                }
                catch (InvalidKeyIdException e)
                {
                    throw new Exception(e.Message);
                }
                catch (InvalidKeyException e)
                {
                    throw new Exception(e.Message);
                }
            }
        }
Example #2
0
        /**
         * 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, DecryptionCallback 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 (InvalidKeyException e)
                {
                    throw new InvalidMessageException(e);
                }
                catch (InvalidKeyIdException e)
                {
                    throw new InvalidMessageException(e);
                }
            }
        }