コード例 #1
0
        private async Task buildSessionForDevicesAsync(Dictionary <uint, SessionCipher> sessions, IList <SignalProtocolAddress> devices)
        {
            if (devices.Count <= 0)
            {
                return;
            }
            SignalProtocolAddress device = devices[0];

            devices.RemoveAt(0);

            // Check if there exists already a session for this device:
            if (OMEMO_HELPER.OMEMO_STORE.ContainsSession(device))
            {
                // If yes, the load it:
                SessionCipher cipher = OMEMO_HELPER.loadCipher(device);
                sessions.Add(device.getDeviceId(), cipher);

                Logger.Info("[OmemoSessionBuildHelper] Session for " + device.ToString() + " loaded from cache.");
            }
            else
            {
                // Else try to build a new one by requesting the devices bundle information:
                OmemoBundleInformationResultMessage bundleMsg = await requestBundleInformationAsync(device);

                if (!(bundleMsg is null))
                {
                    SignalProtocolAddress address = OMEMO_HELPER.newSession(CHAT_JID, bundleMsg);
                    SessionCipher         cipher  = OMEMO_HELPER.loadCipher(address);
                    sessions.Add(device.getDeviceId(), cipher);

                    Logger.Info("[OmemoSessionBuildHelper] Session with " + device.ToString() + " established.");
                }
コード例 #2
0
        private void createSessionForNextDevice()
        {
            if ((toDoDevicesRemote == null || toDoDevicesRemote.Count <= 0) && (toDoDevicesOwn == null || toDoDevicesOwn.Count <= 0))
            {
                // All sessions created:
                if (SESSION.DEVICE_SESSIONS.Count <= 0)
                {
                    setState(OmemoSessionBuildHelperState.ERROR);
                    ON_SESSION_RESULT(this, new OmemoSessionBuildResult(OmemoSessionBuildError.TARGET_DOES_NOT_SUPPORT_OMEMO));
                }
                else
                {
                    setState(OmemoSessionBuildHelperState.ESTABLISHED);
                    ON_SESSION_RESULT(this, new OmemoSessionBuildResult(SESSION));
                }
            }
            else
            {
                if (toDoDevicesRemote == null || toDoDevicesRemote.Count <= 0)
                {
                    curAddress = new SignalProtocolAddress(BARE_ACCOUNT_JID, toDoDevicesOwn[0]);
                    toDoDevicesOwn.RemoveAt(0);
                }
                else
                {
                    curAddress = new SignalProtocolAddress(CHAT_JID, toDoDevicesRemote[0]);
                    toDoDevicesRemote.RemoveAt(0);
                }

                if (OMEMO_HELPER.containsSession(curAddress))
                {
                    SessionCipher cipher = OMEMO_HELPER.loadCipher(curAddress);
                    SESSION.DEVICE_SESSIONS.Add(curAddress.getDeviceId(), cipher);
                    createSessionForNextDevice();
                }
                else
                {
                    requestBundleInformation();
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Decrypts the content of BASE_64_PAYLOAD. Loads the SessionCipher from the given OmemoHelper object and saves the result in MESSAGE.
        /// Sets ENCRYPTED to false.
        /// </summary>
        /// <param name="helper">The current OmemoHelper object of the current account.</param>
        /// <param name="localeDeciceId">The local device id.</param>
        /// <returns>True on success.</returns>
        public async Task <bool> decryptAsync(OmemoHelper helper, uint localeDeciceId)
        {
            SignalProtocolAddress remoteAddress = new SignalProtocolAddress(Utils.getBareJidFromFullJid(FROM), SOURCE_DEVICE_ID);

            return(await decryptAsync(helper.loadCipher(remoteAddress), remoteAddress, localeDeciceId, helper));
        }
コード例 #4
0
        private async Task buildSessionForDevicesAsync(Dictionary <uint, SessionCipher> sessions, IList <SignalProtocolAddress> devices)
        {
            if (devices.Count <= 0)
            {
                return;
            }
            SignalProtocolAddress device = devices[0];

            devices.RemoveAt(0);

            // Validate the device fingerprint:
            OmemoFingerprint fingerprint = OMEMO_HELPER.OMEMO_STORE.LoadFingerprint(device);

            if (!(fingerprint is null) && !OMEMO_HELPER.OMEMO_STORE.IsFingerprintTrusted(fingerprint))
            {
                Logger.Warn("[OmemoSessionBuildHelper] Not building a session with " + device.ToString() + " - key not trusted.");
                await buildSessionForDevicesAsync(sessions, devices);

                return;
            }

            // Check if there exists already a session for this device:
            if (OMEMO_HELPER.OMEMO_STORE.ContainsSession(device))
            {
                // If yes, the load it:
                SessionCipher cipher = OMEMO_HELPER.loadCipher(device);
                sessions.Add(device.getDeviceId(), cipher);

                Logger.Info("[OmemoSessionBuildHelper] Session for " + device.ToString() + " loaded from cache.");
            }
            else
            {
                // Else try to build a new one by requesting the devices bundle information:
                OmemoBundleInformationResultMessage bundleMsg = await requestBundleInformationAsync(device);

                if (!(bundleMsg is null))
                {
                    OMEMO_HELPER.newSession(device.getName(), bundleMsg);

                    // Validate fingerprints:
                    if (fingerprint is null)
                    {
                        fingerprint = new OmemoFingerprint(bundleMsg.BUNDLE_INFO.PUBLIC_IDENTITY_KEY, device);
                        OMEMO_HELPER.OMEMO_STORE.StoreFingerprint(fingerprint);
                    }
                    else
                    {
                        OmemoFingerprint receivedFingerprint = new OmemoFingerprint(bundleMsg.BUNDLE_INFO.PUBLIC_IDENTITY_KEY, device);
                        // Make sure the fingerprint did not change or somebody is doing an attack:
                        if (!fingerprint.checkIdentityKey(receivedFingerprint.IDENTITY_PUB_KEY))
                        {
                            Logger.Warn("[OmemoSessionBuildHelper] Unable to establish session with " + device.ToString() + " - other fingerprint received than stored locally.");
                            await buildSessionForDevicesAsync(sessions, devices);

                            return;
                        }
                    }

                    // Check if the fingerprint is trusted:
                    if (OMEMO_HELPER.OMEMO_STORE.IsFingerprintTrusted(fingerprint))
                    {
                        SessionCipher cipher = OMEMO_HELPER.loadCipher(device);
                        sessions.Add(device.getDeviceId(), cipher);

                        Logger.Info("[OmemoSessionBuildHelper] Session with " + device.ToString() + " established.");
                    }
                    else
                    {
                        Logger.Warn("[OmemoSessionBuildHelper] Unable to establish session with " + device.ToString() + " - key not trusted.");
                    }
                }
コード例 #5
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>
        public bool decrypt(OmemoHelper omemoHelper, uint localOmemoDeviceId)
        {
            try
            {
                // 1. Check if the message contains a key for the local device:
                OmemoKey key = getOmemoKey(localOmemoDeviceId);
                if (key == 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);
                SessionCipher         cipher  = omemoHelper.loadCipher(address);
                byte[] encryptedKeyAuthTag    = Convert.FromBase64String(key.BASE_64_KEY);
                byte[] decryptedKeyAuthTag    = null;
                if (key.IS_PRE_KEY)
                {
                    decryptedKeyAuthTag = cipher.decrypt(new PreKeySignalMessage(encryptedKeyAuthTag));
                    // 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:
                if (decryptedKeyAuthTag == 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);
                Aes128Gcm aes = new Aes128Gcm()
                {
                    key     = aesKey,
                    authTag = aesAuthTag,
                    iv      = aesIv
                };

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

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

                ENCRYPTED = false;
                return(true);
            }
            catch (Exception e)
            {
                Logger.Info("Discarded received OMEMO message - failed to decrypt with:" + e.Message);
            }
            return(false);
        }