Example #1
0
        /// <summary>
        /// Decrypts the key and HMAC concatenation (<see cref="OmemoMessage.cipherText"/>) with the given <paramref name="mk"/> and returns the result.
        /// </summary>
        /// <param name="mk">The message key that should be used for decryption.</param>
        /// <param name="msg">The <see cref="OmemoMessage"/> containing the key and HMAC concatenation (<see cref="OmemoMessage.cipherText"/>).</param>
        /// <param name="msgHmac">The HMAC of the <paramref name="msg"/>.</param>
        /// <param name="assData">Encode(IK_A) || Encode(IK_B) => Concatenation of Alices and Bobs public part of their identity key.</param>
        /// <returns>key || HMAC</returns>
        private byte[] DecryptKeyHmacForDevice(byte[] mk, OmemoMessage msg, byte[] msgHmac, byte[] assData)
        {
            // 32 byte (256 bit) of salt. Initialized with 0s.
            byte[] hkdfOutput = CryptoUtils.HkdfSha256(mk, new byte[32], "OMEMO Message Key Material", 80);
            CryptoUtils.SplitKey(hkdfOutput, out byte[] encKey, out byte[] authKey, out byte[] iv);
            byte[] hmacInput     = CryptoUtils.Concat(assData, msg.ToByteArray());
            byte[] hmacResult    = CryptoUtils.HmacSha256(authKey, hmacInput);
            byte[] hmacTruncated = CryptoUtils.Truncate(hmacResult, 16);

            // Debug trace output:
            Logger.Trace("[" + nameof(DecryptKeyHmacForDevice) + "] " + nameof(mk) + ": " + CryptoUtils.ToHexString(mk));
            Logger.Trace("[" + nameof(DecryptKeyHmacForDevice) + "] " + nameof(msgHmac) + ": " + CryptoUtils.ToHexString(msgHmac));
            Logger.Trace("[" + nameof(DecryptKeyHmacForDevice) + "] " + nameof(assData) + ": " + CryptoUtils.ToHexString(assData));
            Logger.Trace("[" + nameof(DecryptKeyHmacForDevice) + "] " + nameof(hkdfOutput) + ": " + CryptoUtils.ToHexString(hkdfOutput));
            Logger.Trace("[" + nameof(DecryptKeyHmacForDevice) + "] " + nameof(encKey) + ": " + CryptoUtils.ToHexString(encKey));
            Logger.Trace("[" + nameof(DecryptKeyHmacForDevice) + "] " + nameof(authKey) + ": " + CryptoUtils.ToHexString(authKey));
            Logger.Trace("[" + nameof(DecryptKeyHmacForDevice) + "] " + nameof(iv) + ": " + CryptoUtils.ToHexString(iv));
            Logger.Trace("[" + nameof(DecryptKeyHmacForDevice) + "] " + nameof(hmacInput) + ": " + CryptoUtils.ToHexString(hmacInput));
            Logger.Trace("[" + nameof(DecryptKeyHmacForDevice) + "] " + nameof(hmacResult) + ": " + CryptoUtils.ToHexString(hmacResult));
            Logger.Trace("[" + nameof(DecryptKeyHmacForDevice) + "] " + nameof(hmacTruncated) + ": " + CryptoUtils.ToHexString(hmacTruncated));

            if (!hmacTruncated.SequenceEqual(msgHmac))
            {
                throw new OmemoException("Failed to decrypt. HMAC of OmemoMessage does not match.");
            }
            return(CryptoUtils.Aes256CbcDecrypt(encKey, iv, msg.cipherText));
        }
Example #2
0
        //--------------------------------------------------------Attributes:-----------------------------------------------------------------\\
        #region --Attributes--


        #endregion
        //--------------------------------------------------------Constructor:----------------------------------------------------------------\\
        #region --Constructors--


        #endregion
        //--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\
        #region --Set-, Get- Methods--


        #endregion
        //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\
        #region --Misc Methods (Public)--
        /// <summary>
        /// HKDF-SHA-256 using the root key (<paramref name="rk"/>) as HKDF salt, the Diffie-Hellman shared secret (<paramref name="sharedSecret"/>) as HKDF input material and "OMEMO Root Chain" as HKDF info.
        /// </summary>
        /// <param name="rk">Root key.</param>
        /// <param name="sharedSecret">Diffie-Hellman shared secret.</param>
        /// <returns>A <see cref="Tuple"/> containing the new root key (rk) and the new chain key (ck).</returns>
        public static Tuple <byte[], byte[]> KDF_RK(byte[] rk, byte[] sharedSecret)
        {
            byte[] tmp    = CryptoUtils.HkdfSha256(sharedSecret, rk, "OMEMO Root Chain", 64);
            byte[] rk_new = new byte[32];
            Buffer.BlockCopy(tmp, 0, rk_new, 0, rk_new.Length);
            byte[] ck_new = new byte[32];
            Buffer.BlockCopy(tmp, rk_new.Length, ck_new, 0, ck_new.Length);
            return(new Tuple <byte[], byte[]>(rk_new, ck_new));
        }
