Encryption (E2EE)

async-matrix ships end-to-end encryption primitives — Olm (1:1) and Megolm (group) — as Async::Matrix::E2EE, backed by a native Rust binding over vodozemac, the same crypto library used by Element. The binding is built with magnus and compiled via rake-compiler; requiring async/matrix loads the compiled object.

E2EE exposes the cryptographic building blocks. It is what a bridge or bot uses to participate in encrypted rooms; it is not a turnkey “encrypt my bot” switch.

Account and identity keys

An Account holds a device’s long-term identity and its one-time keys:

account = Async::Matrix::E2EE::Account.new
account.curve25519_key    # => base64 identity (Curve25519) key
account.ed25519_key       # => base64 signing (Ed25519) key

account.generate_one_time_keys(1)   # publish these so others can start sessions

Olm — 1:1 sessions

Establish a session from published identity + one-time keys, then exchange messages:

# Alice starts an outbound session to Bob
outbound = alice.create_outbound_session(bob.curve25519_key, bob_one_time_key)
type, body = outbound.encrypt("yo g")

# Bob accepts it inbound and decrypts
session, plaintext = bob.create_inbound_session(alice.curve25519_key, body)
plaintext   # => "yo g"

# Replies flow back over the same session
reply_type, reply_body = session.encrypt("hello back")
outbound.decrypt(reply_type, reply_body)   # => "hello back"

Megolm — group sessions

Room messages use Megolm. The sender holds a GroupSession; recipients rebuild an InboundGroupSession from its exported session key:

group = Async::Matrix::E2EE::GroupSession.new
message = group.encrypt("hello world")        # => base64 megolm ciphertext

inbound = Async::Matrix::E2EE::InboundGroupSession.new(group.session_key)
plaintext, index = inbound.decrypt(message)   # => ["hello world", 0]

The returned index is the Megolm ratchet index — useful for detecting replays and ordering.

Signature verification

Verify Ed25519 signatures (e.g. on device keys) with the module function:

signature = account.sign("payload")

Async::Matrix::E2EE.verify_signature(account.ed25519_key, "payload", signature)   # => true
Async::Matrix::E2EE.verify_signature(account.ed25519_key, "tampered", signature)  # => false

Building requirement

Because the binding is native, building the gem needs a Rust toolchain (the magnus extension is compiled at install time). The encryption section of the config schema carries the bridge-level encryption settings that sit on top of these primitives.


This site uses Just the Docs, a documentation theme for Jekyll.