Module: backend
- class omemo.backend.Backend(max_num_per_session_skipped_keys=1000, max_num_per_message_skipped_keys=None)[source]
Bases:
ABC
The base class for all backends. A backend is a unit providing the functionality of a certain OMEMO version to the core library.
Warning
Make sure to call
__init__()
from your subclass to configure per-message and per-session skipped message key DoS protection thresholds, and respect those thresholds when decrypting key material usingdecrypt_key_material()
.Note
Most methods can raise
StorageException
in addition to those exceptions listed explicitly.Note
All usages of “identity key” in the public API refer to the public part of the identity key pair in Ed25519 format. Otherwise, “identity key pair” is explicitly used to refer to the full key pair.
Note
For backend implementors: as part of your backend implementation, you are expected to subclass various abstract base classes like
Session
,Content
,PlainKeyMaterial
,EncryptedKeyMaterial
andKeyExchange
. Whenever any of these abstract base types appears in a method signature of theBackend
class, what’s actually meant is an instance of your respective subclass. This is not correctly expressed through the type system, since I couldn’t think of a clean way to do so. Adding generics for every single of these types seemed not worth the effort. For now, the recommended way to deal with this type inaccuray is to assert the types of the affected method parameters, for example:async def store_session(self, session: Session) -> Any: assert isinstance(session, MySessionImpl) ...
Doing so tells mypy how to deal with the situation. These assertions should never fail.
Note
For backend implementors: you can access the identity key pair at any time via
omemo.identity_key_pair.IdentityKeyPair.get()
.- Parameters
max_num_per_session_skipped_keys (int) –
max_num_per_message_skipped_keys (Optional[int]) –
- __init__(max_num_per_session_skipped_keys=1000, max_num_per_message_skipped_keys=None)[source]
- Parameters
max_num_per_session_skipped_keys (
int
) – The maximum number of skipped message keys to keep around per session. Once the maximum is reached, old message keys are deleted to make space for newer ones. Accessible viamax_num_per_session_skipped_keys
.max_num_per_message_skipped_keys (
Optional
[int
]) – The maximum number of skipped message keys to accept in a single message. When set toNone
(the default), this parameter defaults to the per-session maximum (i.e. the value of themax_num_per_session_skipped_keys
parameter). This parameter may only be 0 if the per-session maximum is 0, otherwise it must be a number between 1 and the per-session maximum. Accessible viamax_num_per_message_skipped_keys
.
- Return type
None
- property max_num_per_session_skipped_keys: int
Returns: The maximum number of skipped message keys to keep around per session.
- Return type
int
- property max_num_per_message_skipped_keys: int
Returns: The maximum number of skipped message keys to accept in a single message.
- Return type
int
- abstract property namespace: str
Returns: The namespace provided/handled by this backend implementation.
- Return type
str
- abstract async load_session(bare_jid, device_id)[source]
- Parameters
bare_jid (
str
) – The bare JID the device belongs to.device_id (
int
) – The id of the device.
- Return type
Optional
[Session
]- Returns
The session associated with the device, or None if such a session does not exist.
Warning
Multiple sessions for the same device can exist in memory, however only one session per device can exist in storage. Which one of the in-memory sessions is persisted in storage is controlled by calling the
store_session()
method.
- abstract async store_session(session)[source]
Store a session, overwriting any previously stored session for the bare JID and device id this session belongs to.
- Parameters
session (
Session
) – The session to store.- Return type
None
Warning
Multiple sessions for the same device can exist in memory, however only one session per device can exist in storage. Which one of the in-memory sessions is persisted in storage is controlled by calling this method.
- Return type
None
- Parameters
session (Session) –
- abstract async build_session_active(bare_jid, device_id, bundle, plain_key_material)[source]
Actively build a session.
- Parameters
bare_jid (
str
) – The bare JID the device belongs to.device_id (
int
) – The id of the device.bundle (
Bundle
) – The bundle containing the public key material of the other device required for active session building.plain_key_material (
PlainKeyMaterial
) – The key material to encrypt for the recipient as part of the initial key exchange/session initiation.
- Return type
Tuple
[Session
,EncryptedKeyMaterial
]- Returns
The newly built session, the encrypted key material and the key exchange information required by the other device to complete the passive part of session building. The
initiation
property of the returned session must returnACTIVE
. Thekey_exchange
property of the returned session must return the information required by the other party to complete its part of the key exchange.- Raises
KeyExchangeFailed – in case of failure related to the key exchange required for session building.
Warning
This method may be called for a device which already has a session. In that case, the original session must remain in storage and must remain loadable via
load_session()
. Only upon callingstore_session()
, the old session must be overwritten with the new one. In summary, multiple sessions for the same device can exist in memory, while only one session per device can exist in storage, which can be controlled using thestore_session()
method.
- abstract async build_session_passive(bare_jid, device_id, key_exchange, encrypted_key_material)[source]
Passively build a session.
- Parameters
bare_jid (
str
) – The bare JID the device belongs to.device_id (
int
) – The id of the device.key_exchange (
KeyExchange
) – Key exchange information for the passive session building.encrypted_key_material (
EncryptedKeyMaterial
) – The key material to decrypt as part of the initial key exchange/session initiation.
- Return type
Tuple
[Session
,PlainKeyMaterial
]- Returns
The newly built session and the decrypted key material. Note that the pre key used to initiate this session must somehow be associated with the session, such that
hide_pre_key()
anddelete_pre_key()
can work.- Raises
KeyExchangeFailed – in case of failure related to the key exchange required for session building.
DecryptionFailed – in case of backend-specific failures during decryption of the initial message.
Warning
This method may be called for a device which already has a session. In that case, the original session must remain in storage and must remain loadable via
load_session()
. Only upon callingstore_session()
, the old session must be overwritten with the new one. In summary, multiple sessions for the same device can exist in memory, while only one session per device can exist in storage, which can be controlled using thestore_session()
method.
- abstract async encrypt_plaintext(plaintext)[source]
Encrypt some plaintext symmetrically.
- Parameters
plaintext (
bytes
) – The plaintext to encrypt symmetrically.- Return type
Tuple
[Content
,PlainKeyMaterial
]- Returns
The encrypted plaintext aka content, as well as the key material needed to decrypt it.
- abstract async encrypt_empty()[source]
Encrypt an empty message for the sole purpose of session manangement/ratchet forwarding/key material transportation.
- Return type
Tuple
[Content
,PlainKeyMaterial
]- Returns
The symmetrically encrypted empty content, and the key material needed to decrypt it.
- abstract async encrypt_key_material(session, plain_key_material)[source]
Encrypt some key material asymmetrically using the session.
- Parameters
session (
Session
) – The session to encrypt the key material with.plain_key_material (
PlainKeyMaterial
) – The key material to encrypt asymmetrically for each recipient.
- Return type
- Returns
The encrypted key material.
- abstract async decrypt_plaintext(content, plain_key_material)[source]
Decrypt some symmetrically encrypted plaintext.
- Parameters
content (
Content
) – The content to decrypt. Not empty, i.e.Content.empty
will returnFalse
.plain_key_material (
PlainKeyMaterial
) – The key material to decrypt with.
- Return type
bytes
- Returns
The decrypted plaintext.
- Raises
DecryptionFailed – in case of backend-specific failures during decryption.
- abstract async decrypt_key_material(session, encrypted_key_material)[source]
Decrypt some key material asymmetrically using the session.
- Parameters
session (
Session
) – The session to decrypt the key material with.encrypted_key_material (
EncryptedKeyMaterial
) – The encrypted key material.
- Return type
- Returns
The decrypted key material
- Raises
TooManySkippedMessageKeys – if the number of message keys skipped by this message exceeds the upper limit enforced by
max_num_per_message_skipped_keys
.DecryptionFailed – in case of backend-specific failures during decryption.
Warning
Make sure to respect the values of
max_num_per_session_skipped_keys
andmax_num_per_message_skipped_keys
.Note
When the maximum number of skipped message keys for this session, given by
max_num_per_session_skipped_keys
, is exceeded, old skipped message keys are deleted to make space for new ones.
- abstract async signed_pre_key_age()[source]
- Return type
int
- Returns
The age of the signed pre key, i.e. the time elapsed since it was last rotated, in seconds.
- abstract async rotate_signed_pre_key()[source]
Rotate the signed pre key. Keep the old signed pre key around for one additional rotation period, i.e. until this method is called again.
- Return type
None
- abstract async hide_pre_key(session)[source]
Hide a pre key from the bundle returned by
get_bundle()
and pre key count returned byget_num_visible_pre_keys()
, but keep the pre key for cryptographic operations.- Parameters
session (
Session
) – A session that was passively built usingbuild_session_passive()
. Use this session to identity the pre key to hide.- Return type
bool
- Returns
Whether the pre key was hidden. If the pre key doesn’t exist (e.g. because it has already been deleted), or was already hidden, do not throw an exception, but return False instead.
- abstract async delete_pre_key(session)[source]
Delete a pre key.
- Parameters
session (
Session
) – A session that was passively built usingbuild_session_passive()
. Use this session to identity the pre key to delete.- Return type
bool
- Returns
Whether the pre key was deleted. If the pre key doesn’t exist (e.g. because it has already been deleted), do not throw an exception, but return False instead.
Delete all pre keys that were previously hidden using
hide_pre_key()
.- Return type
None
- abstract async get_num_visible_pre_keys()[source]
- Return type
int
- Returns
The number of visible pre keys available. The number returned here should match the number of pre keys included in the bundle returned by
get_bundle()
.
- abstract async generate_pre_keys(num_pre_keys)[source]
Generate and store pre keys.
- Parameters
num_pre_keys (
int
) – The number of pre keys to generate.- Return type
None
- abstract async get_bundle(bare_jid, device_id)[source]
- Parameters
bare_jid (
str
) – The bare JID of this XMPP account, to be included in the bundle.device_id (
int
) – The id of this device, to be included in the bundle.
- Return type
- Returns
The bundle containing public information about the cryptographic state of this backend.
Warning
Do not include pre keys hidden by
hide_pre_key()
in the bundle!
- exception omemo.backend.BackendException[source]
Bases:
OMEMOException
Parent type for all exceptions specific to
Backend
.
- exception omemo.backend.DecryptionFailed[source]
Bases:
BackendException
Raised by various methods of
Backend
in case of backend-specific failures during decryption.
- exception omemo.backend.KeyExchangeFailed[source]
Bases:
BackendException
Raised by
Backend.build_session_active()
andBackend.build_session_passive()
in case of an error during the processing of a key exchange for session building. Known error conditions are:The bundle does not contain and pre keys (active session building)
The signature of the signed pre key could not be verified (active session building)
An unkown (signed) pre key was referred to (passive session building)
Additional backend-specific error conditions might exist.
- exception omemo.backend.TooManySkippedMessageKeys[source]
Bases:
BackendException
Raised by
Backend.decrypt_key_material()
if a message skips more message keys than allowed.