Example #3
0
        //--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\
        #region --Set-, Get- Methods--


        #endregion
        //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\
        #region --Misc Methods (Public)--
        /// <summary>
        /// Encrypts the given plaintext message and returns the result.
        /// </summary>
        /// <param name="msg">The plain text message to encrypt.</param>
        /// <returns>A tuple consisting out of the cipher text and key-HMAC combination (Tuple[cipherText, keyHmac]).</returns>
        public Tuple <byte[], byte[]> EncryptMessasge(byte[] msg)
        {
            byte[] key = KeyHelper.GenerateSymetricKey();
            // 32 byte (256 bit) of salt. Initialized with 0s.
            byte[] hkdfOutput = CryptoUtils.HkdfSha256(key, new byte[32], "OMEMO Payload", 80);
            CryptoUtils.SplitKey(hkdfOutput, out byte[] encKey, out byte[] authKey, out byte[] iv);
            byte[] cipherText = CryptoUtils.Aes256CbcEncrypt(encKey, iv, msg);
            byte[] hmac       = CryptoUtils.HmacSha256(authKey, cipherText);
            hmac = CryptoUtils.Truncate(hmac, 16);
            byte[] keyHmac = CryptoUtils.Concat(key, hmac);
            return(new Tuple <byte[], byte[]>(cipherText, keyHmac));
        }
Example #4
0
        /// <summary>
        /// Encrypts the given key and HMAC concatenation and returns the result.
        /// </summary>
        /// <param name="keyHmac">The key, HMAC concatenation result.</param>
        /// <param name="session">The <see cref="OmemoSessionModel"/> between the sender and receiver.</param>
        /// <param name="assData">Encode(IK_A) || Encode(IK_B) => Concatenation of Alices and Bobs public part of their identity key.</param>
        private OmemoAuthenticatedMessage EncryptKeyHmacForDevices(byte[] keyHmac, OmemoSessionModel session, byte[] assData)
        {
            byte[] mk = LibSignalUtils.KDF_CK(session.ckS, 0x01);
            session.ckS = LibSignalUtils.KDF_CK(session.ckS, 0x02);
            OmemoMessage omemoMessage = new OmemoMessage(session);

            ++session.nS;
            // 32 byte (256 bit) of salt. Initialized with 0s.
            byte[] hkdfOutput = CryptoUtils.HkdfSha256(mk, new byte[32], "OMEMO Message Key Material", 80);
            CryptoUtils.SplitKey(hkdfOutput, out byte[] encKey, out byte[] authKey, out byte[] iv);
            omemoMessage.cipherText = CryptoUtils.Aes256CbcEncrypt(encKey, iv, keyHmac);
            byte[] omemoMessageBytes = omemoMessage.ToByteArray();
            byte[] hmacInput         = CryptoUtils.Concat(assData, omemoMessageBytes);
            byte[] hmacResult        = CryptoUtils.HmacSha256(authKey, hmacInput);
            byte[] hmacTruncated     = CryptoUtils.Truncate(hmacResult, 16);
            return(new OmemoAuthenticatedMessage(hmacTruncated, omemoMessageBytes));
        }
Example #5
0
        /// <summary>
        /// Tries to decrypt the given <paramref name="cipherContent"/>.
        /// </summary>
        /// <param name="authMsg">The <see cref="OmemoAuthenticatedMessage"/> that should be used for decrypting the <paramref name="cipherContent"/>.</param>
        /// <param name="session">The <see cref="OmemoSessionModel"/> that should be used for decryption.</param>
        /// <param name="cipherContent">The cipher text that should be decrypted.</param>
        /// <returns>On success the plain text for the given <paramref name="cipherContent"/>.</returns>
        public byte[] DecryptMessage(OmemoAuthenticatedMessage authMsg, OmemoSessionModel session, byte[] cipherContent)
        {
            byte[] keyHmac = DecryptKeyHmacForDevice(authMsg, session);
            byte[] key     = new byte[32];
            Buffer.BlockCopy(keyHmac, 0, key, 0, key.Length);
            byte[] hmacRef = new byte[16];
            Buffer.BlockCopy(keyHmac, key.Length, hmacRef, 0, hmacRef.Length);

            // 32 byte (256 bit) of salt. Initialized with 0s.
            byte[] hkdfOutput = CryptoUtils.HkdfSha256(key, new byte[32], "OMEMO Payload", 80);
            CryptoUtils.SplitKey(hkdfOutput, out byte[] encKey, out byte[] authKey, out byte[] iv);
            byte[] hmac = CryptoUtils.HmacSha256(authKey, cipherContent);
            hmac = CryptoUtils.Truncate(hmac, 16);
            if (!hmacRef.SequenceEqual(hmac))
            {
                throw new OmemoException("Failed to decrypt. HMAC does not match.");
            }
            return(CryptoUtils.Aes256CbcDecrypt(encKey, iv, cipherContent));
        }
