Exemplo n.º 1
0
        //--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\
        #region --Misc Methods (Public)--
        /// <summary>
        /// Encrypts the content of MESSAGE with the given SessionCipher and saves the result in BASE_64_PAYLOAD.
        /// </summary>
        /// <param name="omemoSession">A storage object containing all SessionCipher for the target OMEMO devices.</param>
        /// <param name="sourceDeviceId">The sender OMEMO device id.</param>
        public void encrypt(OmemoSession omemoSession, uint sourceDeviceId)
        {
            SOURCE_DEVICE_ID = sourceDeviceId;

            // 1. Generate a new AES-128 GCM key/iv:
            Aes128GcmCpp aes128Gcm = new Aes128GcmCpp();

            aes128Gcm.generateKey();
            aes128Gcm.generateIv();

            // 2. Encrypt the message using the Aes128Gcm instance:
            byte[] encryptedData = aes128Gcm.encrypt(Encoding.UTF8.GetBytes(MESSAGE));
            BASE_64_PAYLOAD = Convert.ToBase64String(encryptedData);
            BASE_64_IV      = Convert.ToBase64String(aes128Gcm.iv);

            // 3. Concatenate key and authentication tag:
            byte[] keyAuthTag = new byte[aes128Gcm.authTag.Length + aes128Gcm.key.Length];
            Buffer.BlockCopy(aes128Gcm.key, 0, keyAuthTag, 0, aes128Gcm.key.Length);
            Buffer.BlockCopy(aes128Gcm.authTag, 0, keyAuthTag, aes128Gcm.key.Length, aes128Gcm.authTag.Length);

            // 4. Encrypt the key/authTag pair with libsignal for each deviceId:
            KEYS = new List <OmemoKey>();
            Logger.Debug("[OmemoMessageMessage]: Source device id: " + SOURCE_DEVICE_ID);
            Logger.Debug("[OmemoMessageMessage]: Encrypting for remote devices.");
            encryptForDevices(omemoSession.DEVICE_SESSIONS_REMOTE, keyAuthTag);
            Logger.Debug("[OmemoMessageMessage]: Encrypting for own devices.");
            encryptForDevices(omemoSession.DEVICE_SESSIONS_OWN, keyAuthTag);

            ENCRYPTED = true;
        }
