Expand description
Core Crypto is a wrapper on top of OpenMLS aimed to provide an ergonomic API for usage in web through Web Assembly and in mobile devices through FFI.
The goal is provide a easier and less verbose API to create, manage and interact with MLS groups.
§Wire CoreCrypto
This repository is part of the source code of Wire. You can find more information at wire.com or by contacting opensource@wire.com.
You can find the published source code at github.com/wireapp/wire.
For licensing information, see the attached LICENSE file and the list of third-party licenses at wire.com/legal/licenses/.
No license is granted to the Wire trademark and its associated logos, all of which will continue to be owned exclusively by Wire Swiss GmbH. Any use of the Wire trademark and/or its associated logos is expressly prohibited without the express prior written consent of Wire Swiss GmbH.
§Parts
- CoreCrypto: Abstracts MLS & Proteus in a unified API
 - CoreCryptoFFI: FFI bindings for iOS, Android and WASM
 - Keystore: Encrypted Keystore powered by SQLCipher on all platforms except WASM. WASM uses an IndexedDB-backed, encrypted store with AES256-GCM
 - MlsProvider: RustCrypto + Keystore MLS provider
 
See ARCHITECTURE.md
§Usage
§API Docs
§Building
§General Requirements
- rust: https://rustup.rs/
 - GNU make: https://www.gnu.org/software/make/ (min version: 4.3)
 
§Pre-commit
- Install the 
pre-commitframework - Run 
pre-commit installto initialize the pre-commit hooks 
§Android
Install Android SDK and Build-Tools for API level 30+
If you are building on macOS you’ll need to setup
$ANDROID_SDK_ROOTpath variable manually:export ANDROID_SDK_ROOT=~/Android/Sdk
Install the Android NDK. Make sure to set the
ANDROID_NDK_HOME variable to point to the NDK installation.
Install android rust targets:
rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabiBuild:
make android§iOS
Install Xcode & its command-line tools: https://developer.apple.com/xcode/.
Install iOS rust targets:
rustup target add aarch64-apple-ios aarch64-apple-ios-simBuild:
make ios
# Additionally, if you want to export a .XCFramework:
make ios-create-xcframework§MacOS
Install macOS rust targets:
rustup target add aarch64-apple-darwin§Linux
If cross-compiling from macOS, you’ll need to install https://github.com/messense/homebrew-macos-cross-toolchains.
Install Linux targets:
rustup target add x86_64-unknown-linux-gnu§WASM
Make sure you have all prerequisites:
- Install wasm-pack
 - Install the 
wasm32-unknown-unknowntoolchain:rustup target add wasm32-unknown-unknown - Install node.js (recommended way is via Volta)
 - Install Bun (follow the instructions on Bun’s website)
 
Build:
make ts§Bindings
Build bindings for Android, JVM, iOS and WASM
# builds bindings and targets for the JVM (macOS / Linux)
make jvm
# builds bindings and targets for Android
make android
# builds iOS framework
make ios-create-xcframework
# builds wasm binary & TS bindings
make ts§Testing
§General testing
# Install cargo-nextest if you haven't done so, it yields some substantial speedup
cargo install cargo-nextest
cargo nextest run§Run core crypto internal tests on WASM target
If you haven’t already, install the target and wasm-pack:
rustup target add wasm32-unknown-unknown
cargo install wasm-packIf you want to test for chrome, get chromedriver or the webdriver for the browser you want to test for, respectively.
Then, to run tests for a crate in the workspace do
wasm-pack test --headless --chrome ./<crate-folder-to-test>§Addendum: testing all ciphersuites
This takes quite a while.
cargo nextest run --features test-all-cipher§Platform-specific tests for Kotlin/JVM
make jvm-test§Platform-specific tests for Android
make android-test§Swift/iOS
No E2E testing is available as of now on Swift.
§Platform-specific tests for WASM/Web
make ts-testNote the CC_TEST_LOG_LEVEL environment variable. At 1 it emits browser console logs; at 2 it also emits CoreCrypto
logs.
§Benchmarks
There are benches implemented in crypto/benches for several operations on mls groups with varying
sizes or proteus. Parameters like minimum or maximum group sizes and step sizes are defined in
crypto/benches/utils/mod.rs.
§Executing Benches
To execute the benches, e.g. for creating commits, run
cargo bench --bench=commit -- --quickwhere commit is the name of the bench specified in crypto/Cargo.toml, and the corresponding
file in crypto/benches. In case you’re interested in higher accuracy, and willing to trade it for
execution speed, omit the --quick flag. If you need reporting plots, remove the .without_plots() call in
crypto/benches/utils/mod.rs. The reports generated by criterion will be located in
target/criterion.
§Git workflow
- The 
mainbranch is used as the everyday development branch. - No merge commits. Always rebase on top of 
main. - Release branches are named 
release/<series>, e.g.release/1.x,release/2.x. - Release branches contain fixes relevant to their specific release series and are never merged to 
main. - Release branches always branch off their first major release tag. For example, the output of
git merge-base main release/2.xmust be a commit pointed to by tagv2.0.0. - Release branches are created lazily, that is, only when the first fix needs to be applied and released for a specific release series.
 - Use conventional commits – those are picked up by the changelog generator.
 - If there is a JIRA ticket related to the change, you should mention it in either the PR title or the commit(s), with
