Expand description

OpenMLS

OpenMLS Chat OpenMLS List

Tests & Checks ARM64 Build Status codecov

Docs Book Rust Version

OpenMLS is a Rust implementation of Messaging Layer Security based on draft 12+.

It is a software library that can serve as a building block in applications that require end-to-end encryption of messages. It has a safe and easy-to-use interface that hides the complexity of the underlying cryptographic operations.

Supported ciphersuites

  • MLS10_128_HPKEX25519_AES128GCM_SHA256_Ed25519 (MTI)
  • MLS10_128_DHKEMP256_AES128GCM_SHA256_P256
  • MLS10_128_HPKEX25519_CHACHA20POLY1305_SHA256_Ed25519

Supported platforms

OpenMLS is built and tested on the Github CI for the following rust targets.

  • x86_64-unknown-linux-gnu
  • i686-unknown-linux-gnu
  • x86_64-pc-windows-msvc
  • i686-pc-windows-msvc
  • x86_64-apple-darwin

Additionally, we’re building and testing aarch64-unknown-linux-gnu on drone.io.

The Github CI also builds (but doesn’t test) the following rust targets.

  • aarch64-apple-darwin
  • aarch64-unknown-linux-gnu
  • aarch64-linux-android
  • aarch64-apple-ios
  • aarch64-apple-ios-sim
  • wasm32-unknown-unknown
  • armv7-linux-androideabi
  • x86_64-linux-android
  • i686-linux-android

OpenMLS supports 32 bit platforms and above.

Cryptography Dependencies

OpenMLS does not implement its own cryptographic primitives. Instead, it relies on existing implementations of the cryptographic primitives used by MLS. There are two different cryptography backends implemented right now. But consumers can bring their own implementation. See traits for more details.

Working on OpenMLS

For more details when working on OpenMLS itself please see the Developer.md.

Quick Start

For a quick start to learn how OpenMLS works here’s the basic code to set up to parties and have them create a group.

use openmls::prelude::*;
use openmls_rust_crypto::{OpenMlsRustCrypto};

// Define cipher suite ...
let ciphersuite = Ciphersuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519;
// ... and the crypto backend to use.
let backend = &OpenMlsRustCrypto::default();

// Now let's create two participants.

// A helper to create and store credentials.
fn generate_credential_bundle(
    identity: Vec<u8>,
    credential_type: CredentialType,
    signature_algorithm: SignatureScheme,
    backend: &impl OpenMlsCryptoProvider,
) -> Result<Credential, CredentialError> {
    let credential_bundle =
        CredentialBundle::new(identity, credential_type, signature_algorithm, backend)?;
    let credential_id =  credential_bundle.credential()
        .signature_key()
        .tls_serialize_detached()
        .expect("Error serializing signature key.");
    // Store the credential bundle into the key store so OpenMLS has access
    // to it.
    backend
        .key_store()
        .store(&credential_id, &credential_bundle)
        .expect("An unexpected error occurred.");
    Ok(credential_bundle.into_parts().0)
}

// A helper to create key package bundles.
fn generate_key_package_bundle(
    ciphersuites: &[Ciphersuite],
    credential: &Credential,
    backend: &impl OpenMlsCryptoProvider,
) -> Result<KeyPackage, KeyPackageBundleNewError> {
    // Fetch the credential bundle from the key store
    let credential_id = credential
        .signature_key()
        .tls_serialize_detached()
        .expect("Error serializing signature key.");
    let credential_bundle = backend
        .key_store()
        .read(&credential_id)
        .expect("An unexpected error occurred.");

    // Create the key package bundle
    let key_package_bundle =
        KeyPackageBundle::new(ciphersuites, &credential_bundle, backend, vec![])?;

    // Store it in the key store
    let key_package_id = key_package_bundle.key_package()
            .hash_ref(backend.crypto())
            .expect("Could not hash KeyPackage.");
    backend
        .key_store()
        .store(key_package_id.value(), &key_package_bundle)
        .expect("An unexpected error occurred.");
    Ok(key_package_bundle.into_parts().0)
}

// First they need credentials to identify them
let sasha_credential = generate_credential_bundle(
    "Sasha".into(),
    CredentialType::Basic,
    ciphersuite.signature_algorithm(),
    backend,
)
.expect("An unexpected error occurred.");

let maxim_credential = generate_credential_bundle(
    "Maxim".into(),
    CredentialType::Basic,
    ciphersuite.signature_algorithm(),
    backend,
)
.expect("An unexpected error occurred.");

// Then they generate key packages to facilitate the asynchronous handshakes
// in MLS

// Generate KeyPackages
let sasha_key_package = generate_key_package_bundle(&[ciphersuite], &sasha_credential, backend)
    .expect("An unexpected error occurred.");

let maxim_key_package = generate_key_package_bundle(&[ciphersuite], &maxim_credential, backend)
    .expect("An unexpected error occurred.");

// Now Sasha starts a new group ...
let mut sasha_group = MlsGroup::new(
    backend,
    &MlsGroupConfig::default(),
    GroupId::from_slice(b"My First Group"),
    sasha_key_package
        .hash_ref(backend.crypto())
        .expect("Could not hash KeyPackage.")
        .as_slice(),
)
.expect("An unexpected error occurred.");

// ... and invites Maxim.
// The key package has to be retrieved from Maxim in some way. Most likely
// via a server storing key packages for users.
let (mls_message_out, welcome) = sasha_group
    .add_members(backend, &[maxim_key_package])
    .expect("Could not add members.");

// Sasha merges the pending commit that adds Maxim.
sasha_group
   .merge_pending_commit()
   .expect("error merging pending commit");

// Now Maxim can join the group.
 let mut maxim_group = MlsGroup::new_from_welcome(
    backend,
    &MlsGroupConfig::default(),
    welcome,
    // The public tree is need and transferred out of band.
    // It is also possible to use the [`RatchetTreeExtension`]
    Some(sasha_group.export_ratchet_tree()),
 )
 .expect("Error joining group from Welcome");

Modules

Ciphersuites for MLS

Credentials

OpenMLS Errors

Extensions

Message framing

Group API for MLS

Key Packages

Messages

Single place, re-exporting the most used public functions. Prelude for OpenMLS. Include this to get access to all the public functions of OpenMLS.

Key schedule

This module implements the ratchet tree component of MLS.

MLS versions