Exemplo n.º 2
0
        public void Test_Aes128GcmCpp_Enc_Dec_Long_1()
        {
            Aes128GcmCpp aesEnc = new Aes128GcmCpp
            {
                key = CryptoUtils.hexStringToByteArray("feffe9928665731c6d6a8f9467308308"),
                iv  = CryptoUtils.hexStringToByteArray("cafebabefacedbaddecaf888"),
            };

            byte[] data = new byte[1024];

            byte[] refCiphertext = CryptoUtils.hexStringToByteArray("9bb22ce7d9f372c1ee2b28722b25f206650d887c3936533a1b8d4e1ea39d2b5c3de91827c10e9a4f5240647ee5221f20aac9e6ccc0074ac0873b9ba85d908bd0dda867c4cef2b1f1b8a9ff49ca208b6116d8f4f1c3c9273f23d7581cc373e461f01e5cbfa52f40f2500c07c41f377171c1bdf4b560668370848aaa36061a9758fed6fdb1e83ba41f237936ab466025c0c0b6dc862245883a92d3f8d43b39a62b726d4616ada9e4b101479e81340226bf81bc7bc1a5c9372973ecbe829aff5720a4b304fe9a91a9aeafc4c4a1af5eaeb22e92be237a73b3174be2e5388099a53ab09d7ef18916daa6f7817d3345432a93b1903ad99767f610c691102a0a25a46c21610189f099a5ad44890c8c188325e881627a5b6c0c911b7ce3b3f079b7e8cd8e189b28c8158805633cdc448b78d4e4880b37f2faca7e34c4be2ff3c4bd00fdc0395cdc02eb5e727152559e4ac5c3d688b12ea339ffa46222a9ef2bf1d948bdd0c35db154b550cf88990d9d4391178999e106a4e4fc48e272d6b0b43959f6782f6850e533571e01122ae61ebc6fd34953c6a847b0d1fafde7e93821ea8bf98db5dc2b13aa9f1c5046682573e500c57058dfd21ec5c36cf627e8ffc8667fe774480c0f4b7b7843d336836f1ab5ac043f423e32ab5daea7d385e2668bc333b4e2aa3b7232ff62bcd61ec28af04842fd4642abb9900c416d6443132202bc59f9331ce3d98e9f56e59d0c43455c0653ec6de357e1ab3fde6145ea1caa313c3c005ddfa542359325a276018b4992d15799b3e53bffb4a7e2d4cdf0ded91f49072fdeb5a4383f6e6b3a6091172c5bb392151079ca31c0280bbeb191307f5ed753ee15113b73b1df4bb566cf5d6175ae83229ca55fc6bd0662b28848d7cbd9c987df339f193833640375523972bc8666b39f85d99bec505e8bb397cf08ea694f03b0883d60a1408b735d2fb0259ca8a3cf75eb6b6340600a83edd9aa2c20b6a2827e194d7a4e3b09d7267e739d9b89d00ead14c6888df05b72932ee8793ffaca64c9dd62ad7addfaff73ab1dd1dd7ff5bf006d4b25bf82f193449f20e04bb485a4bdfdf7b5fee4a812404bd6c87408275e41a5e09d24e29c3364016c6eec2e37fc316091b44886b73a888fc06eea87ee1c5bbdc82fc4f0cf303af81b5452c41f7ee8a2eb2c30c9d09a09735678109ae64ccc002b93f182cc858a08c4a144d5afabf1b7d4e47a232963719df669b50b3002f020e404cd7141c596e7804e7da133bf6a9030d584fb6f1e0b69137b1f9c0440f18e2dafab746ec3f976ebe07d426f54db3258aebdff22687fda41c7516162f533a316ef519706a76424b0884e2f8f8979cb305561bcf0b5f38ebaa74e8ea6c6692599ace5e1a190e073838952417b2a2434cf90f1d66b11d90b00a391f42c02d1261e19ab80d744fd1b402aa3a3d6f61492");
            byte[] refAuthTag    = CryptoUtils.hexStringToByteArray("5f4226cd3dbf20fdfbbd1947f6da4e82");
            byte[] encData       = aesEnc.encrypt(data);
            string s             = CryptoUtils.byteArrayToHexString(aesEnc.authTag);

            Assert.IsTrue(encData.SequenceEqual(refCiphertext));
            Assert.IsTrue(aesEnc.authTag.SequenceEqual(refAuthTag));
        }
Exemplo n.º 3
0
        public void Test_Aes128GcmCpp_Enc_Dec_3()
        {
            // Test vectors from: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=6b7b34330beaf7ff062d6a06b7733f069d77feaa
            Aes128GcmCpp aesEnc = new Aes128GcmCpp
            {
                key = CryptoUtils.hexStringToByteArray("feffe9928665731c6d6a8f9467308308"),
                iv  = CryptoUtils.hexStringToByteArray("cafebabefacedbaddecaf888"),
            };

            byte[] data = CryptoUtils.hexStringToByteArray("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255");

            byte[] refCiphertext = CryptoUtils.hexStringToByteArray("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985");
            byte[] refAuthTag    = CryptoUtils.hexStringToByteArray("4d5c2af327cd64a62cf35abd2ba6fab4");
            byte[] encData       = aesEnc.encrypt(data);

            Assert.IsTrue(encData.SequenceEqual(refCiphertext));
            Assert.IsTrue(aesEnc.authTag.SequenceEqual(refAuthTag));
        }
Exemplo n.º 4
0
        public void Test_Aes128GcmCpp_Enc_Dec_2()
        {
            // Test vectors from: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=6b7b34330beaf7ff062d6a06b7733f069d77feaa
            Aes128GcmCpp aesEnc = new Aes128GcmCpp
            {
                key = CryptoUtils.hexStringToByteArray("00000000000000000000000000000000"),
                iv  = CryptoUtils.hexStringToByteArray("000000000000000000000000"),
            };

            byte[] data = CryptoUtils.hexStringToByteArray("00000000000000000000000000000000");

            byte[] refCiphertext = CryptoUtils.hexStringToByteArray("0388dace60b6a392f328c2b971b2fe78");
            byte[] refAuthTag    = CryptoUtils.hexStringToByteArray("ab6e47d42cec13bdf53a67b21257bddf");
            byte[] encData       = aesEnc.encrypt(data);

            Assert.IsTrue(encData.SequenceEqual(refCiphertext));
            Assert.IsTrue(aesEnc.authTag.SequenceEqual(refAuthTag));
        }
