Exemplo n.º 1
0
        /// <summary>
        /// Encrypts the message and prepares everything for sending it.
        /// </summary>
        /// <param name="sid">The device ID of the sender.</param>
        /// <param name="senderIdentityKey">The identity key pair of the sender.</param>
        /// <param name="storage">An instance of the <see cref="IOmemoStorage"/> interface.</param>
        /// <param name="devices">A collection of <see cref="OmemoDeviceGroup"/>s the message should be encrypted for.</param>
        public void encrypt(uint sid, IdentityKeyPairModel senderIdentityKey, IOmemoStorage storage, List <OmemoDeviceGroup> devices)
        {
            try
            {
                SID = sid;
                if (IS_PURE_KEY_EXCHANGE_MESSAGE)
                {
                    // Encrypt 32 zero bytes as dummy data for devices:
                    DoubleRachet rachet = new DoubleRachet(senderIdentityKey);
                    keys = rachet.EncryptKeyHmacForDevices(new byte[32], devices).Select(x => new OmemoKeys(x.Item1, x.Item2.Select(x => new OmemoKey(x)).ToList())).ToList();
                }
                else
                {
                    XElement contentNode = generateEnvelope();
                    byte[]   contentData = Encoding.UTF8.GetBytes(contentNode.ToString());

                    // Encrypt message:
                    DoubleRachet           rachet    = new DoubleRachet(senderIdentityKey);
                    Tuple <byte[], byte[]> encrypted = rachet.EncryptMessasge(contentData);
                    BASE_64_PAYLOAD = Convert.ToBase64String(encrypted.Item1);

                    // Encrypt key || HMAC for devices:
                    keys = rachet.EncryptKeyHmacForDevices(encrypted.Item2, devices).Select(x => new OmemoKeys(x.Item1, x.Item2.Select(x => new OmemoKey(x)).ToList())).ToList();
                }

                // Store all sessions:
                foreach (OmemoDeviceGroup group in devices)
                {
                    foreach (KeyValuePair <uint, OmemoSessionModel> device in group.SESSIONS)
                    {
                        // Only store sessions in case encryption for this device was successful:
                        if (!(keys.Where(k => string.Equals(k.BARE_JID, group.BARE_JID)).FirstOrDefault()?.KEYS.Where(k => k.DEVICE_ID == device.Key).FirstOrDefault() is null))
                        {
                            storage.StoreSession(new OmemoProtocolAddress(group.BARE_JID, device.Key), device.Value);
                        }
                    }
                }

                ENCRYPTED = true;
            }
            catch (Exception e)
            {
                if (e is OmemoException)
                {
                    throw e;
                }
                throw new OmemoException("Failed to encrypt.", e);
            }
        }
