The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

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 implement cross-signing or SAS verification (yet).

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.0 (GitHub main, 2026-05-13). Not on CRAN yet.

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

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.

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.