Exemple #1
0
        public async Task decryptOmemoEncryptedMessageAsync(OmemoEncryptedMessage msg, bool trustedKeysOnly)
        {
            XMPPAccount          account         = CONNECTION.account;
            OmemoProtocolAddress receiverAddress = new OmemoProtocolAddress(account.getBareJid(), account.omemoDeviceId);
            // Try to decrypt the message, in case no exception occurred, everything went fine:
            OmemoDecryptionContext decryptCtx = new OmemoDecryptionContext(receiverAddress, account.omemoIdentityKey, account.omemoSignedPreKey, account.OMEMO_PRE_KEYS, trustedKeysOnly, OMEMO_STORAGE);

            msg.decrypt(decryptCtx);
            Debug.Assert(!msg.ENCRYPTED);
            Logger.Debug("Successfully decrypted an " + nameof(OmemoEncryptedMessage) + " for '" + receiverAddress.BARE_JID + "'.");

            // Republish bundle information in case the message is a key exchange message and used a PreKey:
            if (decryptCtx.keyExchange)
            {
                Logger.Info("Received a OMEMO key exchange message. Republishing bundle for '" + receiverAddress.BARE_JID + "'...");
                PreKeyModel newPreKey = decryptCtx.STORAGE.ReplaceOmemoPreKey(decryptCtx.usedPreKey);
                account.OMEMO_PRE_KEYS.Remove(decryptCtx.usedPreKey);
                account.OMEMO_PRE_KEYS.Add(newPreKey);
                await announceBundleInfoAsync();

                Logger.Info("Bundle for '" + receiverAddress.BARE_JID + "' republished.");
            }

            // Reply with an empty message to confirm the successful key exchange:
            // TODO: This is no good way, since there it would be possible to stalk people without them knowing.
        }
Exemple #2
0
        /// <summary>
        /// Generates a new Ed25519 <see cref="SignedPreKeyModel"/> and returns it.
        /// </summary>
        /// <param name="id">The id of the <see cref="SignedPreKeyModel"/>.</param>
        /// <param name="identiyKey">The private part of an <see cref="IdentityKeyPairModel"/> used for signing.</param>
        public static SignedPreKeyModel GenerateSignedPreKey(uint id, ECPrivKeyModel identiyKey)
        {
            PreKeyModel preKey = GeneratePreKey(id);

            byte[] signature = Ed25519.Sign(preKey.pubKey.key, identiyKey.key);
            return(new SignedPreKeyModel(preKey, signature));
        }
Exemple #3
0
 /// <summary>
 /// Generates the signature of the given <paramref name="preKey"/> and returns it.
 /// </summary>
 /// <param name="preKey">The <see cref="PreKeyModel"/> that should be signed.</param>
 /// <param name="identiyKey">The private Key used for signing the given <paramref name="preKey"/>.</param>
 /// <returns>The signature of the given <paramref name="preKey"/>.</returns>
 public static byte[] SignPreKey(PreKeyModel preKey, ECPrivKeyModel identiyKey)
 {
     byte[] pubKey    = preKey.pubKey.ToByteArrayWithPrefix();
     byte[] signature = new byte[Ed25519.SignatureSize];
     Ed25519.Sign(identiyKey.key, 0, pubKey, 0, pubKey.Length, signature, 0);
     return(signature);
 }
Exemple #4
0
        public PreKeyModel ReplaceOmemoPreKey(PreKeyModel preKey)
        {
            using (MainDbContext ctx = new MainDbContext())
            {
                // Remove the old key:
                dbAccount.omemoInfo.preKeys.Remove(preKey);
                preKey.Remove(ctx, true);

                // Generate a new one:
                PreKeyModel newPreKey = KeyHelper.GeneratePreKey(dbAccount.omemoInfo.maxPreKeyId++);
                dbAccount.omemoInfo.preKeys.Add(newPreKey);
                dbAccount.omemoInfo.bundleInfoAnnounced = false;

                // Store everything in the DB:
                ctx.Add(newPreKey);
                ctx.Update(dbAccount.omemoInfo);
                return(newPreKey);
            }
        }
Exemple #5
0
        public async Task decryptOmemoEncryptedMessageAsync(OmemoEncryptedMessage msg, bool trustedKeysOnly)
        {
            XMPPAccount          account         = CONNECTION.account;
            OmemoProtocolAddress receiverAddress = new OmemoProtocolAddress(account.getBareJid(), account.omemoDeviceId);
            // Try to decrypt the message, in case no exception occurred, everything went fine:
            OmemoDecryptionContext decryptCtx = new OmemoDecryptionContext(receiverAddress, account.omemoIdentityKey, account.omemoSignedPreKey, account.OMEMO_PRE_KEYS, trustedKeysOnly, OMEMO_STORAGE);

            msg.decrypt(decryptCtx);
            Debug.Assert(!msg.ENCRYPTED);
            Logger.Debug("Successfully decrypted an " + nameof(OmemoEncryptedMessage) + " for '" + receiverAddress.BARE_JID + "'.");

            // Republish bundle information in case the message is a key exchange message and used a PreKey:
            if (decryptCtx.keyExchange)
            {
                Logger.Info("Received a OMEMO key exchange message. Republishing bundle for '" + receiverAddress.BARE_JID + "'...");
                PreKeyModel newPreKey = decryptCtx.STORAGE.ReplaceOmemoPreKey(decryptCtx.usedPreKey);
                account.OMEMO_PRE_KEYS.Remove(decryptCtx.usedPreKey);
                account.OMEMO_PRE_KEYS.Add(newPreKey);
                await announceBundleInfoAsync();

                Logger.Info("Bundle for '" + receiverAddress.BARE_JID + "' republished.");

                // Reply with an empty message to confirm the successful key exchange:
                // TODO: This is no good way, since there it would be possible to stalk people without them knowing.
                OmemoEncryptedMessage reply       = new OmemoEncryptedMessage(msg.getTo(), msg.getFrom(), null, msg.TYPE, false);
                OmemoDeviceGroup      deviceGroup = new OmemoDeviceGroup(decryptCtx.senderAddress.BARE_JID);
                deviceGroup.SESSIONS.Add(decryptCtx.senderAddress.DEVICE_ID, decryptCtx.session);
                try
                {
                    reply.encrypt(CONNECTION.account.omemoDeviceId, CONNECTION.account.omemoIdentityKey, OMEMO_STORAGE, new List <OmemoDeviceGroup> {
                        deviceGroup
                    });
                    await CONNECTION.SendAsync(reply);
                }
                catch (Exception e)
                {
                    Logger.Error("[OMEMO HELPER] Failed to encrypt and the empty OMEMO message reply with: ", e);
                }
                Logger.Info($"Send an empty OMEMO message to confirm the successful key exchange with '{msg.getFrom()}'.");
            }
        }
 public PreKeyModel ReplaceOmemoPreKey(PreKeyModel preKey)
 {
     // Not relevant for us
     return(preKey);
 }