Matrix End-to-End Encryption Primitives

'Olm' and 'Megolm' encryption ratchet primitives for the 'Matrix' messaging protocol < https://matrix.org/>, wrapping the 'vodozemac' Rust crate. Provides device-key generation, one-time-key management, 1:1 'Olm' sessions, and 'Megolm' group sessions. Pairs with the 'mx.api' package, which handles 'Matrix' HTTP transport.


mx.crypto

Olm + Megolm cryptographic ratchet primitives for Matrix, wrapping vodozemac (Matrix.org's pure-Rust crypto crate). Pairs with mx.api, which handles HTTP transport.

mx.crypto is crypto only. It does not make HTTP calls, does not canonicalise JSON, and does not orchestrate Matrix protocols. It exposes encrypted Ed25519 signing-key primitives for cross-signing and forwarded Megolm session import/export; mx.client owns the protocol and trust policy. SAS key agreement, SHA-256 commitments, display bytes, and constant-time MAC verification are available through mxc_sas_*(). Interactive protocol handling, human confirmation, and durable trust remain in mx.client.

Install

Requires a working Rust toolchain (cargo, rustc >= 1.85). On Ubuntu: sudo apt install rustc cargo. On macOS: brew install rust. Or rustup from https://rustup.rs.

# GitHub only for now; not on CRAN yet.
remotes::install_github("cornball-ai/mx.crypto")

Quick start: encrypt then decrypt

library(mx.crypto)

# Two devices want to talk
alice <- mxc_account_new()
bob   <- mxc_account_new()

# Bob publishes a one-time key
mxc_account_generate_one_time_keys(bob, 1L)
bob_otks <- mxc_account_one_time_keys(bob)
bob_idk  <- mxc_account_identity_keys(bob)

# Alice opens an Olm session to Bob using one of Bob's OTKs
sess_a <- mxc_olm_create_outbound(
    alice,
    peer_curve25519 = bob_idk$curve25519,
    peer_otk        = bob_otks[[1]]
)

# Alice encrypts; the first message is a pre-key (type 0)
ct <- mxc_olm_encrypt(sess_a, charToRaw("hello"))

# Bob accepts the pre-key, builds the matching inbound session, and
# decrypts in one step
result <- mxc_olm_create_inbound(
    bob,
    peer_curve25519 = mxc_account_identity_keys(alice)$curve25519,
    prekey_b64      = ct$body
)
mxc_account_mark_published(bob)
rawToChar(result$plaintext)
#> [1] "hello"

Verifying homeserver-supplied keys

Real Matrix flows pull device keys and one-time keys from a homeserver that you cannot fully trust. Verify before you use them:

# After mx.api::mx_keys_query(...) returns a device_keys entry:
keys <- mxc_verify_device_keys(
    device_keys = dk,
    expected_user_id = "@alice:example.org",
    expected_device_id = "ALICEDEV"
)
# `keys` is list(curve25519 = "...", ed25519 = "..."), only present if
# the device's self-signature checked out and its algorithms list
# advertises Olm + Megolm.

# After mx.api::mx_keys_claim(...) returns a signed OTK:
otk <- mxc_verify_one_time_key(
    algorithm_key_id   = "signed_curve25519:AAAA",
    key_object         = signed_otk_obj,
    signing_ed25519    = keys$ed25519,
    expected_user_id   = "@alice:example.org",
    expected_device_id = "ALICEDEV"
)
# `otk` is the verified curve25519 OTK string, ready to feed into
# mxc_olm_create_outbound().

Both helpers fail closed: any structural problem, signer mismatch, or signature-bytes mismatch raises a clear error. Identity pinning (TOFU on first contact + cross-signing) lives above this layer.

Status

0.2.1.1 (GitHub main, 2026-09-04). Not on CRAN yet.

  • 0.1.0 was the initial release, GitHub-only.
  • 0.2.0 adds mxc_ed25519_verify and the two mxc_verify_* helpers, fixes a latent memory-safety bug in mxc_olm_create_outbound (SessionCreationError is now propagated to R rather than silently encoded as a Session external pointer), and ships an audit vignette + SECURITY.md. See NEWS.md for the full changelog.
  • 0.2.1.1 adds encrypted Ed25519 signing-key handles for cross-signing and forwarded inbound Megolm session import, export, and identity inspection. The corresponding Matrix protocol orchestration lives in mx.client.

Tested on Ubuntu 24.04 and macOS via the GitHub Actions r-ci workflow, plus a live homeserver round-trip exercise at inst/integration/e2e_demo.R.

Security

  • SECURITY.md (repo root) covers the threat model, the pinned vodozemac version, pickle hygiene, and known limitations.
  • vignette("security-audit", package = "mx.crypto") walks the 2026-05 audit against the Soatok disclosure, with reproducers and fixes.
  • Vulnerability reports: email [email protected].

License

MIT or Apache 2.0, at your option. The bundled vodozemac crate is Apache 2.0; see inst/NOTICE and inst/AUTHORS for attribution of all vendored Rust crates.

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.

install.packages("mx.crypto")

0.2.2 by Troy Hernandez, 2 months ago


https://github.com/cornball-ai/mx.crypto


Report a bug at https://github.com/cornball-ai/mx.crypto/issues


Browse source code at https://github.com/cran/mx.crypto


Authors: Troy Hernandez [aut, cre] (ORCID: , cornball.ai [cph] , The Matrix.org Foundation C.I.C. [ctb, cph] (Authors of the bundled 'vodozemac' Rust crate; see inst/AUTHORS) , Authors of the dependency Rust crates [ctb] (see inst/AUTHORS for details)


Documentation:   PDF Manual  


MIT + file LICENSE | Apache License 2.0 license


Suggests tinytest, mx.api, simplermarkdown

System requirements: Cargo (Rust's package manager), rustc (>= 1.85)


Suggested by chat.api, corteza, mx.client.


See at CRAN