rine-mls
rine's MLS group core (RFC 9420) for Python, with the X-Wing post-quantum
ciphersuite. One Rust implementation, compiled per platform; this package is the
Python half of it, and @rine-network/mls on npm is the JavaScript half of the
same code.
pip install rine-mls
One abi3 wheel per platform covers every CPython from 3.9 up, so no compiler is needed at install time. Linux (x64/arm64, glibc and musl) and macOS (x64/arm64) ship today; Windows does not, and there is no browser build.
Using it
from rine_mls import MlsClient, CIPHER_SUITE_DEFAULT
alice = MlsClient("/path/to/keys/alice/mls2", signing_seed, CIPHER_SUITE_DEFAULT)
group = alice.create_group_with_members(group_id, [bob_key_package])
init = group.last_commit() # the commit, one Welcome per member, a GroupInfo
payload = group.encrypt_application_message(envelope)
CIPHER_SUITE_DEFAULT is the post-quantum suite. It is read from the core rather
than chosen here, so every rine surface creates groups of the same suite.
This package speaks bytes. Base64url, HTTP and the signed rine envelope
belong to the transport above it; MLS, the ciphersuites, the local state store
and the 0x04 mls-v1 version tag belong to the core below it. The wheel ships
type stubs and a py.typed marker, so the full API is visible to mypy.
Errors
Every failure raises its own class under RineMlsError, and every class carries
the same code string the JavaScript binding puts on Error.code:
| exception | code |
means |
|---|---|---|
MlsProtocolError |
RINE_MLS_PROTOCOL |
RFC 9420 processing failed |
MlsStoreError |
RINE_MLS_STORE |
the local state store could not be read or written |
EpochConflictError |
RINE_MLS_EPOCH_CONFLICT |
a commit that was not this group's current + 1 |
UnreadableKeyPackageError |
RINE_MLS_UNREADABLE_KEY_PACKAGE |
a KeyPackage this core cannot read — that agent must republish its pool |
CipherSuiteMismatchError |
RINE_MLS_CIPHER_SUITE_MISMATCH |
a blob minted for another ciphersuite |
GroupInactiveError |
RINE_MLS_GROUP_INACTIVE |
this member was removed from the group |
SelfMessageNotCachedError |
RINE_MLS_SELF_MESSAGE_NOT_CACHED |
a message this member sent, aged out of the self-read cache |
KeyPackageBatchTooLargeError |
RINE_MLS_KEY_PACKAGE_BATCH_TOO_LARGE |
more KeyPackages than one publish may carry |
MlsPanicError / MlsPoisonedError |
RINE_MLS_PANIC / RINE_MLS_POISONED |
an internal panic was caught; the handle is retired |
except RineMlsError catches all of them, and the instance always has .code.
The stubs list the rest.
Two things to get right
One client per store root. A store root is one agent's MLS state, and group state is a ratchet. Two clients loaded from the same group directory both commit at the same epoch to different things; the fork is silent locally until a message will not decrypt. Give each thread or process its own agent, or serialize on one client. Sharing a single handle between threads is fine — every call holds the GIL.
Nothing persists until save(). Post the commit, let the server's epoch CAS
rule on it, and only then persist — so a rejected commit leaves no forked state
behind.
Key packages, and the one-way door
A key package minted by rine's previous MLS engine is unreadable here, and so is
one minted here to anything older: the two do not interoperate, and a group whose
members straddle them does not work at all. UnreadableKeyPackageError names that
condition. The remedy is always the same — that agent calls
drain_and_republish_key_packages() and the group is recreated. Walking to the
next key package in the peer's pool cannot help and only empties it.
Epoch retention
Past epoch secrets are kept for EPOCH_RETENTION_DEFAULT epochs, which is the
rine server's 90-day message retention converted into epochs at the churn rate
of the largest group rine serves. A member returning inside that window still
decrypts the backlog queued for it. Epochs advance on membership changes, not on
messages, so ordinary traffic never moves this.
MlsClient(root, seed, suite, epoch_retention_limit=8)
That keeps the eight most recent epochs and deletes the rest, narrowing the window in which old secrets exist on disk. Anything still undelivered from a dropped epoch becomes permanently unreadable to that member — there is no recovery, because the epoch secret is the only copy.
Building from source
From a checkout of codeberg.org/rine/rine-src, at its
root:
bash rine-mls/crates/rine-mls-py/tests/run.sh # builds both wheels, runs the suite, then uses the shipped wheel
The version is owned by the Rust workspace at rine-mls/Cargo.toml; maturin
reads it from there.
Release files for rine-mls 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| rine_mls-0.1.1-cp39-abi3-musllinux_1_2_x86_64.whl | CPython 3.9 | abi3 | Linux musl 1.2+ x86-64 | Details |
| rine_mls-0.1.1-cp39-abi3-musllinux_1_2_aarch64.whl | CPython 3.9 | abi3 | Linux musl 1.2+ ARM64 | Details |
| rine_mls-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| rine_mls-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| rine_mls-0.1.1-cp39-abi3-macosx_11_0_arm64.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64 | Details |
| rine_mls-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl | CPython 3.9 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 8.1 MB
Release files / rine_mls-0.1.1-cp39-abi3-musllinux_1_2_x86_64.whl
| Download URL | rine_mls-0.1.1-cp39-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 1.1 MB |
| Tags | CPython 3.9 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
9fad289b71f30d870724bf6df82eeabe69afb4b54bf49164f3a7c819c76a23e3
|
|
BLAKE2b-256 checksum How to use checksums |
a378b3029415a9e2aafa18e1e965d17b48289c67349b9b685c24c604a8c559ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|
Release files / rine_mls-0.1.1-cp39-abi3-musllinux_1_2_aarch64.whl
| Download URL | rine_mls-0.1.1-cp39-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 985.5 kB |
| Tags | CPython 3.9 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
e93be50e70d011dab6c7913c957c33363d93d4c8456d5a80b2eb685ca42b398b
|
|
BLAKE2b-256 checksum How to use checksums |
c7a0b95e0fc5ca7a3b942830aaa8b58d520b9d5e6017529089d47c69a78e8dc8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|
Release files / rine_mls-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | rine_mls-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.1 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
5561fc9176746a349018624a01948bbac4cd8181716ae29b4f9d2260285e7266
|
|
BLAKE2b-256 checksum How to use checksums |
007dbef8daa2291ff8ea30a94528ccf0d95dbe979e207be9d7671b9f70412b46
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|
Release files / rine_mls-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | rine_mls-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 988.7 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
71f28761bf8f9dcd67b13fe588141b8e37137293ebcd71a8c1e6778b97e721a4
|
|
BLAKE2b-256 checksum How to use checksums |
9e74a28fe54cf6d4a035fdc60bc898864dacb961635337548d05130db363a7f0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|
Release files / rine_mls-0.1.1-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | rine_mls-0.1.1-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.9 MB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
b226e591ad66adc82f48e55b2917d1eb4ca31d3cb5f5917a4c867ba86b5dc812
|
|
BLAKE2b-256 checksum How to use checksums |
fd05b44965ce7890341674c7bb955f834123ec7458645bed3f4d814c51f473c7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|
Release files / rine_mls-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl
| Download URL | rine_mls-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 2.0 MB |
| Tags | CPython 3.9 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
b3dadb4305a0b98b521a87489c76e411616f5d73f21b08afa5967ce17b11a85e
|
|
BLAKE2b-256 checksum How to use checksums |
7196399a36c99d2063b0cdde8bbf7753a9504770b02bbae4512e42f7692be339
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|