Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1.x] Externalize KeyPackageStorage and update join and write to storage generation API #209

Closed
Tracked by #211
mulmarta opened this issue Nov 8, 2024 · 6 comments

Comments

@mulmarta
Copy link
Contributor

mulmarta commented Nov 8, 2024

Background:

Part of #211

Before (0.x)

Join Group API

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

let client = Client::builder() 
        .key_package_repo(key_package_store) // Transfer the ownership of the key package 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 key package private key by calling KeyPackageStorage::get on (a clone of) the key_package_store with all key package references included in the welcome_message.

Write to Storage API

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

// Store state of the joined group.
group.write_to_storage().unwrap();

In the above, write_to_storage internally deletes the key package private key used to join by calling KeyPackageStorage::delete on (a clone of) the key_package_store owned by client.

After (1.x)

Join Group API

Client joins a group in three steps. First, it parses the Welcome message which returns information needed to fetch the private key from the storage. The same function will be used to parse other MLSMessage types like Commit, Proposal. Second, Client retrieves the private key and, third, it joins using the private key.

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

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

// Parse the Welcome message
let parsed_message = client.parse_message(welcome_message);

let ParsedMessage::Welcome {
    key_package_refs, // List of key package refs found in the message
    cipher_suite,
} = parsed_message
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();

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

// Delete used key package
key_package_store.delete(key_package_ref).unwrap();
@mgeisler
Copy link
Contributor

mgeisler commented Nov 8, 2024

Thanks for the write-up, Marta! This looks very nice to me.

I believe that this will overall make all method calls to Client and Group be "idempotent" (if that's the right word?)? That is, if I call it Client::join_group twice with the same arguments, I get the same (group, new_member_info) values back?

(Module any randomness that might be picked when the values are created, but semantically the values would compare equal after two calls.)

@mulmarta
Copy link
Contributor Author

You're right that join_group will be idempotent. I'm not 100% sure about Group functions. E.g. if you call Group::process_incoming_message with a ciphertext, I think for forward secrecy, Group should delete the decryption key from memory? Of course if you create Group again with the same snapshot, then you can receive the ciphertext for the second time.

@mgeisler
Copy link
Contributor

E.g. if you call Group::process_incoming_message with a ciphertext, I think for forward secrecy, Group should delete the decryption key from memory?

Yeah, it makes sense that there is an in-memory state which can change!

@tomleavy
Copy link
Contributor

Yes, the good news is we already have this in place in order to support processing multiple messages before the user calls write to storage.

@tomleavy tomleavy changed the title [WIP] [1.x] Externalize KeyPackageStorage and update join and write to storage generation API [1.x] Externalize KeyPackageStorage and update join and write to storage generation API Nov 11, 2024
@tomleavy
Copy link
Contributor

@mulmarta was working on the write_to_storage story, and I feel like we can avoid key package interaction in there all together by just having a property of private_kp_data in the above example containing the KeyPackageRef that needs to be deleted?

@tomleavy
Copy link
Contributor

Closing in favor of #215

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants