awslabs / mls-rs

An implementation of Messaging Layer Security (RFC 9420)
Apache License 2.0
105 stars 19 forks source link

[1.x] Externalize dependencies of group join #215

Open mulmarta opened 2 weeks ago

mulmarta commented 2 weeks ago

Background:

Part of #211

Before (0.x)

Join Group API

// Make a key package store that conforms to the KeyPackageStorage trait
let psk_store = MyPskStore::new();

let client = Client::builder() 
        .pre_shared_key_storage(psk_store) // Transfer the ownership of the PSK repo to a client via the ClientBuilder
        ....
        .build();

// Join a group.
let (group, new_member_info) = client.join_group(tree_data, welcome_message).unwrap();

In the above, join_group internally finds the required PSKs by calling PreSharedKeyStorage::get on (a clone of) the psk_store with all External PSK IDs listed in the welcome message.

After (1.x)

Join Group API

Joining a group requires the Welcome message, the key package private key and the PSKs. Everything in the Welcome message except cipher suite and key package refs is encrypted. This encrypted part of the Welcome message contains among others External PDK IDs of PSKs needed to join and GroupInfo. This means that joining with PSKs requires 2 steps: first decrypt Welcome, second, find PSKs and join. Since this is complicated, we define 2 ways for joining: an immediate one as in #209 and one with PSK that uses an additional examine_welcome_message API.

Join with PSKs

let key_package_store = MyKeyPackageStore::new();
let psk_store = MyPskStore::new();

let client = Client::builder() 
        .... // No PSK / key package storage specific configuration 
        .build();

// Parse the Welcome message
let message_description = welcome_message.description();

let MlsMessageDescription::Welcome {
    key_package_refs, // List of key package refs found in the message
    cipher_suite,
} = message_description
else {
    // Handle the case where this is not a Welcome message
};

// Independently retrieve key package private key
let (private_kp_data, key_package_ref) = key_package_store.get(key_package_refs, cipher_suite).unwrap();

let joiner = client.group_joiner(welcome_message, private_kp_data).unwrap();

// Independently retrieve PSKs
let psks = psk_store.get(joiner.psk_ids()).unwrap();
println!("GroupInfo = {:?}", joiner.group_info);

// Join group. Key package private key is no longer needed - we cache decrypted secrets and leaf node
// secret key in `joiner`
let (group, new_member_info) = joiner
    .with_psks(psks)
    .with_tree_data(tree_data)
    .join()
    .unwrap()