Example #6
0
        /// <summary>
        /// Encrypts the given key and HMAC concatenation and returns the result.
        /// </summary>
        /// <param name="keyHmac">The key, HMAC concatenation result.</param>
        /// <param name="session">The <see cref="OmemoSessionModel"/> between the sender and receiver.</param>
        /// <param name="assData">Encode(IK_A) || Encode(IK_B) => Concatenation of Alices and Bobs public part of their identity key.</param>
        private OmemoAuthenticatedMessage EncryptKeyHmacForDevices(byte[] keyHmac, OmemoSessionModel session, byte[] assData)
        {
            byte[] mk = LibSignalUtils.KDF_CK(session.ckS, 0x01);
            Logger.Trace("[" + nameof(EncryptKeyHmacForDevices) + "] " + nameof(session.ckS) + ": " + CryptoUtils.ToHexString(session.ckS));
            session.ckS = LibSignalUtils.KDF_CK(session.ckS, 0x02);
            OmemoMessage omemoMessage = new OmemoMessage(session);

            ++session.nS;

            // 32 byte (256 bit) of salt. Initialized with 0s.
            byte[] hkdfOutput = CryptoUtils.HkdfSha256(mk, new byte[32], "OMEMO Message Key Material", 80);
            CryptoUtils.SplitKey(hkdfOutput, out byte[] encKey, out byte[] authKey, out byte[] iv);
            omemoMessage.cipherText = CryptoUtils.Aes256CbcEncrypt(encKey, iv, keyHmac);
            byte[] omemoMessageBytes = omemoMessage.ToByteArray();
            byte[] hmacInput         = CryptoUtils.Concat(assData, omemoMessageBytes);
            byte[] hmacResult        = CryptoUtils.HmacSha256(authKey, hmacInput);
            byte[] hmacTruncated     = CryptoUtils.Truncate(hmacResult, 16);

            // Update the session state:
            if (session.state == SessionState.RECEIVED)
            {
                session.state = SessionState.READY;
            }

            // Debug trace output:
            Logger.Trace("[" + nameof(EncryptKeyHmacForDevices) + "] " + nameof(mk) + ": " + CryptoUtils.ToHexString(mk));
            Logger.Trace("[" + nameof(EncryptKeyHmacForDevices) + "] " + nameof(assData) + ": " + CryptoUtils.ToHexString(assData));
            Logger.Trace("[" + nameof(EncryptKeyHmacForDevices) + "] " + nameof(hkdfOutput) + ": " + CryptoUtils.ToHexString(hkdfOutput));
            Logger.Trace("[" + nameof(EncryptKeyHmacForDevices) + "] " + nameof(encKey) + ": " + CryptoUtils.ToHexString(encKey));
            Logger.Trace("[" + nameof(EncryptKeyHmacForDevices) + "] " + nameof(authKey) + ": " + CryptoUtils.ToHexString(authKey));
            Logger.Trace("[" + nameof(EncryptKeyHmacForDevices) + "] " + nameof(iv) + ": " + CryptoUtils.ToHexString(iv));
            Logger.Trace("[" + nameof(EncryptKeyHmacForDevices) + "] " + nameof(hmacInput) + ": " + CryptoUtils.ToHexString(hmacInput));
            Logger.Trace("[" + nameof(EncryptKeyHmacForDevices) + "] " + nameof(hmacResult) + ": " + CryptoUtils.ToHexString(hmacResult));
            Logger.Trace("[" + nameof(EncryptKeyHmacForDevices) + "] " + nameof(hmacTruncated) + ": " + CryptoUtils.ToHexString(hmacTruncated));
            Logger.Trace("[" + nameof(EncryptKeyHmacForDevices) + "] " + nameof(session.state) + ": " + session.state);

            return(new OmemoAuthenticatedMessage(hmacTruncated, omemoMessageBytes));
        }