diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0cc6ac701af..618979ebf08 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -39,16 +39,23 @@ jobs: RUSTDOCFLAGS: -Dwarnings steps: - uses: actions/checkout@v7.0.0 - - uses: dtolnay/rust-toolchain@stable + - name: Install stable Rust + uses: dtolnay/rust-toolchain@stable with: - components: rustfmt, clippy + components: clippy # Check using Clippy with the feature combinations listed in the README. - run: cargo clippy - run: cargo clippy --no-default-features --features aes,hkdfsha2,nistp,serde - - name: Format - run: cargo fmt --all -- --check - - name: Docs run: cargo doc --no-deps + + - name: Install nightly Rust + uses: dtolnay/rust-toolchain@nightly + with: + components: rustfmt + + - name: Format + run: cargo +nightly fmt --all --message-format human -- --check + diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000000..909746b7a30 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,16 @@ +# Enforce consistent code formatting across the project +max_width = 100 +use_small_heuristics = "Default" + +# Comment formatting (requires nightly rustfmt) +wrap_comments = true +comment_width = 100 + +# Unstable features +imports_granularity = "Crate" +group_imports = "StdExternalCrate" +error_on_line_overflow = true + +# Note: format_code_in_doc_comments is NOT enabled due to known issues +# with block comment conversion and trailing comment alignment. +# See: https://github.com/rust-lang/rustfmt/issues/5533 diff --git a/src/aead.rs b/src/aead.rs index 44a6d74504b..f29357c6422 100644 --- a/src/aead.rs +++ b/src/aead.rs @@ -1,11 +1,12 @@ -use crate::IdLookupError; -use num_enum::TryFromPrimitive; use std::str::FromStr; -/** -Aead represents an authenticated encryption with additional data -encryption function, as per [RFC9180§7.3](https://www.rfc-editor.org/rfc/rfc9180.html#section-7.3) -*/ +use num_enum::TryFromPrimitive; + +use crate::IdLookupError; + +/// An authenticated encryption with additional data encryption function, as per [RFC9180§7.3][1]. +/// +/// [1]: https://www.rfc-editor.org/rfc/rfc9180.html#section-7.3 #[non_exhaustive] #[repr(u16)] #[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive)] diff --git a/src/base_mode_open.rs b/src/base_mode_open.rs index 15bd6287ce7..c8a848ee9e5 100644 --- a/src/base_mode_open.rs +++ b/src/base_mode_open.rs @@ -1,20 +1,20 @@ -use crate::{from_bytes, Config}; use hpke::HpkeError; -/** -`base_mode_open` provides an interface to [`hpke::single_shot_open`] -that does not require compile time selection of an algorithm. Instead, -the selected algorithm is provided through the [`Config`] passed as -the first argument. - -# Errors - -This will return an `Result::Err` variant if: +use crate::{from_bytes, Config}; -* we are unable to deserialize the private key or encapsulated key -* there is an error in key decapsulation -* there is an error in decryption - */ +/// Single-shot HPKE ciphertext opening. +/// +/// `base_mode_open` provides an interface to [`hpke::single_shot_open`] that does not require +/// compile time selection of an algorithm. Instead, the selected algorithm is provided through the +/// [`Config`] passed as the first argument. +/// +/// # Errors +/// +/// This will return a `Result::Err` variant if: +/// +/// * we are unable to deserialize the private key or encapsulated key +/// * there is an error in key decapsulation +/// * there is an error in decryption pub fn base_mode_open( config: &Config, private_key: &[u8], diff --git a/src/base_mode_seal.rs b/src/base_mode_seal.rs index a0c07722c7f..f251b3ce33d 100644 --- a/src/base_mode_seal.rs +++ b/src/base_mode_seal.rs @@ -1,21 +1,20 @@ -use crate::{from_bytes, Config, EncappedKeyAndCiphertext}; use hpke::{HpkeError, Serializable}; -/** -`base_mode_seal` provides an interface to [`hpke::single_shot_seal`] -that does not require compile time selection of an -algorithm. Instead, the selected algorithm is provided through the -[`Config`] passed as the first argument. - -# Errors - -This will return an `Result::Err` variant if: - -* we are unable to deserialize the recipient public key -* there is an error in key encapsultion -* there is an error in encryption +use crate::{from_bytes, Config, EncappedKeyAndCiphertext}; - */ +/// Single-shot HPKE ciphertext sealing. +/// +/// `base_mode_seal` provides an interface to [`hpke::single_shot_seal`] that does not require +/// compile time selection of an algorithm. Instead, the selected algorithm is provided through the +/// [`Config`] passed as the first argument. +/// +/// # Errors +/// +/// This will return an `Result::Err` variant if: +/// +/// * we are unable to deserialize the recipient public key +/// * there is an error in key encapsultion +/// * there is an error in encryption pub fn base_mode_seal( config: &Config, recipient_public_key: &[u8], diff --git a/src/ciphertext.rs b/src/ciphertext.rs index a6c791b25e9..1839d1b902e 100644 --- a/src/ciphertext.rs +++ b/src/ciphertext.rs @@ -1,13 +1,12 @@ -/** -a simple struct to return the combined encapsulated key -and ciphertext from seal -*/ +/// Encapsulated key and ciphertext. +/// +/// Obtained from [`crate::base_mode_seal::base_mode_seal`]. #[derive(Debug, Clone, PartialEq, Eq)] pub struct EncappedKeyAndCiphertext { - /// the encapsulated encryption key + /// The encapsulated encryption key pub encapped_key: Vec, - /// the ciphertext, encrypted with the key + /// The ciphertext, encrypted with the key pub ciphertext: Vec, } diff --git a/src/config.rs b/src/config.rs index 0e09237a8c0..1dccc78c3db 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,13 +1,14 @@ +use hpke::HpkeError; + use crate::{ base_mode_open, base_mode_seal, Aead, EncappedKeyAndCiphertext, IdLookupError, Kdf, Kem, }; -use hpke::HpkeError; -/** -Config is an open struct that contains an ([`Aead`], [`Kdf`], [`Kem`]) -algorithmic triple. This can be used with [`Config::base_mode_seal`], -[`Config::base_mode_open`], [`base_mode_seal`], or [`base_mode_open`]. -*/ +/// Configuration for crate interfaces. +/// +/// Contains an ([`Aead`], [`Kdf`], [`Kem`]) algorithmic triple. This can be used with +/// [`Config::base_mode_seal`], [`Config::base_mode_open`], [`base_mode_seal`], or +/// [`base_mode_open`]. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr( feature = "serde", @@ -15,7 +16,8 @@ algorithmic triple. This can be used with [`Config::base_mode_seal`], )] #[cfg_attr(feature = "serde", serde(crate = "serde_crate"))] pub struct Config { - /// the [authenticated encryption with additional data encryption function](crate::Aead) to be used + /// the [authenticated encryption with additional data encryption function](crate::Aead) to be + /// used pub aead: Aead, /// the [key derivation function](crate::Kdf) to be used pub kdf: Kdf, @@ -24,21 +26,19 @@ pub struct Config { } impl Config { - /** - base_mode_seal provides an interface to [`hpke::single_shot_seal`] that does - not require compile time selection of an algorithm. Instead, the - selected algorithm is provided through the [`Config`] that this - method is called on. - - # Errors - - This will return an `Result::Err` variant if: - - * we are unable to deserialize the recipient public key - * there is an error in key encapsultion - * there is an error in encryption - - */ + /// Single-shot HPKE ciphertext sealing. + /// + /// `base_mode_seal` provides an interface to [`hpke::single_shot_seal`] that does not require + /// compile time selection of an algorithm. Instead, the selected algorithm is provided through + /// the receiver. + /// + /// # Errors + /// + /// This will return a `Result::Err` variant if: + /// + /// * we are unable to deserialize the recipient public key + /// * there is an error in key encapsultion + /// * there is an error in encryption pub fn base_mode_seal( &self, recipient_public_key: &[u8], @@ -49,21 +49,19 @@ impl Config { base_mode_seal(self, recipient_public_key, info, plaintext, aad) } - /** - base_mode_open provides an interface to [`hpke::single_shot_open`] - that does not require compile time selection of an - algorithm. Instead, the selected algorithm is provided through the - [`Config`] that this method is called on. - - # Errors - - This will return an `Result::Err` variant if: - - * we are unable to deserialize the private key or encapsulated key - * there is an error in key decapsulation - * there is an error in decryption - - */ + /// Single-shot HPKE ciphertext opening. + /// + /// `base_mode_open` provides an interface to [`hpke::single_shot_open`] that does not require + /// compile time selection of an algorithm. Instead, the selected algorithm is provided through + /// the receiver + /// + /// # Errors + /// + /// This will return a `Result::Err` variant if: + /// + /// * we are unable to deserialize the private key or encapsulated key + /// * there is an error in key decapsulation + /// * there is an error in decryption pub fn base_mode_open( &self, private_key: &[u8], @@ -75,7 +73,11 @@ impl Config { base_mode_open(self, private_key, encapped_key, info, ciphertext, aad) } - /// Attempt to convert three u16 ids into a valid config. The id mappings are defined in the draft. + /// Attempt to convert three u16 ids into a valid [`Config`]. + /// + /// The ID mappings are defined in the [IANA HPKE registries][1]. + /// + /// [1]: https://www.iana.org/assignments/hpke/hpke.xhtml pub fn try_from_ids(aead_id: u16, kdf_id: u16, kem_id: u16) -> Result { Ok(Self { aead: aead_id.try_into().map_err(|_| IdLookupError("aead"))?, diff --git a/src/kdf.rs b/src/kdf.rs index 4d08f6c2468..90597705ce8 100644 --- a/src/kdf.rs +++ b/src/kdf.rs @@ -1,7 +1,9 @@ -use crate::IdLookupError; -use num_enum::TryFromPrimitive; use std::str::FromStr; +use num_enum::TryFromPrimitive; + +use crate::IdLookupError; + /// A key derivation function used in HPKE. /// /// Codepoints are defined in [RFC9180§7.2][1] and [draft-ietf-hpke-pq][2]. diff --git a/src/kem.rs b/src/kem.rs index 4fd18411855..f303236035f 100644 --- a/src/kem.rs +++ b/src/kem.rs @@ -1,7 +1,9 @@ -use crate::{IdLookupError, Keypair}; -use num_enum::TryFromPrimitive; use std::str::FromStr; +use num_enum::TryFromPrimitive; + +use crate::{IdLookupError, Keypair}; + /// An asymmetric key encapsulation mechanism. /// /// Codepoints are defined in [RFC9180§7.2][1] and [draft-ietf-hpke-pq][2]. diff --git a/src/keypair.rs b/src/keypair.rs index 405d60264af..2c4357bceb8 100644 --- a/src/keypair.rs +++ b/src/keypair.rs @@ -1,6 +1,7 @@ -use crate::Kem; use hpke::Serializable; +use crate::Kem; + /// An encoded keypair #[derive(Debug, Clone, Eq, PartialEq, zeroize::Zeroize)] pub struct Keypair { diff --git a/src/lib.rs b/src/lib.rs index 4f6e6b638ad..510c46081b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,9 +49,7 @@ pub use kdf::{Kdf, KDF_ALL}; mod kem; pub use kem::{Kem, KEM_ALL}; -/** -A simple error type for failed id lookups - */ +/// A simple error type for failed id lookups #[derive(Copy, Clone, Debug)] #[cfg_attr( feature = "serde", diff --git a/src/macros.rs b/src/macros.rs index 4da0f751758..b10eec5dd22 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,9 +29,21 @@ macro_rules! match_algo { #[cfg(feature = "shake")] $crate::Kdf::Shake256 => match_algo!(@kem, $aead, hpke::kdf::KdfShake256, $kem, $fn), #[cfg(feature = "shake")] - $crate::Kdf::TurboShake128 => match_algo!(@kem, $aead, hpke::kdf::KdfTurboShake128, $kem, $fn), + $crate::Kdf::TurboShake128 => match_algo!( + @kem, + $aead, + hpke::kdf::KdfTurboShake128, + $kem, + $fn + ), #[cfg(feature = "shake")] - $crate::Kdf::TurboShake256 => match_algo!(@kem, $aead, hpke::kdf::KdfTurboShake256, $kem, $fn), + $crate::Kdf::TurboShake256 => match_algo!( + @kem, + $aead, + hpke::kdf::KdfTurboShake256, + $kem, + $fn + ), } };