Module: xep_0384

class slixmpp_omemo.xep_0384.XEP_0384(*args, **kwargs)[source]

Bases: BasePlugin

An implementation of XEP-0384: OMEMO Encryption.

Supports both the 0.3 version of the protocol (under the eu.siacs.conversations.axolotl namespace, also known as legacy OMEMO, oldmemo and siacs OMEMO) and the current 0.8 version (under the omemo:2 namespace, also known as newmemo, twomemo and OMEMO 2).

The plugin does not treat the protocol versions as separate encryption mechanisms, instead it manages all versions transparently with no manual intervention required.

Certain initialization tasks such as a data consistency check are transparently ran in the background when the plugin is loaded. The omemo_initialized event is fired when those initial background tasks are done. Waiting for this event can be useful e.g. in automated testing environments to be sure that a test client has generated and uploaded its OMEMO data before continuing.

Tip

A lot of essential functionality is accessible via the SessionManager instance that is returned by get_session_manager(). The session manager is the core of the underlying OMEMO library and offers functionality such as listing all devices known for an XMPP account, managing trust and settings your own device’s label. Refer to the library’s API Documentation for details.

Parameters:
name: str = 'xep_0384'

A short name for the plugin based on the implemented specification. For example, a plugin for XEP-0030 would use ‘xep_0030’.

description: str = 'OMEMO Encryption'

A longer name for the plugin, describing its purpose. For example, a plugin for XEP-0030 would use ‘Service Discovery’ as its description value.

dependencies: ClassVar[set[str]] = {'xep_0004', 'xep_0030', 'xep_0060', 'xep_0163', 'xep_0280', 'xep_0334'}

Some plugins may depend on others in order to function properly. Any plugin names included in dependencies will be initialized as needed if this plugin is enabled.

default_config: ClassVar[dict[str, Any]] = {'fallback_message': 'This message is OMEMO encrypted.'}

The basic, standard configuration for the plugin, which may be overridden when initializing the plugin. The configuration fields included here may be accessed directly as attributes of the plugin. For example, including the configuration field ‘foo’ would mean accessing plugin.foo returns the current value of plugin.config[‘foo’].

plugin_init()[source]

Initialize plugin state, such as registering event handlers.

Return type:

None

plugin_end()[source]

Cleanup plugin state, and prepare for plugin removal.

Return type:

None

session_bind(jid)[source]

Initialize plugin state based on the bound JID.

Return type:

None

Parameters:

jid (JID)

abstract property storage: Storage

Returns: The storage implementation to use to store OMEMO-related data.

property legacy_storage: LegacyStorage | None

This property can be overridden to have the plugin perform migration from a legacy storage backend (python-omemo versions older than v1.0.0) to the new storage backend returned by storage(). This migration is fully automatic and idempotent.

Returns:

A legacy storage backend implementation to migrate data from, otherwise None.

abstract property _btbv_enabled: bool

Returns: Whether BTBV is enabled.

async _devices_blindly_trusted(blindly_trusted, identifier)[source]

Get notified about newly blindly trusted devices. This method is called automatically by whenever at least one device was blindly trusted. You can use this method for example to notify the user about the automated change in trust.

Does nothing by default.

Parameters:
Return type:

None

abstractmethod async _prompt_manual_trust(manually_trusted, identifier)[source]

Prompt manual trust decision on a set of undecided identity keys. The trust decisions are expected to be persisted by calling set_trust().

Parameters:
  • manually_trusted (FrozenSet[DeviceInformation]) – A set of devices whose trust has to be manually decided by the user.

  • identifier (str | None) – A piece of application-specific information that callers can pass to encrypt_message(), which is then forwarded here unaltered. This can be used, for example, by instant messaging clients, to identify the chat tab which triggered the call to encrypt_message() and subsequently this call to _prompt_manual_trust().

Raises:

TrustDecisionFailed – if for any reason the trust decision failed/could not be completed. Feel free to raise a subclass instead.

Return type:

None

Note

This is called when the encryption needs to know whether it is allowed to encrypt for these devices or not. When this method returns, all previously undecided trust levels should have been replaced by calling set_trust() with a different trust level. If they are not replaced or still evaluate to the undecided trust level after the call, the encryption will fail with an exception. See encrypt() for details.

async get_session_manager()[source]

Access the session manager, which is the main interface to the underlying OMEMO library. A lot of useful functionality is available on the session manager, refer to the library’s API Documentation for details.

Return type:

SessionManager

Returns:

The session manager instance that is internally used by this plugin.

async _on_device_list_update(msg)[source]

Callback to handle PEP updates to the device list node of either OMEMO protocol version.

Parameters:

msg (Message) – The stanza containing the PEP update event.

