Esempio n. 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);
                }
            }
        }
Esempio n. 2
0
        /**
         * Encrypt a message.
         *
         * @param paddedPlaintext The plaintext message bytes, optionally padded.
         * @return Ciphertext.
         * @throws NoSessionException
         */
        public byte[] encrypt(byte[] paddedPlaintext)
        {
            lock (LOCK)
            {
                try
                {
                    SenderKeyRecord  record         = senderKeyStore.loadSenderKey(senderKeyId);
                    SenderKeyState   senderKeyState = record.getSenderKeyState();
                    SenderMessageKey senderKey      = senderKeyState.getSenderChainKey().getSenderMessageKey();
                    byte[]           ciphertext     = getCipherText(senderKey.getIv(), senderKey.getCipherKey(), paddedPlaintext);

                    SenderKeyMessage senderKeyMessage = new SenderKeyMessage(senderKeyState.getKeyId(),
                                                                             senderKey.getIteration(),
                                                                             ciphertext,
                                                                             senderKeyState.getSigningKeyPrivate());

                    senderKeyState.setSenderChainKey(senderKeyState.getSenderChainKey().getNext());

                    senderKeyStore.storeSenderKey(senderKeyId, record);

                    return(senderKeyMessage.serialize());
                }
                catch (InvalidKeyIdException e)
                {
                    throw new NoSessionException(e);
                }
            }
        }
Esempio n. 3
0
 /**
  * Construct a group session for receiving messages from senderKeyName.
  *
  * @param senderKeyName The (groupId, senderId, deviceId) tuple associated with the SenderKeyDistributionMessage.
  * @param senderKeyDistributionMessage A received SenderKeyDistributionMessage.
  */
 public void process(SenderKeyName senderKeyName, SenderKeyDistributionMessage senderKeyDistributionMessage)
 {
     lock (GroupCipher.LOCK)
     {
         SenderKeyRecord senderKeyRecord = senderKeyStore.loadSenderKey(senderKeyName);
         senderKeyRecord.addSenderKeyState(senderKeyDistributionMessage.getId(),
                                           senderKeyDistributionMessage.getIteration(),
                                           senderKeyDistributionMessage.getChainKey(),
                                           senderKeyDistributionMessage.getSignatureKey());
         senderKeyStore.storeSenderKey(senderKeyName, senderKeyRecord);
     }
 }
Esempio n. 4
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);
                }
            }
        }
 public void storeSenderKey(SenderKeyName senderKeyName, SenderKeyRecord record)
 {
     store[senderKeyName] = record;
 }