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
If you’re using macOS, you’ll also need to install GNU sed:
brew install gnu-sed
and add an alias to your shell configuration file: alias sed=gsed
(e.g. to ~/.zshenv
if you’re using zsh).
§Development Requirements
§Pre-commit
- Install the
pre-commit
framework - Run
pre-commit install
to initialize the pre-commit hooks
§Android
Install Android SDK and Build-Tools for API level 30+
[!important] If you are building on macOS you’ll need to setup
$ANDROID_SDK_ROOT
path variable manually:ⓘexport ANDROID_SDK_ROOT=~/Android/Sdk
Install android rust targets:
rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi
Build:
cd crypto-ffi
cargo make android
cd bindings
./gradlew android:build
§iOS
Install Xcode & its command-line tools: https://developer.apple.com/xcode/.
Install iOS rust targets:
rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim
Build:
cd crypto-ffi
cargo make ios
cargo make ios-create-xcframework
§MacOS
Install macOS rust targets:
rustup target add x86_64-apple-darwin aarch64-apple-darwin
§Linux
[!note] 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-unknown
toolchain:rustup target add wasm32-unknown-unknown
- Install node.js (recommended way is via Volta)
- Install Bun (follow the instructions on Bun’s website)
Build:
cd crypto-ffi
cargo make wasm
§Bindings
Build bindings for Android, JVM, iOS and WASM
cd crypto-ffi
cargo make jvm
cargo make android
cargo make ios-create-xcframework
cargo make wasm
§Testing
§General testing
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-pack
If 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
[!warning] This takes quite a while.
cargo nextest run --features test-all-cipher
§Platform-specific tests for Kotlin/JVM
Build the JVM target every timee the Rust code changes:
# substitute with `jvm-darwin` on OSX
core-crypto/crypto-ffi$ cargo make jvm-linux
Then run the tests each time the wrapper or wrapper tests change
core-crypto/crypto-ffi/bindings$ ./gradlew jvm:build -x lint -x lintRelease
§Platform-specific tests for Android
Build the Android target every timee the Rust code changes:
core-crypto/crypto-ffi$ cargo make android
Then run the tests each time the wrapper or wrapper tests change
core-crypto/crypto-ffi/bindings$ ./gradlew android:build -x lint -x lintRelease
§Swift/iOS
No E2E testing is available as of now on Swift.
§Platform-spcecific tests for WASM/Web
Install TS dependencies on first go, and each time they change:
bun install
Build the WASM target every timee the Rust code changes:
core-crypto/crypto-ffi$ cargo make wasm
Then run the tests each time the wrapper or wrapper tests change
core-crypto/crypto-ffi$ bun run test
Note that CI will fail if it doesn’t like your formatting. This can typically be automtically adjusted with
core-crypto/crypto-ffi$ bun eslinst bindings/js --max-warnings=0 --fix
§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 -- --quick
where 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
main
branch 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.x
must 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
main
to prepare for release (git checkout -b prepare-release/X.Y.Z
) - Run
sh scripts/update-versions.sh X.Y.Z
to update the versions of- all workspace member crates
package.json
crypto-ffi/bindings/gradle.properties
Make sure the result of the script run is correct.
- Generate the relevant changelog section:and add it to the top of
git cliff --bump --unreleased
CHANGELOG.md
. Make sure the version number generated bygit cliff
matches 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
- Make sure the changes look reasonable and complete; you can use the previous release as a reference
- Push your
prepare-release/X.Y.Z
branch and create a PR for it - Get it reviewed, then merge it into
main
and remove theprepare-release/X.Y.Z
branch 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à!
§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/android
./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
.
Modules§
- This module contains the primitives to enable transactional support on a higher level within the MlsCentral. All mutating operations need to be done through a CentralContext.
- re-export rusty-jwt-tools API
- MLS Abstraction
- Common imports that should be useful for most uses of the crate
- Proteus Abstraction
Structs§
- Metadata describing the conditions of the build of this software.
- Wrapper superstruct for both mls::MlsCentral and proteus::ProteusCentral
Enums§
- CoreCrypto errors
- Wrapper for errors that can happen during a Cryptobox migration
- MLS-specific error wrapper - see github.com/openmls/openmls for details
- Response from the delivery service
- Wrapper for Proteus-related errors
Constants§
- Metadata describing the conditions of the build of this software.
Traits§
- Client callbacks to allow communication with the delivery service. There are two different endpoints, one for messages and one for commit bundles.
Type Aliases§
- A simpler definition for Result types that the Error is a CryptoError