Skip to content

Commit

Permalink
Done fixing up the API (at least for the functions that are tested)
Browse files Browse the repository at this point in the history
  • Loading branch information
msprotz committed Jun 20, 2024
1 parent 81ea7d2 commit 97d1014
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 20 deletions.
57 changes: 37 additions & 20 deletions js/MLS_JS.ml
Original file line number Diff line number Diff line change
Expand Up @@ -56,38 +56,55 @@ let option_bytes_of_uint8array o =

let framing_params_of_js o = {
encrypt = o##.encrypt;
padding_size = Z.of_int o##.padding_size;
authenticated_data = bytes_of_uint8array o##.authenticated_data;
padding_size = Z.of_int o##.padding_size_;
authenticated_data = bytes_of_uint8array o##.authenticated_data_;
}

let leaf_node_params_of_js o =
{ nothing_yet = () }

let commit_params_of_js o =
let proposals = Array.to_list o##.proposals in
let inline_tree = o##.inline_tree in
let force_update = o##.force_update in
let leaf_node_params = leaf_node_params_of_js o##.leaf_node_params in
let proposals = Array.to_list (Js.to_array o##.proposals) in
let inline_tree = o##.inline_tree_ in
let force_update = o##.force_update_ in
let leaf_node_params = leaf_node_params_of_js o##.leaf_node_params_ in
{ proposals; inline_tree; force_update; leaf_node_params }

let js_of_create_commit_result { commit; welcome; group_info } = object%js
val commit = uint8array_of_bytes commit
val welcome = Js.Opt.option (Option.map uint8array_of_bytes welcome)
val group_info = uint8array_of_bytes group_info
val group_info_ = uint8array_of_bytes group_info
end

let js_of_create_key_package_result { key_package; keystore_key; keystore_value } = object%js
val key_package = uint8array_of_bytes key_package
val key_package_ = uint8array_of_bytes key_package
val keystore_key_ = uint8array_of_bytes keystore_key
val keystore_value_ = uint8array_of_bytes keystore_value
end

let js_of_processed_message_content = function
| ApplicationMessage bytes ->
Obj.magic object%js
val kind = Js.string "ApplicationMessage"
val message = uint8array_of_bytes bytes
end
| Proposal uv ->
Obj.magic object%js
val kind = Js.string "Proposal"
val unvalidated_proposal_ = uv
end
| Commit uc ->
Obj.magic object%js
val kind = Js.string "Commit"
val unvalidated_commit_ = uc
end

let js_of_processed_message { group_id; epoch; sender; authenticated_data1; content } = object%js
val group_id = uint8array_of_bytes group_id
val group_id_ = uint8array_of_bytes group_id
val epoch = 0 (* TODO *)
val sender = sender (* TODO *)
val authenticated_data = uint8array_of_bytes authenticated_data1
val content = content
val authenticated_data_ = uint8array_of_bytes authenticated_data1
val content = js_of_processed_message_content content
end

let _ =
Expand Down Expand Up @@ -131,7 +148,7 @@ let _ =
Js.some cp

method mkX509Credential kp chain =
let chain = List.map bytes_of_uint8array (Array.to_list chain) in
let chain = List.map bytes_of_uint8array (Array.to_list (Js.to_array chain)) in
let* cp = call_c mk_x509_credential kp chain in
Js.some cp

Expand All @@ -141,7 +158,7 @@ let _ =

method createKeyPackage cp =
let$ ckpr = call_ce create_key_package cp in
Js.some ckpr
Js.some (js_of_create_key_package_result ckpr)

method createGroup cp =
let$ g = call_ce create_group cp in
Expand Down Expand Up @@ -185,7 +202,7 @@ let _ =

method getNewCredentials uv =
let* r = call_c get_new_credentials uv in
Js.some (Array.of_list r)
Js.some (Js.array (Array.of_list r))

method getNewCredential uv =
let* r = call_c get_new_credential uv in
Expand All @@ -195,19 +212,19 @@ let _ =
let bytes = bytes_of_uint8array bytes in
let* pm, g = call_c process_message g bytes in
Js.some (object%js
val processed_message = js_of_processed_message pm
val processed_message_ = js_of_processed_message pm
val group = g
end)

method iHerebyDeclareThatIHaveCheckedTheNewCredentialsAndValidateTheCommit uv =
Js.some (i_hereby_declare_that_i_have_checked_the_new_credentials_and_validate_the_commit uv)
Js.some (call_c i_hereby_declare_that_i_have_checked_the_new_credentials_and_validate_the_commit uv)

method mergeCommit g vc =
let* g = call_c merge_commit g vc in
Js.some g

method iHerebyDeclareThatIHaveCheckedTheNewCredentialsAndValidateTheProposal up =
Js.some (i_hereby_declare_that_i_have_checked_the_new_credentials_and_validate_the_proposal up)
Js.some (call_c i_hereby_declare_that_i_have_checked_the_new_credentials_and_validate_the_proposal up)

method queueNewProposal g vp =
let* g = call_c queue_new_proposal g vp in
Expand All @@ -216,7 +233,7 @@ let _ =
method sendApplicationMessage g fp m =
let fp = framing_params_of_js fp in
let m = bytes_of_uint8array m in
let$ message, g = call_ce g fp m in
let$ message, g = call_ce send_application_message g fp m in
Js.some (object%js
val message = uint8array_of_bytes message
val group = g
Expand Down Expand Up @@ -253,8 +270,8 @@ let _ =
let commit_params = commit_params_of_js commit_params in
let$ create_commit_result, mls_group = call_ce create_commit mls_group framing_params commit_params in
Js.some object%js
val create_commit_result = js_of_create_commit_result create_commit_result
val mls_group = mls_group
val create_commit_result_ = js_of_create_commit_result create_commit_result
val group_ = mls_group
end

method createAddProposal kp =
Expand Down
25 changes: 25 additions & 0 deletions js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,31 @@ if (typeof module !== undefined)
// NEW MLS API
setEntropy: MLS.setEntropy,
setCiphersuite: MLS.setCiphersuite,
generateSignatureKeyPair: MLS.generateSignatureKeyPair,
getSignaturePublicKey: MLS.getSignaturePublicKey,
mkBasicCredential: MLS.mkBasicCredential,
mkX509Credential: MLS.mkX509Credential,
getPublicCredential: MLS.getPublicCredential,
createKeyPackage: MLS.createKeyPackage,
createGroup: MLS.createGroup,
startJoinGroup: MLS.startJoinGroup,
continueJoinGroup: MLS.continueJoinGroup,
finalizeJoinGroup: MLS.finalizeJoinGroup,
exportSecret: MLS.exportSecret,
epochAuthenticator: MLS.epochAuthenticator,
epoch: MLS.epoch,
groupId: MLS.groupId,
getNewCredentials: MLS.getNewCredentials,
getNewCredential: MLS.getNewCredential,
processMessage: MLS.processMessage,
iHerebyDeclareThatIHaveCheckedTheNewCredentialsAndValidateTheCommit: MLS.iHerebyDeclareThatIHaveCheckedTheNewCredentialsAndValidateTheCommit,
mergeCommit: MLS.mergeCommit,
iHerebyDeclareThatIHaveCheckedTheNewCredentialsAndValidateTheProposal: MLS.iHerebyDeclareThatIHaveCheckedTheNewCredentialsAndValidateTheProposal,
queueNewProposal: MLS.queueNewProposal,
sendApplicationMessage: MLS.sendApplicationMessage,
proposeAddMember: MLS.proposeAddMember,
proposeRemoveMember: MLS.proposeRemoveMember,
proposeRemoveMyself: MLS.proposeRemoveMyself,
createCommit: MLS.createCommit,
createAddProposal: MLS.createAddProposal,
createRemoveProposal: MLS.createRemoveProposal,
Expand Down
80 changes: 80 additions & 0 deletions js/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,85 @@ var test_main = () => {
console.log(`JS-driven test took ${t2 - t1} milliseconds.`);
};

var test_new = () => {
// A test for the new, more general API. We start with some warm-up.

// This is the only supported one for now, we plan to expose AES-GCM soo.
MLS.setCiphersuite("mls_128_dhkemx25519_chacha20poly1305_sha256_ed25519");
// The source of entropy is customizable.
MLS.setEntropy((n) => crypto.getRandomValues(new Uint8Array(n)));

// Key pairs are opaque.
let signKeyPair_A = MLS.generateSignatureKeyPair();
console.log("Generated keyPair for A, public = ", MLS.getSignaturePublicKey(signKeyPair_A));

// We now distinguish a credential from a key package. Note that the identity
// is a Uint8Array as well, for uniformity with the rest of the API.
let credPair_A = MLS.mkBasicCredential(signKeyPair_A, Buffer.from("Alice", "ascii"));
let completeKeyPackage_A = MLS.createKeyPackage(credPair_A);
let store_A = {};
console.log(completeKeyPackage_A);
store_A[completeKeyPackage_A.keystore_key] = completeKeyPackage_A.keystore_value;
let keyPackage_A = completeKeyPackage_A.key_package;

let group_A = MLS.createGroup(credPair_A);
console.log("Updated the store =", store_A, "and created a group with just A, epoch =", MLS.epoch(group_A));

// Same thing for B.
let signKeyPair_B = MLS.generateSignatureKeyPair();
let credPair_B = MLS.mkBasicCredential(signKeyPair_B, Buffer.from("Bob", "ascii"));
let completeKeyPackage_B = MLS.createKeyPackage(credPair_B);
let store_B = {};
console.log(completeKeyPackage_B);
store_B[completeKeyPackage_B.keystore_key] = completeKeyPackage_B.keystore_value;
let keyPackage_B = completeKeyPackage_B.key_package;

// TODO: perhaps we would want to allow authenticated_data being null?
let framingParams = { encrypt: true, padding_size: 0, authenticated_data: new Uint8Array([]) };
let addProposal = MLS.createAddProposal(keyPackage_B);
let commitParams = {
// Extra proposals to include in the commit
proposals: [ addProposal ],
// Should we inline the ratchet tree in the Welcome messages?
inline_tree: true,
// Should we force the UpdatePath even if we could do an add-only commit?
force_update: true,
// Options for the generation of the new leaf node
leaf_node_params: {}
};
({ create_commit_result: { welcome, commit, group_info }, group: group_A } = MLS.createCommit(group_A, framingParams, commitParams));
console.log("welcome message for B", welcome);
console.log("commit message", commit);

// A processes the echo of the add
({ group: group_A, processed_message: { content } } = MLS.processMessage(group_A, commit));
// Note that beyond content, there are also fields for: epoch, sender, authenticated data,
// and group_id.
console.assert(content.kind == "Commit", "Processed message is not a commit!!");
let validated_commit = MLS.iHerebyDeclareThatIHaveCheckedTheNewCredentialsAndValidateTheCommit(content.unvalidated_commit);
group_A = MLS.mergeCommit(group_A, validated_commit);

// B creates its fresh state via the welcome message (try returning null
// always and you'll see the error).
let out = MLS.startJoinGroup(welcome, (k) => (k in store_B) ? store_B[k] : null);
out = MLS.continueJoinGroup(out, null);
group_B = MLS.finalizeJoinGroup(out);
console.log("B joined the group", groupId);

// B says hello
({ message, group: group_B } = MLS.sendApplicationMessage(group_B, framingParams, Buffer.from("hello", "ascii")));

// B processes the echo of the message
({ group: group_B, processed_message: { content } } = MLS.processMessage(group_B, message));
console.assert(content.kind == "ApplicationMessage", "Processed message is not an application message!!");
console.log((new TextDecoder()).decode(content.message, "ascii"));

// A receives the message
({ message, group: group_A } = MLS.processMessage(group_A, message));
console.assert(content.kind == "ApplicationMessage", "Processed message is not an application message!!");
console.log((new TextDecoder()).decode(content.message, "ascii"));
};

if (typeof module !== "undefined") {
(async () => {
// Load the WASM modules, and instruct the MLS node module to use NodeCrypto
Expand All @@ -101,6 +180,7 @@ if (typeof module !== "undefined") {
console.log("Test starting");

await test_main();
await test_new();
console.log("done\n")
})();
}

0 comments on commit 97d1014

Please sign in to comment.