the following format: 
[TICKET_ID]. - Sign your commits and tags.
 - Remove branches from the remote once you don’t need them anymore.
 
§Publishing
§Versioning
The versioning scheme used is SemVer AKA Semantic Versioning.
§Making a new release
- Make a branch based on 
mainto prepare for release (git checkout -b prepare-release/X.Y.Z) - Run 
sh scripts/update-versions.sh X.Y.Zto update the versions of- all workspace member crates
 package.jsoncrypto-ffi/bindings/gradle.propertiesMake sure the result of the script run is correct.
 - Generate the relevant changelog section:and add it to the top of
git cliff --bump --unreleasedCHANGELOG.md. Make sure the version number generated bygit cliffmatches the release version. - If there are any release highlights, add them as the first subsection below release title:
## v1.0.2 - 2024-08-16 ### Highlights - foo - bar - baz - In index.md, copy the commented-out table row from the bottom of the file to the appropriate place
in the table, ordering by version number, descending. Search and replace the first 5 occurrences of 
x.x.xwithX.Y.Z. - Make sure the changes look reasonable and complete; you can use the previous release as a reference
 - Push your 
prepare-release/X.Y.Zbranch and create a PR for it - Get it reviewed, then merge it into 
mainand remove theprepare-release/X.Y.Zbranch from the remote - Now, pull your local 
main:git checkout main && git pull - Create the release tag: 
git tag -s vX.Y.Z - Push the new tag: 
git push origin tag vX.Y.Z - Create a new release on github, copying the relevant section from 
CHANGELOG.md - Voilà!
 
§Consider when making a release from a release branch
- Isolate the changes to index.md and 
CHANGELOG.mdfrom the release commit itself - After the release is finished, cherry-pick the changes to index.md and 
CHANGELOG.mdand get them intomain - For release series 
4.xand newer, docs upload happens automatically. If you released from the series3.xor older, you need to trigger docs upload manually:- On GitHub, go to the docs workflow
 - Click the 
Run workflowbutton - In the 
Use workflow fromdropdown, chooserelease/5.x, inTag to checkoutprovide your release tag 
 
§Publishing Android / JVM bindings
Publishing Android / JVM bindings happens automatically by a github workflow when a release tag is pushed.
If you would like to publish the bindings to a local Maven cache, run:
cd crypto-ffi/bindings
./gradlew :jvm:publishToMavenLocal
./gradlew :android:publishToMavenLocal§Publishing JS / WASM bindings
Publishing JS / WASM bindings happens automatically by a github workflow when a release tag is pushed.
If you would like to publish to @wireapp/core-crypto manually, log into NPM and just run bun publish.
Re-exports§
pub use crate::e2e_identity::E2eiEnrollment;pub use crate::e2e_identity::types::E2eiAcmeChallenge;pub use crate::e2e_identity::types::E2eiAcmeDirectory;pub use crate::e2e_identity::types::E2eiNewAcmeAuthz;pub use crate::e2e_identity::types::E2eiNewAcmeOrder;pub use crate::mls::conversation::ConversationId;pub use crate::mls::conversation::MlsConversation;
Modules§
- e2e_
identity  - re-export rusty-jwt-tools API
 - mls
 - MLS Abstraction
 - proteus
 - Proteus Abstraction
 - transaction_
context  - This module contains the primitives to enable transactional support on a higher level within the Session. All mutating operations need to be done through a TransactionContext.
 
Structs§
- Build
Metadata  - Metadata describing the conditions of the build of this software.
 - Certificate
Bundle  - Represents a x509 certificate chain supplied by the client It can fetch it after an end-to-end identity process where it can get back a certificate from the Authentication Service
 - Client
Id  - A Client identifier
 - Core
Crypto  - Wrapper superstruct for both mls::session::Session and proteus::ProteusCentral
 - Credential
 - Credential.
 - Database
 - Database
Key  - The key used to encrypt the database.
 - Entropy
Seed  - Wrapped 32-byte entropy seed with bounds check
 - Group
Epoch  - Group epoch. Internally this is stored as a 
u64. The group epoch is incremented with every valid Commit that is merged into the group state. - History
Secret  - A 
HistorySecretencodes sufficient client state that it can be used to instantiate an ephemeral client. - KeyPackage
 - The key package struct.
 - KeyPackage
In  - The key package struct.
 - Keystore
Error  - A key store operation failed
 - MlsBuffered
Conversation Decrypt Message  - Type safe recursion of MlsConversationDecryptMessage
 - MlsCiphersuite
 - A wrapper for the OpenMLS Ciphersuite, so that we are able to provide a default value.
 - MlsCommit
Bundle  - Returned when a commit is created
 - MlsConversation
Configuration  - The configuration parameters for a group/conversation
 - MlsConversation
Decrypt Message  - Represents the potential items a consumer might require after passing us an encrypted message we have decrypted for him
 - MlsCrypto
