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. }
/// <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)); }
/// <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); }
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); } }
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); }