import 'dart:convert'; import 'package:omemo_dart/omemo_dart.dart'; /// This example aims to demonstrate how omemo_dart is used. Since omemo_dart is not /// dependent on any XMPP library, you need to convert stanzas to the appropriate /// intermediary format and back. void main() async { const aliceJid = 'alice@some.server'; const bobJid = 'bob@other.serve'; // You are Alice and want to begin using OMEMO, so you first create an OmemoManager. final aliceManager = OmemoManager( // Generate Alice's OMEMO device bundle. We can specify how many One-time Prekeys we want, but // per default, omemo_dart generates 100 (recommended by XEP-0384). await OmemoDevice.generateNewDevice(aliceJid), // The trust manager we want to use. In this case, we use the provided one that // implements "Blind Trust Before Verification". To make things simpler, we keep // no persistent data and can thus use the MemoryBTBVTrustManager. If we wanted to keep // the state, we would have to override BlindTrustBeforeVerificationTrustManager. MemoryBTBVTrustManager(), // This function is called whenever we need to send an OMEMO heartbeat to [recipient]. // [result] is the encryted data to include. This needs to be wired into your XMPP library's // OMEMO implementation. // For simplicity, we use an empty function and imagine it works. (result, recipient) async => {}, // This function is called whenever we need to fetch the device list for [jid]. // This needs to be wired into your XMPP library's OMEMO implementation. // For simplicity, we use an empty function and imagine it works. (jid) async => [], // This function is called whenever we need to fetch the device bundle with id [id] from [jid]. // This needs to be wired into your XMPP library's OMEMO implementation. // For simplicity, we use an empty function and imagine it works. (jid, id) async => null, // This function is called whenever we need to subscribe to [jid]'s device list PubSub node. // This needs to be wired into your XMPP library's OMEMO implementation. // For simplicity, we use an empty function and imagine it works. (jid) async {}, // This function is called whenever our own device bundle has to be republished to our PEP node. // This needs to be wired into your XMPP library's OMEMO implementation. // For simplicity, we use an empty function and imagine it works. (device) async {}, ); // Alice now wants to chat with Bob at his bare Jid "bob@other.server". To make things // simple, we just generate the identity bundle ourselves. In the real world, we would // request it using PEP and then convert the device bundle into a OmemoBundle object. final bobManager = OmemoManager( await OmemoDevice.generateNewDevice(bobJid), BlindTrustBeforeVerificationTrustManager(), (result, recipient) async => {}, (jid) async => [], (jid, id) async => null, (jid) async {}, ); // Alice prepares to send the message to Bob, so she builds the message stanza and // collects all the children of the stanza that should be encrypted into a string. const aliceMessageStanzaBody = ''' Hello Bob, it's me, Alice! '''; // Since OMEMO 0.8.3 mandates usage of XEP-0420: Stanza Content Encryption, we have to // wrap our acual payload - aliceMessageStanzaBody - into an SCE envelope. Note that // the rpad element must contain a random string. See XEP-0420 for recommendations. // OMEMO makes the