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

Update your own key material in the group. This operation creates a Commit that includes a path with new encryption keys and can optionally update your credential, capabilities, and extensions.

Self Update

Basic Update

Update key material with default parameters:
use openmls::prelude::*;

let leaf_node_params = LeafNodeParameters::default();

let bundle = alice_group.self_update(
    provider,
    &signer,
    leaf_node_params,
)?;

let commit = bundle.commit();
let welcome = bundle.welcome();  // Some if there were pending Adds
let group_info = bundle.group_info();

// Send commit to group
alice_group.merge_pending_commit(provider)?;

Update with New Parameters

Update credential, capabilities, or extensions:
let new_capabilities = Capabilities::builder()
    .versions(vec![ProtocolVersion::Mls10])
    .ciphersuites(vec![ciphersuite])
    .extensions(vec![ExtensionType::ApplicationId])
    .build();

let new_extensions = Extensions::single(
    Extension::ApplicationId(ApplicationIdExtension::new(b"my-app-id"))
);

let leaf_node_params = LeafNodeParameters::builder()
    .with_capabilities(new_capabilities)
    .with_extensions(new_extensions)
    .build();

let bundle = alice_group.self_update(
    provider,
    &signer,
    leaf_node_params,
)?;

alice_group.merge_pending_commit(provider)?;

Update Signature Key

Update your signature public key (requires new signer):
// Generate new signature key pair
let new_signature_keypair = SignatureKeyPair::new(
    ciphersuite.signature_algorithm()
)?;
new_signature_keypair.store(provider.storage())?;

let new_signer = NewSignerBundle {
    signer: &new_signature_keypair,
    new_public_key: new_signature_keypair.public().into(),
};

let leaf_node_params = LeafNodeParameters::builder()
    .with_signature_public_key(new_signature_keypair.public().into())
    .build();

let bundle = alice_group.self_update_with_new_signer(
    provider,
    &old_signer,
    new_signer,
    leaf_node_params,
)?;

alice_group.merge_pending_commit(provider)?;

Method Signatures

self_update

provider
&Provider
required
OpenMLS provider for crypto and storage
signer
&impl Signer
required
Your current signature key
leaf_node_parameters
LeafNodeParameters
required
New parameters for your leaf node
Returns: Result<CommitMessageBundle, SelfUpdateError> The bundle contains:
  • Commit message
  • Optional Welcome (if there were pending Add proposals)
  • Optional GroupInfo
Location: openmls/src/group/mls_group/updates.rs:23

self_update_with_new_signer

Update including signature public key change.
provider
&Provider
required
OpenMLS provider for crypto and storage
old_signer
&impl Signer
required
Your current signature key
new_signer
NewSignerBundle
required
New signature key and public key
leaf_node_parameters
LeafNodeParameters
required
New parameters (must include new signature public key)
Returns: Result<CommitMessageBundle, SelfUpdateError> Location: openmls/src/group/mls_group/updates.rs:62

propose_self_update

Create an Update proposal without committing.
provider
&Provider
required
OpenMLS provider for crypto and storage
signer
&impl Signer
required
Your signature key
leaf_node_parameters
LeafNodeParameters
required
New parameters for your leaf node
Returns: Result<(MlsMessageOut, ProposalRef), ProposeSelfUpdateError> Location: openmls/src/group/mls_group/updates.rs:148

Leaf Node Parameters

Configure what to update in your leaf node:
let params = LeafNodeParameters::builder()
    .with_capabilities(capabilities)
    .with_extensions(extensions)
    .with_signature_public_key(public_key)  // Only with new_signer
    .build();
with_capabilities
Capabilities
Update supported protocol versions, ciphersuites, extensions, and proposals
with_extensions
Extensions<LeafNode>
Update leaf node extensions (e.g., ApplicationId)
with_signature_public_key
SignaturePublicKey
Update signature public key (requires self_update_with_new_signer)

Complete Examples

Simple Key Rotation

1

Create update parameters

let leaf_node_params = LeafNodeParameters::default();
2

Perform update

let bundle = alice_group.self_update(
    provider,
    &alice_signer,
    leaf_node_params,
)?;
3

Send and merge

let commit = bundle.commit();
delivery_service.send_to_group(alice_group.group_id(), commit)?;

alice_group.merge_pending_commit(provider)?;

Update Credential

1

Create new credential

let new_credential = BasicCredential::new(
    b"alice@new-domain.example".to_vec()
)?;
let new_credential_with_key = CredentialWithKey {
    credential: new_credential.into(),
    signature_key: current_signature_public_key.into(),
};
2

Build leaf parameters

// Note: Updating credential requires more complex setup
// You need to update both the credential and ensure
// the signature key matches
let leaf_node_params = LeafNodeParameters::builder()
    // Set other parameters
    .build();
3

Update and merge

let bundle = alice_group.self_update(
    provider,
    &alice_signer,
    leaf_node_params,
)?;

alice_group.merge_pending_commit(provider)?;

Propose Update (Two-Step)

1

Create update proposal

let (proposal_msg, proposal_ref) = alice_group.propose_self_update(
    provider,
    &alice_signer,
    leaf_node_params,
)?;
2

Send proposal

delivery_service.send_to_group(
    alice_group.group_id(),
    proposal_msg,
)?;
3

Commit later

// Someone (possibly you) commits the proposal
let (commit, welcome, group_info) = alice_group
    .commit_to_pending_proposals(provider, &alice_signer)?;

alice_group.merge_pending_commit(provider)?;

Processing Updates

Other members process your update:
// Bob receives and processes Alice's update
let processed = bob_group.process_message(provider, commit_msg)?;

if let ProcessedMessageContent::StagedCommitMessage(staged_commit) = 
    processed.into_content()
{
    // Check for update proposals
    for update in staged_commit.update_proposals() {
        println!("Member {} updated their leaf", update.sender());
    }
    
    // Merge the commit
    bob_group.merge_staged_commit(provider, *staged_commit)?;
}

Error Handling

match alice_group.self_update(provider, &signer, params) {
    Ok(bundle) => {
        // Success
    }
    Err(SelfUpdateError::GroupStateError(state_error)) => {
        match state_error {
            MlsGroupStateError::PendingCommit => {
                // Must merge or clear pending commit first
            }
            MlsGroupStateError::UseAfterEviction => {
                // Can't update after being removed
            }
        }
    }
    Err(SelfUpdateError::CreateCommitError(commit_error)) => {
        // Failed to create commit
    }
    Err(e) => eprintln!("Error updating: {}", e),
}

Advanced Usage

Using CommitBuilder

let bundle = alice_group
    .commit_builder()
    .leaf_node_parameters(leaf_node_params)
    .consume_proposal_store(true)  // Include pending proposals
    .load_psks(provider.storage())?
    .build(provider.rand(), provider.crypto(), &signer, |_| true)?
    .stage_commit(provider)?;

let commit = bundle.commit();
alice_group.merge_pending_commit(provider)?;

Update with Other Proposals

// Update yourself and add members in one commit
let bundle = alice_group
    .commit_builder()
    .leaf_node_parameters(leaf_node_params)
    .propose_adds(key_packages.iter().cloned())
    .load_psks(provider.storage())?
    .build(provider.rand(), provider.crypto(), &signer, |_| true)?
    .stage_commit(provider)?;

Important Notes

Signature Key Update: When updating your signature public key, you MUST use self_update_with_new_signer() and the new public key in LeafNodeParameters must match the NewSignerBundle.
Automatic Path: self_update() always includes a path in the commit, updating your encryption keys even if you only change other parameters.
Extension Support: The updated leaf node must support all group context extensions. The update will fail if it doesn’t.
Pending Proposals: self_update() consumes all pending proposals by default. Use CommitBuilder for more control.

When to Update

Update your key material when:
  • Regular Rotation: Periodically for forward secrecy
  • Credential Change: When your identity information changes
  • Capabilities Change: When you want to support new features
  • Key Compromise: If you suspect your keys are compromised
  • Policy Requirement: When group policy requires updates

Next Steps