Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/openmls/openmls/llms.txt

Use this file to discover all available pages before exploring further.

Overview

OpenMLS uses digital signatures to authenticate MLS protocol messages. This module provides types and operations for:
  • Creating and managing signature keys
  • Signing data with labeled signatures
  • Verifying signatures against public keys
  • Type-safe signature workflows

Signature

A cryptographic signature value.
Signature
struct
Digital signature over signed content

Conversions

From<Vec<u8>>
impl
Creates a signature from raw bytes
impl From<Vec<u8>> for Signature

SignaturePublicKey

A public signature verification key.
SignaturePublicKey
struct
Public key for signature verification

Methods

into_signature_public_key_enriched
fn(self, SignatureScheme) -> OpenMlsSignaturePublicKey
Converts the raw signature key into an enriched form with signature scheme
pub fn into_signature_public_key_enriched(
    self,
    signature_scheme: SignatureScheme,
) -> OpenMlsSignaturePublicKey
as_slice
fn(&self) -> &[u8]
Returns the key bytes as a slice
pub fn as_slice(&self) -> &[u8]

Conversions

From<Vec<u8>>
impl
Creates a signature public key from bytes
impl From<Vec<u8>> for SignaturePublicKey
From<&[u8]>
impl
Creates a signature public key from a byte slice
impl From<&[u8]> for SignaturePublicKey
From<OpenMlsSignaturePublicKey>
impl
Converts from enriched to raw signature public key
impl From<OpenMlsSignaturePublicKey> for SignaturePublicKey

OpenMlsSignaturePublicKey

An enriched public signature key that includes the signature scheme.
OpenMlsSignaturePublicKey
struct
Signature public key with associated signature scheme

Methods

new
fn(VLBytes, SignatureScheme) -> Result<Self, CryptoError>
Creates a new signature public key with the given bytes and scheme
pub fn new(value: VLBytes, signature_scheme: SignatureScheme) -> Result<Self, CryptoError>
from_signature_key
fn(SignaturePublicKey, SignatureScheme) -> Self
Creates an enriched key from a raw signature key and scheme
pub fn from_signature_key(key: SignaturePublicKey, signature_scheme: SignatureScheme) -> Self
signature_scheme
fn(&self) -> SignatureScheme
Returns the signature scheme
pub fn signature_scheme(&self) -> SignatureScheme
as_slice
fn(&self) -> &[u8]
Returns the key bytes as a slice
pub fn as_slice(&self) -> &[u8]

SignatureScheme

Signature algorithms according to IANA TLS parameters.
SignatureScheme
enum
Supported signature schemes

Conversions

TryFrom<u16>
impl
Attempts to convert a u16 value to a SignatureScheme
impl TryFrom<u16> for SignatureScheme
Returns an error if the value doesn’t correspond to a supported scheme.

SignContent

Labeled signature content used for signing operations.
SignContent
struct
Content to be signed with MLS label prefix

MLS Signature Format

MLS uses labeled signatures with the format:
struct {
    opaque label<V> = "MLS 1.0 " + Label;
    opaque content<V> = Content;
} SignContent;

Methods

new
fn(&str, VLBytes) -> Self
Creates new SignContent with a label and content
pub fn new(label: &str, content: VLBytes) -> Self
The label is automatically prefixed with “MLS 1.0 ”.

Signing Traits

Signable

Trait for structs that can be signed.
Signable
trait
Implemented by structs that need to be signed
pub trait Signable: Sized {
    type SignedOutput;

    fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error>;
    fn label(&self) -> &str;
    fn sign(self, signer: &impl Signer) -> Result<Self::SignedOutput, SignatureError>;
}

SignedStruct

Marker trait for signed structs.
SignedStruct
trait
Implemented by structs containing a signature
pub trait SignedStruct<T> {
    fn from_payload(payload: T, signature: Signature, serialized_payload: Vec<u8>) -> Self;
}

Verifiable

Trait for structs that can be verified.
Verifiable
trait
Implemented by structs with signatures that need verification
pub trait Verifiable: Sized {
    type VerifiedStruct: VerifiedStruct;

    fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error>;
    fn signature(&self) -> &Signature;
    fn label(&self) -> &str;
    fn verify(
        self,
        crypto: &impl OpenMlsCrypto,
        pk: &OpenMlsSignaturePublicKey,
    ) -> Result<Self::VerifiedStruct, SignatureError>;
    fn verify_no_out(
        &self,
        crypto: &impl OpenMlsCrypto,
        pk: &OpenMlsSignaturePublicKey,
    ) -> Result<(), SignatureError>;
}

VerifiedStruct

Marker trait for verified structs.
VerifiedStruct
trait
Marker trait for structs with verified signatures
pub trait VerifiedStruct {}

Errors

SignatureError

SignatureError
enum
Signature generation and verification errors

Usage Examples

Creating Signature Keys

use openmls::prelude::*;
use openmls_basic_credential::SignatureKeyPair;

let signature_scheme = SignatureScheme::ED25519;

// Generate a new key pair
let keypair = SignatureKeyPair::new(signature_scheme)
    .expect("Failed to generate signature key pair");

// Get the public key
let public_key: SignaturePublicKey = keypair.public().into();

// Create enriched public key
let enriched_key = public_key.into_signature_public_key_enriched(signature_scheme);

Signing with Signable Trait

use openmls::prelude::*;

// Example: KeyPackageTbs implements Signable
let key_package_tbs = KeyPackageTbs {
    protocol_version: ProtocolVersion::default(),
    ciphersuite,
    init_key,
    leaf_node,
    extensions,
};

// Sign to produce KeyPackage (which implements SignedStruct)
let key_package = key_package_tbs.sign(&signer)?;

Verifying Signatures

use openmls::prelude::*;

// Deserialize an unverified struct (implements Verifiable)
let key_package_in = KeyPackageIn::tls_deserialize(&mut bytes)?;

// Get the public key from the credential
let public_key = OpenMlsSignaturePublicKey::from_signature_key(
    credential.signature_key().clone(),
    signature_scheme,
);

// Verify and get verified struct
let verified = key_package_in.verify(provider.crypto(), &public_key)?;

Creating Labeled Sign Content

use openmls::ciphersuite::{SignContent, LABEL_PREFIX};
use tls_codec::Serialize;

let label = "KeyPackageTBS";
let content = payload_bytes.into();

let sign_content = SignContent::new(label, content);
let to_sign = sign_content.tls_serialize_detached()?;

// The actual bytes signed include:
// "MLS 1.0 KeyPackageTBS" + payload_bytes

Signature Scheme Selection

use openmls::prelude::*;

// Get signature scheme from ciphersuite
let ciphersuite = Ciphersuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519;
let sig_scheme = ciphersuite.signature_algorithm();
// Returns: SignatureScheme::ED25519

// Match on signature scheme
match sig_scheme {
    SignatureScheme::ED25519 => println!("Using Ed25519"),
    SignatureScheme::ECDSA_SECP256R1_SHA256 => println!("Using ECDSA P-256"),
    _ => println!("Other scheme"),
}

Type-Safe Signature Workflow

OpenMLS uses type-level enforcement to ensure correct signature handling:
// 1. Create unsigned struct (implements Signable)
let unsigned = KeyPackageTbs { /* ... */ };

// 2. Sign it (consumes unsigned, produces SignedStruct)
let signed = unsigned.sign(&signer)?;

// 3. Serialize and send
let bytes = signed.tls_serialize_detached()?;

// 4. Receiver deserializes (produces Verifiable)
let verifiable = KeyPackageIn::tls_deserialize(&mut bytes)?;

// 5. Verify (consumes verifiable, produces VerifiedStruct)
let verified = verifiable.verify(crypto, &public_key)?;

// 6. Only verified structs can be used in protocol operations
process_key_package(verified);
The type system ensures:
  • Only signed structs are serialized
  • Only verified structs are used in protocol logic
  • Unverified data cannot be accidentally processed

Security Considerations

  • Always verify signatures before processing received data
  • Use the correct signature scheme for the ciphersuite
  • Protect private signature keys appropriately
  • The MLS label prefix (“MLS 1.0 ”) is critical for domain separation
  • Signature verification errors should be treated as security events