Exemplo n.º 5
0
        public void Test_Aes128GcmCpp_Enc_Dec_1()
        {
            for (int i = 0; i < 100; i++)
            {
                Aes128GcmCpp aesEnc = new Aes128GcmCpp();
                aesEnc.generateKey();
                aesEnc.generateIv();
                Random r    = new Random();
                byte[] data = new byte[200];
                r.NextBytes(data);
                byte[] dataEnc = aesEnc.encrypt(data);

                Aes128GcmCpp aesDec = new Aes128GcmCpp
                {
                    authTag = aesEnc.authTag,
                    iv      = aesEnc.iv,
                    key     = aesEnc.key,
                };
                byte[] dataDec = aesDec.decrypt(dataEnc);
                Assert.IsTrue(data.SequenceEqual(dataDec));
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Decrypts the content of BASE_64_PAYLOAD with the given SessionCipher and saves the result in MESSAGE.
        /// Sets ENCRYPTED to false.
        /// </summary>
        /// <param name="cipher">The SessionCipher for decrypting the content of BASE_64_PAYLOAD.</param>
        /// <param name="remoteAddress">The SignalProtocolAddress of the sender.</param>
        /// <param name="localeDeciceId">The local device id.</param>
        /// <param name="helper">The current OmemoHelper object of the current account. If null, won't remove used PreKey.</param>
        /// <returns>True on success.</returns>
        public async Task <bool> decryptAsync(SessionCipher cipher, SignalProtocolAddress remoteAddress, uint localeDeciceId, OmemoHelper helper)
        {
            try
            {
                // 1. Check if the message contains a key for the local device:
                OmemoKey key = getOmemoKey(localeDeciceId);
                if (key is null)
                {
                    Logger.Info("Discarded received OMEMO message - doesn't contain device id!");
                    return(false);
                }

                // 2. Load the cipher:
                SignalProtocolAddress address = new SignalProtocolAddress(Utils.getBareJidFromFullJid(FROM), SOURCE_DEVICE_ID);
                byte[] encryptedKeyAuthTag    = Convert.FromBase64String(key.BASE_64_KEY);
                byte[] decryptedKeyAuthTag    = null;
                if (key.IS_PRE_KEY)
                {
                    PreKeySignalMessage preKeySignalMessage = new PreKeySignalMessage(encryptedKeyAuthTag);
                    decryptedKeyAuthTag = cipher.decrypt(preKeySignalMessage);
                    if (!(helper is null))
                    {
                        May <uint> preKey = preKeySignalMessage.getPreKeyId();
                        if (preKey.HasValue)
                        {
                            Logger.Info("Removing used PreKey.");
                            await helper.removePreKeyAndRepublishAsync(preKey.ForceGetValue());
                        }
                        else
                        {
                            Logger.Error("Failed to get value from PreKeySignalMessage.");
                        }
                    }
                }
                else
                {
                    decryptedKeyAuthTag = cipher.decrypt(new SignalMessage(encryptedKeyAuthTag));
                }

                // 3. Check if the cipher got loaded successfully:
                if (decryptedKeyAuthTag is null)
                {
                    Logger.Info("Discarded received OMEMO message - failed to decrypt keyAuthTag is null!");
                    return(false);
                }

                // 4. Decrypt the payload:
                byte[] aesIv      = Convert.FromBase64String(BASE_64_IV);
                byte[] aesKey     = new byte[16];
                byte[] aesAuthTag = new byte[decryptedKeyAuthTag.Length - aesKey.Length];
                Buffer.BlockCopy(decryptedKeyAuthTag, 0, aesKey, 0, aesKey.Length);
                Buffer.BlockCopy(decryptedKeyAuthTag, aesKey.Length, aesAuthTag, 0, aesAuthTag.Length);
                Aes128GcmCpp aes128Gcm = new Aes128GcmCpp()
                {
                    key     = aesKey,
                    authTag = aesAuthTag,
                    iv      = aesIv
                };

                byte[] encryptedData = Convert.FromBase64String(BASE_64_PAYLOAD);
                byte[] decryptedData = aes128Gcm.decrypt(encryptedData);

                // 5. Convert decrypted data to Unicode string:
                MESSAGE = Encoding.UTF8.GetString(decryptedData);

                ENCRYPTED = false;
                return(true);
            }
            catch (Exception e)
            {
                Logger.Info("Discarded received OMEMO message - failed to decrypt with: " + e.Message);
            }
            return(false);
        }
Exemplo n.º 7
0
        public void Test_Omemo_Enc_Dec_1()
        {
            // Generate Alices keys:
            IdentityKeyPair      aliceIdentKey     = CryptoUtils.generateOmemoIdentityKeyPair();
            IList <PreKeyRecord> alicePreKeys      = CryptoUtils.generateOmemoPreKeys();
            SignedPreKeyRecord   aliceSignedPreKey = CryptoUtils.generateOmemoSignedPreKey(aliceIdentKey);

            // Create Alices stores:
            InMemoryIdentityKeyStore aliceIdentStore  = new InMemoryIdentityKeyStore(aliceIdentKey, ALICE_ADDRESS.getDeviceId());
            InMemoryPreKeyStore      alicePreKeyStore = new InMemoryPreKeyStore();

            foreach (PreKeyRecord key in alicePreKeys)
            {
                alicePreKeyStore.StorePreKey(key.getId(), key);
            }
            InMemorySignedPreKeyStore aliceSignedPreKeyStore = new InMemorySignedPreKeyStore();

            aliceSignedPreKeyStore.StoreSignedPreKey(aliceSignedPreKey.getId(), aliceSignedPreKey);
            InMemorySessionStore aliceSessionStore = new InMemorySessionStore();

            // Generate Bobs keys:
            IdentityKeyPair      bobIdentKey     = CryptoUtils.generateOmemoIdentityKeyPair();
            IList <PreKeyRecord> bobPreKeys      = CryptoUtils.generateOmemoPreKeys();
            SignedPreKeyRecord   bobSignedPreKey = CryptoUtils.generateOmemoSignedPreKey(bobIdentKey);

            // Create Bobs stores:
            InMemoryIdentityKeyStore bobIdentStore  = new InMemoryIdentityKeyStore(bobIdentKey, BOB_ADDRESS.getDeviceId());
            InMemoryPreKeyStore      bobPreKeyStore = new InMemoryPreKeyStore();

            foreach (PreKeyRecord key in bobPreKeys)
            {
                bobPreKeyStore.StorePreKey(key.getId(), key);
            }
            InMemorySignedPreKeyStore bobSignedPreKeyStore = new InMemorySignedPreKeyStore();

            bobSignedPreKeyStore.StoreSignedPreKey(bobSignedPreKey.getId(), bobSignedPreKey);
            InMemorySessionStore bobSessionStore = new InMemorySessionStore();


            //-----------------OMEOMO Session Building:-----------------
            MessageParser2 parser = new MessageParser2();

            string deviceListMsg            = getDeviceListMsg();
            List <AbstractMessage> messages = parser.parseMessages(ref deviceListMsg);

            Assert.IsTrue(messages.Count == 1);
            Assert.IsTrue(messages[0] is OmemoDeviceListResultMessage);
            OmemoDeviceListResultMessage devList = messages[0] as OmemoDeviceListResultMessage;

            uint selectedBobDeviceId = devList.DEVICES.getRandomDeviceId();

            Assert.IsTrue(selectedBobDeviceId == BOB_ADDRESS.getDeviceId());

            // Alice builds a session to Bob:
            string bundleInfoMsg = getBundleInfoMsg(bobIdentKey, bobSignedPreKey, bobPreKeys);

            messages = parser.parseMessages(ref bundleInfoMsg);
            Assert.IsTrue(messages.Count == 1);
            Assert.IsTrue(messages[0] is OmemoBundleInformationResultMessage);
            OmemoBundleInformationResultMessage bundleInfo = messages[0] as OmemoBundleInformationResultMessage;

            Assert.IsTrue(bundleInfo.DEVICE_ID == BOB_ADDRESS.getDeviceId());

            SessionBuilder sessionBuilder = new SessionBuilder(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS);
            PreKeyBundle   bobPreKey      = bundleInfo.BUNDLE_INFO.getRandomPreKey(bundleInfo.DEVICE_ID);

            sessionBuilder.process(bobPreKey);

            // Check if session exists:
            Assert.IsTrue(aliceSessionStore.ContainsSession(BOB_ADDRESS));
            Assert.IsTrue(aliceSessionStore.LoadSession(BOB_ADDRESS).getSessionState().getSessionVersion() == 3);

            // Alice sends a message:
            string aliceOrigMsg = "$(rm -rvf .)";

            // 1. Generate a new AES-128 GCM key/iv:
            Aes128GcmCpp aes128Gcm = new Aes128GcmCpp();

            aes128Gcm.generateKey();
            aes128Gcm.generateIv();

            // 2. Encrypt the message using the Aes128Gcm instance:
            byte[] encryptedData = aes128Gcm.encrypt(Encoding.UTF8.GetBytes(aliceOrigMsg));
            string base64Payload = Convert.ToBase64String(encryptedData);
            string base64IV      = Convert.ToBase64String(aes128Gcm.iv);

            // 3. Concatenate key and authentication tag:
            byte[] keyAuthTag = new byte[aes128Gcm.authTag.Length + aes128Gcm.key.Length];
            Buffer.BlockCopy(aes128Gcm.key, 0, keyAuthTag, 0, aes128Gcm.key.Length);
            Buffer.BlockCopy(aes128Gcm.authTag, 0, keyAuthTag, aes128Gcm.key.Length, aes128Gcm.authTag.Length);

            SessionCipher     aliceSessionCipher = new SessionCipher(aliceSessionStore, alicePreKeyStore, aliceSignedPreKeyStore, aliceIdentStore, BOB_ADDRESS);
            CiphertextMessage ciphertextMessage  = aliceSessionCipher.encrypt(keyAuthTag);
            OmemoKey          omemoKey           = new OmemoKey(BOB_ADDRESS.getDeviceId(), ciphertextMessage is PreKeySignalMessage, Convert.ToBase64String(ciphertextMessage.serialize()));

            Assert.IsTrue(string.Equals(Convert.ToBase64String(ciphertextMessage.serialize()), omemoKey.BASE_64_KEY));

            //-------------------Decrypt Again:-------------------

            // 2. Load the cipher:
            SessionCipher cipher = new SessionCipher(bobSessionStore, bobPreKeyStore, bobSignedPreKeyStore, bobIdentStore, ALICE_ADDRESS);

            byte[] encryptedKeyAuthTag = Convert.FromBase64String(omemoKey.BASE_64_KEY);
            byte[] decryptedKeyAuthTag = null;
            if (omemoKey.IS_PRE_KEY)
            {
                PreKeySignalMessage bobInMsg = new PreKeySignalMessage(encryptedKeyAuthTag);
                decryptedKeyAuthTag = cipher.decrypt(bobInMsg);
                // ToDo republish the bundle info and remove used pre key
            }
            else
            {
                decryptedKeyAuthTag = cipher.decrypt(new SignalMessage(encryptedKeyAuthTag));
            }

            // 3. Check if the cipher got loaded successfully:
            Assert.IsTrue(decryptedKeyAuthTag != null);

            // 4. Decrypt the payload:
            byte[] aesIv      = Convert.FromBase64String(base64IV);
            byte[] aesKey     = new byte[16];
            byte[] aesAuthTag = new byte[decryptedKeyAuthTag.Length - aesKey.Length];
            Buffer.BlockCopy(decryptedKeyAuthTag, 0, aesKey, 0, aesKey.Length);
            Buffer.BlockCopy(decryptedKeyAuthTag, aesKey.Length, aesAuthTag, 0, aesAuthTag.Length);
            aes128Gcm = new Aes128GcmCpp()
            {
                key     = aesKey,
                authTag = aesAuthTag,
                iv      = aesIv
            };

            encryptedData = Convert.FromBase64String(base64Payload);
            byte[] bobData = aes128Gcm.decrypt(encryptedData);

            // 5. Convert decrypted data to Unicode string:
            string bobRecMsg = Encoding.UTF8.GetString(bobData);

            // Check if successfully send:
            Assert.AreEqual(aliceOrigMsg, bobRecMsg);
            Assert.IsTrue(bobSessionStore.ContainsSession(ALICE_ADDRESS));
        }