Provider  - MlsCustom
Configuration  - The configuration parameters for a group/conversation which are not handled natively by openmls
 - MlsGroup
 - A 
MlsGrouprepresents an MLS group with a high-level API. The API exposes high level functions to manage a group by adding/removing members, get the current member list, etc. - MlsGroup
Config  - Specifies the configuration parameters for a 
MlsGroup. Refer to the User Manual for more information about the different configuration values. - MlsGroup
Info Bundle  - A [GroupInfo] with metadata
 - MlsMessage
In  - Before use with the 
MlsGroupAPI, the message has to be unpacked viaextractto yield its [MlsMessageInBody]. - MlsProposal
Bundle  - Returned when a Proposal is created. Helps roll backing a local proposal
 - MlsProposal
Ref  - Abstraction over a [openmls::prelude::hash_ref::ProposalRef] to deal with conversions
 - MlsTransport
Data  - An entity / data which has been packaged by the application to be encrypted and transmitted in an application message.
 - Session
 - A MLS Session enables a user device to communicate via the MLS protocol.
 - Session
Config  - Configuration parameters for Session
 - UserId
 - Unique identifier of a User (human person holding some devices).
This contradicts the initial design requirements of this project since it was supposed to be
agnostic from Wire.
End-to-end Identity re-shuffled that… But we still want to keep this isolated from the rest
of the crate that’s why this should remain here and be used cautiously, having the context quoted
above in mind.
For example in 
wireapp://LcksJb74Tm6N12cDjFy7lQ!8e6424430d3b28be@wire.comthe UserId isLcksJb74Tm6N12cDjFy7lQ - Validated
Session Config  - Validated configuration parameters for Session.
 - Verifiable
Group Info  - A type that represents a group info of which the signature has not been
verified. It implements the [
Verifiable] trait and can be turned into a group info by callingverify(...)with the signature key of theCredential. When receiving a serialized group info, it can only be deserialized into aVerifiableGroupInfo, which can then be turned into a group info as described above. - Welcome
Bundle  - Contains everything client needs to know after decrypting an (encrypted) Welcome message
 - Wire
Identity  - Represents the identity claims identifying a client Those claims are verifiable by any member in the group
 - X509
Identity  - Represents the parts of WireIdentity that are specific to a X509 certificate (and not a Basic one).
 
Enums§
- Ciphersuite
Name  - MLS ciphersuites.
 - Client
Identifier  - Used by consumers to initializes a MLS client. Encompasses all the client types available. Could be enriched later with Verifiable Presentations.
 - Connection
Type  - Where to open a connection
 - Device
Status  - Indicates the standalone status of a device Credential in a MLS group at a moment T. This does not represent the states where a device is not using MLS or is not using end-to-end identity
 - E2ei
Conversation State  - Indicates the state of a Conversation regarding end-to-end identity.
 - Error
 - Errors produced by the root module group
 - Group
Info Payload  - Represents the byte array in MlsGroupInfoBundle
 - Leaf
Error  - These errors can be raised from several different modules, so we centralize the definitions here to ease error-handling.
 - MlsCredential
Type  - Lists all the supported Credential types. Could list in the future some types not supported by openmls such as Verifiable Presentation
 - MlsError
Kind  - Openmls produces these kinds of error
 - MlsGroup
Info Encryption Type  - GroupInfoEncryptionType
 - MlsProposal
 - Internal representation of proposal to ease further additions
 - MlsRatchet
Tree Type  - RatchetTreeType
 - MlsTransport
Response  - Response from the delivery service
 - MlsWire
Policy  - Wrapper over WireFormatPolicy
 - Node
 - Container enum for leaf and parent nodes.
 - Proteus
Error Kind  - Proteus produces these kinds of error
 - Recursive
Error  - These errors wrap each of the module-specific errors in CoreCrypto.
 
Constants§
- BUILD_
METADATA  - Metadata describing the conditions of the build of this software.
 - HISTORY_
CLIENT_ ID_ PREFIX  - We always instantiate history clients with this prefix in their client id, so we can use prefix testing to determine with some accuracy whether or not something is a history client.
 - INITIAL_
KEYING_ MATERIAL_ COUNT  - Default number of KeyPackages a client generates the first time it’s created
 
Traits§
- Epoch
Observer  - An 
EpochObserveris notified whenever a conversation’s epoch changes. - History
Observer  - The 
HistoryObserverwill be called when updating the history client in a conversation - Innermost
Error Message  - Produce the error message from the innermost wrapped error.
 - MlsTransport
 - Client callbacks to allow communication with the delivery service. There are two different endpoints, one for messages and one for commit bundles.
 - ToRecursive
Error  - Like 
Into, but different, because we don’t actually want to implementIntofor our subordinate error types. 
Type Aliases§
- KeyPackage
Ref  - A reference to a key package. This value uniquely identifies a key package.
 - MlsError
 - A MLS operation failed, but we captured some context about how it did so
 - Proteus
Error  - A Proteus operation failed, but we captured some context about how it did so
 - RawEntropy
Seed  - 32-byte raw entropy seed
 - Result
 - A module-specific Result type with a default error variant.