Exemplo n.º 2
0
        public void Test_Omemo_Send_Receive_Send()
        {
            // Generate Alices keys:
            IdentityKeyPairModel aliceIdentKey     = KeyHelper.GenerateIdentityKeyPair();
            List <PreKeyModel>   alicePreKeys      = KeyHelper.GeneratePreKeys(0, 1);
            SignedPreKeyModel    aliceSignedPreKey = KeyHelper.GenerateSignedPreKey(0, aliceIdentKey.privKey);
            Bundle aliceBundle = new Bundle()
            {
                identityKey     = aliceIdentKey.pubKey,
                preKeys         = alicePreKeys.Select(key => new PreKeyModel(null, key.pubKey, key.keyId)).ToList(),
                preKeySignature = aliceSignedPreKey.signature,
                signedPreKey    = aliceSignedPreKey.preKey.pubKey,
                signedPreKeyId  = aliceSignedPreKey.preKey.keyId
            };
            InMemmoryOmemoStorage aliceStorage = new InMemmoryOmemoStorage();
            DoubleRachet          aliceRachet  = new DoubleRachet(aliceIdentKey);

            // Generate Bobs keys:
            IdentityKeyPairModel bobIdentKey     = KeyHelper.GenerateIdentityKeyPair();
            List <PreKeyModel>   bobPreKeys      = KeyHelper.GeneratePreKeys(0, 1);
            SignedPreKeyModel    bobSignedPreKey = KeyHelper.GenerateSignedPreKey(0, bobIdentKey.privKey);
            Bundle bobBundle = new Bundle()
            {
                identityKey     = bobIdentKey.pubKey,
                preKeys         = bobPreKeys.Select(key => new PreKeyModel(null, key.pubKey, key.keyId)).ToList(),
                preKeySignature = bobSignedPreKey.signature,
                signedPreKey    = bobSignedPreKey.preKey.pubKey,
                signedPreKeyId  = bobSignedPreKey.preKey.keyId
            };
            InMemmoryOmemoStorage bobStorage = new InMemmoryOmemoStorage();
            DoubleRachet          bobRachet  = new DoubleRachet(bobIdentKey);

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

            string deviceListMsg            = GetBobsDeviceListMsg();
            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.DEVICE_ID);

            // Alice builds a session to Bob:
            string bundleInfoMsg = GetBobsBundleInfoMsg(bobBundle);

            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.BUNDLE_INFO.deviceId == BOB_ADDRESS.DEVICE_ID);
            aliceStorage.StoreFingerprint(new OmemoFingerprint(bobBundle.identityKey, BOB_ADDRESS));

            // Encrypt Message 1:
            string msg1 = "Hello OMEMO";
            OmemoEncryptedMessage   omemoEncryptedMessage = new OmemoEncryptedMessage(ALICE_ADDRESS.BARE_JID, BOB_ADDRESS.BARE_JID, msg1, MessageMessage.TYPE_CHAT, false);
            List <OmemoDeviceGroup> bobDevices            = new List <OmemoDeviceGroup>();
            OmemoDeviceGroup        bobDeviceGroup        = new OmemoDeviceGroup(BOB_ADDRESS.BARE_JID);

            bobDeviceGroup.SESSIONS[BOB_ADDRESS.DEVICE_ID] = new OmemoSessionModel(bobBundle, 0, aliceIdentKey);
            bobDevices.Add(bobDeviceGroup);
            omemoEncryptedMessage.encrypt(ALICE_ADDRESS.DEVICE_ID, aliceIdentKey, aliceStorage, bobDevices);
            Assert.IsTrue(omemoEncryptedMessage.ENCRYPTED);
            Assert.IsNotNull(aliceStorage.LoadFingerprint(BOB_ADDRESS));
            Assert.IsNotNull(aliceStorage.LoadSession(BOB_ADDRESS));

            // Decrypt Message 1:
            // Throws an exception in case something goes wrong:
            OmemoDecryptionContext decryptCtx1 = new OmemoDecryptionContext(BOB_ADDRESS, bobIdentKey, bobSignedPreKey, bobPreKeys, false, bobStorage);

            omemoEncryptedMessage.decrypt(decryptCtx1);
            Assert.AreEqual(msg1, omemoEncryptedMessage.MESSAGE);
            Assert.IsFalse(omemoEncryptedMessage.IS_PURE_KEY_EXCHANGE_MESSAGE);
            Assert.IsFalse(omemoEncryptedMessage.ENCRYPTED);
            Assert.IsNotNull(bobStorage.LoadFingerprint(ALICE_ADDRESS));
            Assert.IsNotNull(bobStorage.LoadSession(ALICE_ADDRESS));

            // Encrypt Message 2:
            string msg2 = "Hello OMEMO 2";
            OmemoEncryptedMessage   omemoEncryptedMessage2 = new OmemoEncryptedMessage(BOB_ADDRESS.BARE_JID, ALICE_ADDRESS.BARE_JID, msg2, MessageMessage.TYPE_CHAT, false);
            List <OmemoDeviceGroup> aliceDevices           = new List <OmemoDeviceGroup>();
            OmemoDeviceGroup        aliceDeviceGroup       = new OmemoDeviceGroup(ALICE_ADDRESS.BARE_JID);

            aliceDeviceGroup.SESSIONS[ALICE_ADDRESS.DEVICE_ID] = bobStorage.LoadSession(ALICE_ADDRESS);
            aliceDevices.Add(aliceDeviceGroup);
            omemoEncryptedMessage2.encrypt(BOB_ADDRESS.DEVICE_ID, bobIdentKey, bobStorage, aliceDevices);
            Assert.IsTrue(omemoEncryptedMessage2.ENCRYPTED);

            // Decrypt Message 2:
            // Throws an exception in case something goes wrong:
            OmemoDecryptionContext decryptCtx2 = new OmemoDecryptionContext(ALICE_ADDRESS, aliceIdentKey, aliceSignedPreKey, alicePreKeys, false, aliceStorage);

            omemoEncryptedMessage2.decrypt(decryptCtx2);
            Assert.AreEqual(msg2, omemoEncryptedMessage2.MESSAGE);
            Assert.IsFalse(omemoEncryptedMessage2.IS_PURE_KEY_EXCHANGE_MESSAGE);
            Assert.IsFalse(omemoEncryptedMessage2.ENCRYPTED);

            // Encrypt Message 3:
            string msg3 = "Hello OMEMO 3";
            OmemoEncryptedMessage omemoEncryptedMessage3 = new OmemoEncryptedMessage(ALICE_ADDRESS.BARE_JID, BOB_ADDRESS.BARE_JID, msg3, MessageMessage.TYPE_CHAT, false);

            bobDeviceGroup.SESSIONS[BOB_ADDRESS.DEVICE_ID] = aliceStorage.LoadSession(BOB_ADDRESS);
            omemoEncryptedMessage3.encrypt(ALICE_ADDRESS.DEVICE_ID, aliceIdentKey, aliceStorage, bobDevices);
            Assert.IsFalse(omemoEncryptedMessage3.IS_PURE_KEY_EXCHANGE_MESSAGE);
            Assert.IsTrue(omemoEncryptedMessage3.ENCRYPTED);
            Assert.IsNotNull(aliceStorage.LoadFingerprint(BOB_ADDRESS));
            Assert.IsNotNull(aliceStorage.LoadSession(BOB_ADDRESS));

            // Decrypt Message 3:
            // Throws an exception in case something goes wrong:
            OmemoDecryptionContext decryptCtx3 = new OmemoDecryptionContext(BOB_ADDRESS, bobIdentKey, bobSignedPreKey, bobPreKeys, false, bobStorage);

            omemoEncryptedMessage3.decrypt(decryptCtx3);
            Assert.AreEqual(msg3, omemoEncryptedMessage3.MESSAGE);
            Assert.IsFalse(omemoEncryptedMessage3.IS_PURE_KEY_EXCHANGE_MESSAGE);
            Assert.IsFalse(omemoEncryptedMessage3.ENCRYPTED);
            Assert.IsNotNull(bobStorage.LoadFingerprint(ALICE_ADDRESS));
            Assert.IsNotNull(bobStorage.LoadSession(ALICE_ADDRESS));
        }