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)
If you’re using macOS, you’ll also need to install GNU sed:
brew install gnu-sed make
and add aliases to your shell configuration file: alias sed=gsed
, aliase make=gmake
(e.g. to ~/.zshenv
if you’re
using zsh).
§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+
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:
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-sim
Build:
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-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:
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-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
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-test
Note 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 -- --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
- 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.x
withX.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.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à!
§Consider when making a release from a release branch
- Isolate the changes to index.md and
CHANGELOG.md
from the release commit itself - After the release is finished, cherry-pick the changes to index.md and
CHANGELOG.md
and get them intomain
- For release series
4.x
and newer, docs upload happens automatically. If you released from the series3.x
or older, you need to trigger docs upload manually:- On GitHub, go to the docs workflow
- Click the
Run workflow
button - In the
Use workflow from
dropdown, chooserelease/5.x
, inTag to checkout
provide 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
HistorySecret
encodes 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
MlsGroup
represents 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
MlsGroup
API, the message has to be unpacked viaextract
to 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.com
the 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
EpochObserver
is notified whenever a conversation’s epoch changes. - History
Observer - The
HistoryObserver
will 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 implementInto
for 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.