Return type:

None

async _on_subscription_changed(presence)[source]

Callback to handle presence subscription changes.

Parameters:

presence (Presence) – The presence stanza triggering this callback.

Return type:

None

async _subscribe(namespace, jid)[source]

Manually subscribe to the device list pubsub node of the JID and track the subscription status.

Parameters:
  • namespace (str) – The OMEMO version namespace (not the node).

  • jid (JID) – The JID whose device list to manually subscribe to. Can be a bare (aka “userhost”) JID but doesn’t have to.

Return type:

None

async _unsubscribe(namespace, jid)[source]

Manually unsubscribe from the device list pubsub node of the JID and track the subscription status.

Parameters:
  • namespace (str) – The OMEMO version namespace (not the node).

  • jid (JID) – The JID whose device list to manually unsubscribe from. Can be a bare (aka “userhost”) JID but doesn’t have to.

Return type:

None

async refresh_device_lists(jids, force_download=False)[source]

Ensure that up-to-date device lists for the JIDs are cached. This is done automatically by encrypt_message(). You don’t have to ever manually call this method, but you can do so for optimization reasons. For example, in a UI-based IM application, this method can be called when an OMEMO-enabled chat tab/window is opened, to be optimally prepared if the user decides to send an encrypted message.

Parameters:
  • jids (Set[JID]) – The JIDs whose device lists to refresh. Can be bare (aka “userhost”) JIDs but don’t have to.

  • force_download (bool) – Force downloading the device list even if pubsub/PEP are enabled to automatically keep the cached device lists up-to-date.

Raises:

Exception – all exceptions raised by refresh_device_lists() are forwarded as-is.

Return type:

None

async encrypt_message(stanza, recipient_jids, identifier=None)[source]

Encrypt a message stanza. Selects the optimal OMEMO protocol version for each recipient device. Twomemo encrypts the whole stanza using SCE, oldmemo encrypts only the body.

Parameters:
  • stanza (Message) – The stanza to encrypt. Must be associated with an XML stream that has message ids enabled.

  • recipient_jids (JID | Set[JID]) – The JID of the recipients. Can be bare (aka “userhost”) JIDs but doesn’t have to. A single JID can be used.

  • identifier (str | None) – A value that is passed on to _devices_blindly_trusted() and _prompt_manual_trust() in case a trust decision is required for any of the recipient devices. This value is not processed or altered, it is simply passed through. Refer to the documentation of _devices_blindly_trusted() or _prompt_manual_trust() for details.

Return type:

Tuple[Message | None, FrozenSet[EncryptionError]]

Returns:

The encrypted version of the input message ready to be sent, and a set of non-critical errors encountered during encryption. The message can contain elements for multiple OMEMO versions, in case there is a mix of supported versions between the recipients. The store hint is enabled on the stanza and the message id is copied from the source message. It also contains a fallback body. If there is nothing to be sent, None is returned in place of an encrypted message. This can be the case if the input message does not contain a body and oldmemo is to be used with all recipients.

Warning

Encrypted message stanzas consist only of the bare minimum: the OMEMO element(s) and the store hint. For OMEMO versions that support SCE, other tags such as read markers are included in the encrypted OMEMO element. For older versions that do not use SCE, only the body is encrypted, which means that other elements such as read markers are lost and have to be copied over manually to be sent in plain if desired.

Warning

Messages without a body are not considered for oldmemo encryption.

Raises:

Exception – all exceptions raised by encrypt() are forwarded as-is.

Parameters:
Return type:

Tuple[Message | None, FrozenSet[EncryptionError]]

async decrypt_message(stanza)[source]

Decrypt an OMEMO-encrypted message. Use is_encrypted() to check whether a stanza contains an OMEMO-encrypted message. The original stanza is not modified by this method. For oldmemo, the optional fallback body is replaced with the decrypted content. For newmemo, the whole SCE stanza is returned.

Parameters:

stanza (Message) – The message stanza.

Return type:

Tuple[Message, DeviceInformation]

Returns:

The decrypted stanza and information about the sending device.

Raises:
  • ValueError – in case there is malformed data not caught be the XML schema validation.

  • ValueError – in case a groupchat message is passed but XEP-0045 is not loaded.

  • XMLSchemaValidationError – in case the element does not conform to the XML schema given in the specification.

  • SenderNotFound – in case the public information about the sending device could not be found or is incomplete.

  • Exception – all exceptions raised by decrypt() are forwarded as-is.

is_encrypted(stanza)[source]
Parameters:

stanza (Message) – The stanza.

Return type:

Set[str]

Returns:

The namespaces of the OMEMO versions this message is encrypted with. Empty if this message is not encrypted with any of the supported OMEMO versions.