From 1425a47dde12807f1429281b91fb194020f70c35 Mon Sep 17 00:00:00 2001 From: Hinton Date: Fri, 19 Apr 2024 15:59:58 +0200 Subject: [PATCH] Add more docs to crypto crate --- bacon.toml | 3 +- .../bitwarden-crypto/src/keys/master_key.rs | 9 ++++ crates/bitwarden-crypto/src/lib.rs | 42 ++++++++++++++++--- crates/bitwarden-crypto/src/rsa.rs | 2 + crates/bitwarden-crypto/src/wordlist.rs | 2 +- crates/bitwarden-exporters/src/csv.rs | 2 +- crates/bitwarden-generators/src/username.rs | 4 +- crates/bitwarden/src/client/client.rs | 1 + crates/bitwarden/src/mobile/crypto.rs | 4 +- 9 files changed, 57 insertions(+), 12 deletions(-) diff --git a/bacon.toml b/bacon.toml index 099e47d75..6844980d5 100644 --- a/bacon.toml +++ b/bacon.toml @@ -66,8 +66,9 @@ command = [ "--document-private-items", "--open", ] +allow_warnings = true need_stdout = false -on_success = "back" +on_success = "job:doc-internal" # You may define here keybindings that would be specific to # a project, for example a shortcut to launch a specific job. diff --git a/crates/bitwarden-crypto/src/keys/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs index 1fd678452..b3a20fbc4 100644 --- a/crates/bitwarden-crypto/src/keys/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -7,6 +7,10 @@ use serde::{Deserialize, Serialize}; use super::utils::{derive_kdf_key, stretch_kdf_key}; use crate::{util, CryptoError, EncString, KeyDecryptable, Result, SymmetricCryptoKey, UserKey}; +/// Key Derivation Function for Bitwarden Account +/// +/// In Bitwarden accounts can use multiple KDFs to derive their master key from their password. This +/// Enum represents all the possible KDFs. #[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Enum))] @@ -22,6 +26,7 @@ pub enum Kdf { } impl Default for Kdf { + /// Default KDF for new accounts. fn default() -> Self { Kdf::PBKDF2 { iterations: default_pbkdf2_iterations(), @@ -29,15 +34,19 @@ impl Default for Kdf { } } +/// Default PBKDF2 iterations pub fn default_pbkdf2_iterations() -> NonZeroU32 { NonZeroU32::new(600_000).expect("Non-zero number") } +/// Default Argon2 iterations pub fn default_argon2_iterations() -> NonZeroU32 { NonZeroU32::new(3).expect("Non-zero number") } +/// Default Argon2 memory pub fn default_argon2_memory() -> NonZeroU32 { NonZeroU32::new(64).expect("Non-zero number") } +/// Default Argon2 parallelism pub fn default_argon2_parallelism() -> NonZeroU32 { NonZeroU32::new(4).expect("Non-zero number") } diff --git a/crates/bitwarden-crypto/src/lib.rs b/crates/bitwarden-crypto/src/lib.rs index 8c368580a..babcc921d 100644 --- a/crates/bitwarden-crypto/src/lib.rs +++ b/crates/bitwarden-crypto/src/lib.rs @@ -1,15 +1,47 @@ //! # Bitwarden Cryptographic primitives //! -//! This crate contains the cryptographic primitives used throughout the SDK. The crate makes a -//! best effort to abstract away cryptographic concepts into concepts such as [`EncString`], -//! [`AsymmetricEncString`] and [`SymmetricCryptoKey`]. +//! This crate contains the cryptographic primitives used throughout the SDK. The general +//! aspiration is for this crate to handle all the difficult cryptographic operations and expose +//! higher level concepts to the rest of the SDK. //! -//! ## Conventions: +//!
+//! Generally you should not find yourself needing to edit this crate! Everything written +//! here requires additional care and attention to ensure that the cryptographic primitives are +//! secure.
+//! +//! ## Example: +//! +//! ```rust +//! use bitwarden_crypto::{SymmetricCryptoKey, KeyEncryptable, KeyDecryptable, CryptoError}; +//! +//! async fn example() -> Result<(), CryptoError> { +//! let key = SymmetricCryptoKey::generate(rand::thread_rng()); +//! +//! let data = "Hello, World!".to_owned(); +//! let encrypted = data.clone().encrypt_with_key(&key)?; +//! let decrypted: String = encrypted.decrypt_with_key(&key)?; +//! +//! assert_eq!(data, decrypted); +//! Ok(()) +//! } +//! ``` +//! +//! ## Development considerations +//! +//! This crate is expected to provide long term support for cryptographic operations. To that end, +//! the following considerations should be taken into account when making changes to this crate: +//! +//! - Limit public interfaces to the bare minimum. +//! - Breaking changes should be rare and well communicated. +//! - Serializable representation of keys and encrypted data must be supported indefinitely as we +//! have no way to update all data. +//! +//! ### Conventions: //! //! - Pure Functions that deterministically "derive" keys from input are prefixed with `derive_`. //! - Functions that generate non deterministically keys are prefixed with `make_`. //! -//! ## Differences from `clients` +//! ### Differences from `clients` //! //! There are some noteworthy differences compared to the other Bitwarden //! [clients](https://github.com/bitwarden/clients). These changes are made in an effort to diff --git a/crates/bitwarden-crypto/src/rsa.rs b/crates/bitwarden-crypto/src/rsa.rs index 98f1282cc..6e3658c04 100644 --- a/crates/bitwarden-crypto/src/rsa.rs +++ b/crates/bitwarden-crypto/src/rsa.rs @@ -21,6 +21,7 @@ pub struct RsaKeyPair { pub private: EncString, } +/// Generate a new RSA key pair of 2048 bits pub(crate) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { let mut rng = rand::thread_rng(); let bits = 2048; @@ -48,6 +49,7 @@ pub(crate) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { }) } +/// Encrypt data using RSA-OAEP-SHA1 with a 2048 bit key pub(super) fn encrypt_rsa2048_oaep_sha1(public_key: &RsaPublicKey, data: &[u8]) -> Result> { let mut rng = rand::thread_rng(); diff --git a/crates/bitwarden-crypto/src/wordlist.rs b/crates/bitwarden-crypto/src/wordlist.rs index 4cc30ff74..f1e7a59c0 100644 --- a/crates/bitwarden-crypto/src/wordlist.rs +++ b/crates/bitwarden-crypto/src/wordlist.rs @@ -1,4 +1,4 @@ -// EFF's Long Wordlist from https://www.eff.org/dice +/// EFF's Long Wordlist from pub const EFF_LONG_WORD_LIST: &[&str] = &[ "abacus", "abdomen", diff --git a/crates/bitwarden-exporters/src/csv.rs b/crates/bitwarden-exporters/src/csv.rs index eb60fca21..a0dcd1040 100644 --- a/crates/bitwarden-exporters/src/csv.rs +++ b/crates/bitwarden-exporters/src/csv.rs @@ -54,7 +54,7 @@ pub(crate) fn export_csv(folders: Vec, ciphers: Vec) -> Result /// /// Be careful when changing this struct to maintain compatibility with old exports. #[derive(serde::Serialize)] diff --git a/crates/bitwarden-generators/src/username.rs b/crates/bitwarden-generators/src/username.rs index ccb46604b..36ded98b2 100644 --- a/crates/bitwarden-generators/src/username.rs +++ b/crates/bitwarden-generators/src/username.rs @@ -173,7 +173,7 @@ fn random_number(mut rng: impl RngCore) -> String { } /// Generate a username using a plus addressed email address -/// The format is +@ +/// The format is `+@` fn username_subaddress(mut rng: impl RngCore, r#type: AppendType, email: String) -> String { if email.len() < 3 { return email; @@ -195,7 +195,7 @@ fn username_subaddress(mut rng: impl RngCore, r#type: AppendType, email: String) } /// Generate a username using a catchall email address -/// The format is @ +/// The format is `@` fn username_catchall(mut rng: impl RngCore, r#type: AppendType, domain: String) -> String { if domain.is_empty() { return domain; diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 2374d6263..87a365a50 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -73,6 +73,7 @@ pub(crate) enum ServiceAccountLoginMethod { }, } +/// The main struct to interact with the Bitwarden SDK. #[derive(Debug)] pub struct Client { token: Option, diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index b8891aa09..2b985eaa8 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -231,9 +231,9 @@ pub fn update_password( #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct DerivePinKeyResponse { - /// [UserKey] protected by PIN + /// [UserKey](bitwarden_crypto::UserKey) protected by PIN pin_protected_user_key: EncString, - /// PIN protected by [UserKey] + /// PIN protected by [UserKey](bitwarden_crypto::UserKey) encrypted_pin: EncString, }