From 4b761ca8c2b8d363d5aedc13e4c605b3196f514e Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Wed, 25 Feb 2026 18:16:12 +0300 Subject: [PATCH 01/75] Update release dates for `crypto-common` v0.2.1, `digest` v0.11.1, andd `cipher` v0.5.1 (#2313) --- cipher/CHANGELOG.md | 2 +- crypto-common/CHANGELOG.md | 2 +- digest/CHANGELOG.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cipher/CHANGELOG.md b/cipher/CHANGELOG.md index 2913ca7d1..ad231ad14 100644 --- a/cipher/CHANGELOG.md +++ b/cipher/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.5.1 (UNRELEASED) +## 0.5.1 (2026-02-25) ### Changed - Block sizes no longer bounded by `crypto_common::BlockSizes` ([#2309]) - `StreamCipherCoreWrapper` is now bounded by `block_buffer::BlockSizes` diff --git a/crypto-common/CHANGELOG.md b/crypto-common/CHANGELOG.md index d9aa66404..7df555f28 100644 --- a/crypto-common/CHANGELOG.md +++ b/crypto-common/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.2.1 (UNRELEASED) +## 0.2.1 (2026-02-25) ### Changed - `BlockSizeUser::BlockSize` is no longer bounded by `BlockSizes` ([#2309]) diff --git a/digest/CHANGELOG.md b/digest/CHANGELOG.md index 420c54d71..141590c44 100644 --- a/digest/CHANGELOG.md +++ b/digest/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.11.1 (UNRELEASED) +## 0.11.1 (2026-02-25) ### Added - `SmallBlockSizeUser` helper trait. The trait is a sub-trait of `BlockSizeUser` with `BlockSize` bounded by `block_buffer::BlockSizes`. ([#2309]) From 3ffdc4eababb1a0454d441b08e6637e367762cee Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Wed, 25 Feb 2026 18:25:44 +0300 Subject: [PATCH 02/75] elliptic-curve: fix `clippy::unnecessary_safety_comment` lint (#2314) --- elliptic-curve/src/point/non_identity.rs | 3 ++- elliptic-curve/src/scalar/nonzero.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/elliptic-curve/src/point/non_identity.rs b/elliptic-curve/src/point/non_identity.rs index 4717ab32d..f6fee940d 100644 --- a/elliptic-curve/src/point/non_identity.rs +++ b/elliptic-curve/src/point/non_identity.rs @@ -23,7 +23,8 @@ use crate::{BatchNormalize, CurveArithmetic, CurveGroup, NonZeroScalar, Scalar}; /// In the context of ECC, it's useful for ensuring that certain arithmetic /// cannot result in the identity point. #[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(transparent)] // SAFETY: needed for `unsafe` safety invariants below +// `repr` is needed for `unsafe` safety invariants below +#[repr(transparent)] pub struct NonIdentity

{ point: P, } diff --git a/elliptic-curve/src/scalar/nonzero.rs b/elliptic-curve/src/scalar/nonzero.rs index 08811d486..d61065be8 100644 --- a/elliptic-curve/src/scalar/nonzero.rs +++ b/elliptic-curve/src/scalar/nonzero.rs @@ -33,7 +33,8 @@ use serdect::serde::{Deserialize, Serialize, de, ser}; /// In the context of ECC, it's useful for ensuring that scalar multiplication /// cannot result in the point at infinity. #[derive(Clone)] -#[repr(transparent)] // SAFETY: needed for `unsafe` safety invariants below +// `repr` is needed for `unsafe` safety invariants below +#[repr(transparent)] pub struct NonZeroScalar where C: CurveArithmetic, From 931a70d27cad7c434654e3e0ccf8f0696f896c42 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Wed, 25 Feb 2026 18:32:32 +0300 Subject: [PATCH 03/75] aead: bump `bytes` dependency to v1.11.1 (#2315) The lower versions are subject to [RUSTSEC-2026-0007], which results in a warning from deps.rs. [RUSTSEC-2026-0007]: https://rustsec.org/advisories/RUSTSEC-2026-0007.html --- aead/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aead/Cargo.toml b/aead/Cargo.toml index 9dc4772aa..c3937a96a 100644 --- a/aead/Cargo.toml +++ b/aead/Cargo.toml @@ -22,7 +22,7 @@ inout = "0.2.2" # optional dependencies arrayvec = { version = "0.7", optional = true, default-features = false } blobby = { version = "0.4", optional = true } -bytes = { version = "1", optional = true, default-features = false } +bytes = { version = "1.11.1", optional = true, default-features = false } [features] default = ["rand_core"] From b7a3bbfef1bea8fe765a9203c3956f997c9a43f9 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 26 Feb 2026 08:30:04 -0700 Subject: [PATCH 04/75] universal-hash: enable and fix workspace-level lints (#2318) Note: lint config was added in #2270 --- universal-hash/Cargo.toml | 3 +++ universal-hash/src/lib.rs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/universal-hash/Cargo.toml b/universal-hash/Cargo.toml index b9c1de234..975a9acc3 100644 --- a/universal-hash/Cargo.toml +++ b/universal-hash/Cargo.toml @@ -16,5 +16,8 @@ description = "Traits which describe the functionality of universal hash functio common = { version = "0.2", package = "crypto-common" } subtle = { version = "2.4", default-features = false } +[lints] +workspace = true + [package.metadata.docs.rs] all-features = true diff --git a/universal-hash/src/lib.rs b/universal-hash/src/lib.rs index 54ea65309..5de418770 100644 --- a/universal-hash/src/lib.rs +++ b/universal-hash/src/lib.rs @@ -129,6 +129,9 @@ pub trait UniversalHash: BlockSizeUser + Sized { /// /// This is useful when constructing Message Authentication Codes (MACs) /// from universal hash functions. + /// + /// # Errors + /// If the `expected` value does not match the computed one. #[inline] fn verify(self, expected: &Block) -> Result<(), Error> { if self.finalize().ct_eq(expected).into() { From f82c5c539c5d2bef4578b8623808ca7eb0bd655a Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:16:50 +0100 Subject: [PATCH 05/75] crypto-common: note in changelog that 0.2.0 was yanked (#2321) --- crypto-common/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto-common/CHANGELOG.md b/crypto-common/CHANGELOG.md index 7df555f28..f3ec08886 100644 --- a/crypto-common/CHANGELOG.md +++ b/crypto-common/CHANGELOG.md @@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#2309]: https://github.com/RustCrypto/traits/pull/2309 -## 0.2.0 (2026-02-04) +## 0.2.0 (2026-02-04) [YANKED] ### Added - Sealed `BlockSizes` trait implemented for types from `U1` to `U255` ([#1172]) - `SerializableState` trait under `hazmat` module ([#1369]) From b97b79f5af0f4b3157b51478754416a211780f6d Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 27 Feb 2026 17:41:41 +0300 Subject: [PATCH 06/75] Release `universal-hash` v0.6.0 (#2317) ### Changed - Edition changed to 2024 and MSRV bumped to 1.85 ([#1759]) - Replaced `generic-array` with `hybrid-array` ([#1385]) - Bump `crypto-common` dependency to v0.2 ([#1385]) - Re-export of `crypto-common` moved to `universal_hash::common` ([#2237]) [#1385]: https://github.com/RustCrypto/traits/pull/1385 [#1759]: https://github.com/RustCrypto/traits/pull/1759 [#2237]: https://github.com/RustCrypto/traits/pull/2237 --- Cargo.lock | 20 +++++++------------- universal-hash/CHANGELOG.md | 26 +++----------------------- universal-hash/Cargo.toml | 2 +- 3 files changed, 11 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d44b956f..103c1337b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "addchain" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" +checksum = "2e33f6a175ec6a9e0aca777567f9ff7c3deefc255660df887e7fa3585e9801d8" dependencies = [ "num-bigint", "num-integer", @@ -733,7 +733,7 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" -version = "0.6.0-rc.10" +version = "0.6.0" dependencies = [ "crypto-common", "subtle", @@ -741,11 +741,11 @@ dependencies = [ [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "wit-bindgen 0.46.0", + "wit-bindgen", ] [[package]] @@ -754,7 +754,7 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] @@ -791,12 +791,6 @@ dependencies = [ "semver", ] -[[package]] -name = "wit-bindgen" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" - [[package]] name = "wit-bindgen" version = "0.51.0" diff --git a/universal-hash/CHANGELOG.md b/universal-hash/CHANGELOG.md index e760936d6..afdafc5aa 100644 --- a/universal-hash/CHANGELOG.md +++ b/universal-hash/CHANGELOG.md @@ -5,34 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.6.0 (UNRELEASED) +## 0.6.0 (2026-02-27) ### Changed - Edition changed to 2024 and MSRV bumped to 1.85 ([#1759]) -- Migrate to `doc_auto_cfg` ([#1370]) -- Exclude pre-1.60 crates from workspace ([#1380]) -- bump crypto-common to v0.2.0-pre; MSRV 1.65 ([#1385]) -- bump crypto-common to v0.2.0-pre.1 ([#1433]) -- bump crypto-common to v0.2.0-pre.2 ([#1436]) -- Bump `hybrid-array` to v0.2.0-pre.8 ([#1438]) -- Bump `crypto-common` and `hybrid-array` ([#1469]) -- Bump `hybrid-array` to v0.2.0-rc.4 ([#1493]) -- Bump `crypto-common` to v0.2.0-pre.5 ([#1496]) +- Replaced `generic-array` with `hybrid-array` ([#1385]) +- Bump `crypto-common` dependency to v0.2 ([#1385]) - Re-export of `crypto-common` moved to `universal_hash::common` ([#2237]) - -### Fixed -- Fix `missing_debug_implementations` for some crates ([#1407]) - -[#1370]: https://github.com/RustCrypto/traits/pull/1370 -[#1380]: https://github.com/RustCrypto/traits/pull/1380 [#1385]: https://github.com/RustCrypto/traits/pull/1385 -[#1407]: https://github.com/RustCrypto/traits/pull/1407 -[#1433]: https://github.com/RustCrypto/traits/pull/1433 -[#1436]: https://github.com/RustCrypto/traits/pull/1436 -[#1438]: https://github.com/RustCrypto/traits/pull/1438 -[#1469]: https://github.com/RustCrypto/traits/pull/1469 -[#1493]: https://github.com/RustCrypto/traits/pull/1493 -[#1496]: https://github.com/RustCrypto/traits/pull/1496 [#1759]: https://github.com/RustCrypto/traits/pull/1759 [#2237]: https://github.com/RustCrypto/traits/pull/2237 diff --git a/universal-hash/Cargo.toml b/universal-hash/Cargo.toml index 975a9acc3..ccf7c1e1e 100644 --- a/universal-hash/Cargo.toml +++ b/universal-hash/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "universal-hash" -version = "0.6.0-rc.10" +version = "0.6.0" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" From d2ea52c7ef6d9c69c25141c53beb37109cc03417 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 27 Feb 2026 18:29:44 +0300 Subject: [PATCH 07/75] Remove `async-signature` (#2323) --- README.md | 6 +++--- async-signature/README.md | 8 -------- 2 files changed, 3 insertions(+), 11 deletions(-) delete mode 100644 async-signature/README.md diff --git a/README.md b/README.md index 89ffebebf..43ae3f406 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # RustCrypto: Traits -[![Project Chat][chat-image]][chat-link] ![Apache2/MIT licensed][license-image] [![dependency status][deps-image]][deps-link] +[![Project Chat][chat-image]][chat-link] +![Apache2/MIT licensed][license-image] +[![dependency status][deps-image]][deps-link] Collection of traits which describe functionality of cryptographic primitives. @@ -9,7 +11,6 @@ Collection of traits which describe functionality of cryptographic primitives. | Name | Algorithm | Crates.io | Docs | MSRV | |---------------------|-----------|:---------:|:-----:|:----:| | [`aead`] | [Authenticated encryption] | [![crates.io](https://img.shields.io/crates/v/aead.svg)](https://crates.io/crates/aead) | [![Documentation](https://docs.rs/aead/badge.svg)](https://docs.rs/aead) | ![MSRV 1.85][msrv-1.85] | -| [`async‑signature`] | [Digital signature] | [![crates.io](https://img.shields.io/crates/v/async-signature.svg)](https://crates.io/crates/async-signature) | [![Documentation](https://docs.rs/async-signature/badge.svg)](https://docs.rs/async-signature) | ![MSRV 1.85][msrv-1.85] | | [`cipher`] | [Block] and [stream cipher] | [![crates.io](https://img.shields.io/crates/v/cipher.svg)](https://crates.io/crates/cipher) | [![Documentation](https://docs.rs/cipher/badge.svg)](https://docs.rs/cipher) | ![MSRV 1.85][msrv-1.85] | | [`crypto‑common`] | Common cryptographic traits | [![crates.io](https://img.shields.io/crates/v/crypto-common.svg)](https://crates.io/crates/crypto-common) | [![Documentation](https://docs.rs/crypto-common/badge.svg)](https://docs.rs/crypto-common) | ![MSRV 1.85][msrv-1.85] | | [`digest`] | [Cryptographic hash function] | [![crates.io](https://img.shields.io/crates/v/digest.svg)](https://crates.io/crates/digest) | [![Documentation](https://docs.rs/digest/badge.svg)](https://docs.rs/digest) | ![MSRV 1.85][msrv-1.85] | @@ -50,7 +51,6 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [//]: # (crates) [`aead`]: ./aead -[`async‑signature`]: ./signature/async [`cipher`]: ./cipher [`crypto‑common`]: ./crypto-common [`crypto`]: ./crypto diff --git a/async-signature/README.md b/async-signature/README.md deleted file mode 100644 index 5011c81d7..000000000 --- a/async-signature/README.md +++ /dev/null @@ -1,8 +0,0 @@ -## 🚨 DEPRECATED! 🚨 - -The `async-signature` crate is deprecated and will not receive further releases. - -The relevant functionality has been merged into the `signature` crate: - - - From 37ae13c883aea527cc4f06fecbdff2f79fbdc776 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 27 Feb 2026 08:43:56 -0700 Subject: [PATCH 08/75] universal-hash: replace `subtle` with `ctutils` (#2324) See #2275 --- Cargo.lock | 2 +- universal-hash/Cargo.toml | 2 +- universal-hash/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 103c1337b..9c8e7871f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -736,7 +736,7 @@ name = "universal-hash" version = "0.6.0" dependencies = [ "crypto-common", - "subtle", + "ctutils", ] [[package]] diff --git a/universal-hash/Cargo.toml b/universal-hash/Cargo.toml index ccf7c1e1e..f04729ed0 100644 --- a/universal-hash/Cargo.toml +++ b/universal-hash/Cargo.toml @@ -13,8 +13,8 @@ categories = ["cryptography", "no-std"] description = "Traits which describe the functionality of universal hash functions (UHFs)" [dependencies] +ctutils = "0.4" common = { version = "0.2", package = "crypto-common" } -subtle = { version = "2.4", default-features = false } [lints] workspace = true diff --git a/universal-hash/src/lib.rs b/universal-hash/src/lib.rs index 5de418770..02c27b053 100644 --- a/universal-hash/src/lib.rs +++ b/universal-hash/src/lib.rs @@ -18,7 +18,7 @@ use common::{ array::{Array, ArraySize}, }; use core::slice; -use subtle::ConstantTimeEq; +use ctutils::CtEq; use typenum::Unsigned; /// Trait implemented by UHF backends. From 82279a5a9ff2af5f10194b9147fe60050cda1851 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 27 Feb 2026 09:04:52 -0700 Subject: [PATCH 09/75] universal-hash v0.6.1 (#2326) ## Changed - Replaced `subtle` with `ctutils` (#2324) --- Cargo.lock | 2 +- universal-hash/CHANGELOG.md | 6 ++++++ universal-hash/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c8e7871f..cdfb158f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -733,7 +733,7 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" -version = "0.6.0" +version = "0.6.1" dependencies = [ "crypto-common", "ctutils", diff --git a/universal-hash/CHANGELOG.md b/universal-hash/CHANGELOG.md index afdafc5aa..b0a228d55 100644 --- a/universal-hash/CHANGELOG.md +++ b/universal-hash/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.6.1 (2026-02-27) +### Changed +- Replaced `subtle` with `ctutils` ([#2324]) + +[#2324]: https://github.com/RustCrypto/traits/pull/2324 + ## 0.6.0 (2026-02-27) ### Changed - Edition changed to 2024 and MSRV bumped to 1.85 ([#1759]) diff --git a/universal-hash/Cargo.toml b/universal-hash/Cargo.toml index f04729ed0..87097f64d 100644 --- a/universal-hash/Cargo.toml +++ b/universal-hash/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "universal-hash" -version = "0.6.0" +version = "0.6.1" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" From 5ac6e7c8c068c798e1012d7f837f52af565bb33e Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 27 Feb 2026 19:26:08 +0300 Subject: [PATCH 10/75] Add notes for yanked crate versions (#2325) --- cipher/CHANGELOG.md | 3 +++ crypto-common/CHANGELOG.md | 3 +++ digest/CHANGELOG.md | 3 +++ 3 files changed, 9 insertions(+) diff --git a/cipher/CHANGELOG.md b/cipher/CHANGELOG.md index ad231ad14..2622244b5 100644 --- a/cipher/CHANGELOG.md +++ b/cipher/CHANGELOG.md @@ -19,6 +19,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#2309]: https://github.com/RustCrypto/traits/pull/2309 ## 0.5.0 (2026-02-04) [YANKED] +Note: this version was yanked because v0.5.1 introduces breaking changes. +Users should migrate to `cipher` v0.5.1 and `crypto-common` v0.2.1 using `cargo update`. + ### Added - Traits for tweakable block ciphers ([#1721]) - Methods for writing keystream ([#1907]) diff --git a/crypto-common/CHANGELOG.md b/crypto-common/CHANGELOG.md index f3ec08886..f40183052 100644 --- a/crypto-common/CHANGELOG.md +++ b/crypto-common/CHANGELOG.md @@ -15,6 +15,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#2309]: https://github.com/RustCrypto/traits/pull/2309 ## 0.2.0 (2026-02-04) [YANKED] +Note: this version was yanked because v0.2.1 introduces breaking changes. +Users should migrate to v0.2.1 using `cargo update`. + ### Added - Sealed `BlockSizes` trait implemented for types from `U1` to `U255` ([#1172]) - `SerializableState` trait under `hazmat` module ([#1369]) diff --git a/digest/CHANGELOG.md b/digest/CHANGELOG.md index 141590c44..314c7f187 100644 --- a/digest/CHANGELOG.md +++ b/digest/CHANGELOG.md @@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#2309]: https://github.com/RustCrypto/traits/pull/2309 ## 0.11.0 (2026-02-13) [YANKED] +Note: this version was yanked because v0.11.1 introduces breaking changes. +Users should migrate to `digest` v0.11.1 and `crypto-common` v0.2.1 using `cargo update`. + ### Added - `CustomizedInit` trait ([#1334]) - `SerializableState` support ([#1369]) From 86ae5c7cd5a6729a0b3c85c176d08467941d3fe8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Mar 2026 03:01:49 +0300 Subject: [PATCH 11/75] ci: bump crate-ci/typos from 1.43.1 to 1.44.0 (#2327) --- .github/workflows/workspace.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index 51fe8ce8b..062506f40 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -56,7 +56,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - uses: crate-ci/typos@v1.43.1 + - uses: crate-ci/typos@v1.44.0 lock: name: Check Cargo.lock From a510d997f84ff9d764c3a0237c3c406dbedd1936 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Mar 2026 07:19:46 -0700 Subject: [PATCH 12/75] build(deps): bump crypto-bigint from 0.7.0-rc.27 to 0.7.0-rc.28 in the all-deps group (#2328) --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cdfb158f6..0b8548848 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,9 +170,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.7.0-rc.27" +version = "0.7.0-rc.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b43308b9b6a47554f4612d5b1fb95ff935040aa3927dd42b1d6cbc015a262d96" +checksum = "96dacf199529fb801ae62a9aafdc01b189e9504c0d1ee1512a4c16bcd8666a93" dependencies = [ "cpubits", "ctutils", From 464b5edea27ad0d354c354bd7ee08eb4b1c90bde Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 8 Mar 2026 13:38:17 -0600 Subject: [PATCH 13/75] elliptic-curve: bump `crypto-bigint` to v0.7 final release (#2330) Release PR: RustCrypto/crypto-bigint#1218 --- Cargo.lock | 4 ++-- elliptic-curve/Cargo.toml | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b8548848..f070b146c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,9 +170,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.7.0-rc.28" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96dacf199529fb801ae62a9aafdc01b189e9504c0d1ee1512a4c16bcd8666a93" +checksum = "4f438b626cb7c9dd48a613a9826e6bad9db71097f9d628f7237af2f6bc13c0ec" dependencies = [ "cpubits", "ctutils", diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index d3b48ddb7..81590521a 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -16,14 +16,9 @@ and traits for representing various elliptic curve forms, scalars, points, and public/secret keys composed thereof. """ -[dependencies.bigint] -package = "crypto-bigint" -version = "0.7.0-rc.27" -default-features = false -features = ["hybrid-array", "rand_core", "subtle", "zeroize"] - [dependencies] array = { package = "hybrid-array", version = "0.4", default-features = false, features = ["zeroize"] } +bigint = { package = "crypto-bigint", version = "0.7", default-features = false, features = ["hybrid-array", "rand_core", "subtle", "zeroize"] } base16ct = "1" common = { package = "crypto-common", version = "0.2", features = ["rand_core"] } rand_core = { version = "0.10", default-features = false } From efe6df2d250bd69724d471fe0c26d232e2768c2a Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 8 Mar 2026 13:55:52 -0600 Subject: [PATCH 14/75] elliptic-curve: bump `digest` requirement to v0.11 (#2331) Release PR: #2300 --- elliptic-curve/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index 81590521a..994ab2266 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -26,7 +26,7 @@ subtle = { version = "2.6", default-features = false } zeroize = { version = "1.7", default-features = false } # optional dependencies -digest = { version = "0.11.0-rc.11", optional = true } +digest = { version = "0.11", optional = true } ff = { version = "0.14.0-rc.0", package = "rustcrypto-ff", optional = true, default-features = false } group = { version = "0.14.0-rc.0", package = "rustcrypto-group", optional = true, default-features = false } hkdf = { version = "0.13.0-rc.5", optional = true, default-features = false } From 42f8110b60130ee04605f866ed8b75caec980829 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 9 Mar 2026 16:14:48 -0600 Subject: [PATCH 15/75] password-hash: bump `phc` dependency to v0.6 (#2332) Release PR: RustCrypto/formats#2255 --- Cargo.lock | 6 +++--- password-hash/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f070b146c..9eddf7866 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -467,14 +467,14 @@ dependencies = [ [[package]] name = "phc" -version = "0.6.0-rc.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d390c5fe8d102c2c18ff39f1e72b9ad5996de282c2d831b0312f56910f5508" +checksum = "44dc769b75f93afdddd8c7fa12d685292ddeff1e66f7f0f3a234cf1818afe892" dependencies = [ "base64ct", + "ctutils", "getrandom", "rand_core", - "subtle", ] [[package]] diff --git a/password-hash/Cargo.toml b/password-hash/Cargo.toml index 2b06ca67f..0793e91d4 100644 --- a/password-hash/Cargo.toml +++ b/password-hash/Cargo.toml @@ -18,7 +18,7 @@ formats (e.g. Modular Crypt Format) [dependencies] getrandom = { version = "0.4", optional = true, default-features = false } -phc = { version = "0.6.0-rc.1", optional = true, default-features = false } +phc = { version = "0.6", optional = true, default-features = false } rand_core = { version = "0.10", optional = true, default-features = false } [features] From 604171bdd8d123356a2897488e573435ff37a555 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 9 Mar 2026 16:34:18 -0600 Subject: [PATCH 16/75] password-hash: enable and fix workspace-level lints (#2333) Note: lint config was added in #2270 --- password-hash/Cargo.toml | 3 ++ password-hash/src/lib.rs | 53 +++++++++++++++++++++++++++++++---- password-hash/tests/traits.rs | 3 +- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/password-hash/Cargo.toml b/password-hash/Cargo.toml index 0793e91d4..38ba951b8 100644 --- a/password-hash/Cargo.toml +++ b/password-hash/Cargo.toml @@ -26,5 +26,8 @@ alloc = ["phc?/alloc"] getrandom = ["dep:getrandom", "phc?/getrandom"] rand_core = ["dep:rand_core", "phc?/rand_core"] +[lints] +workspace = true + [package.metadata.docs.rs] all-features = true diff --git a/password-hash/src/lib.rs b/password-hash/src/lib.rs index 2a2bfdf63..adde8fde8 100644 --- a/password-hash/src/lib.rs +++ b/password-hash/src/lib.rs @@ -86,12 +86,23 @@ pub trait PasswordHasher { /// /// The salt should be unique per password. When in doubt, use [`PasswordHasher::hash_password`] /// which will choose the salt for you. + /// + /// # Errors + /// These will vary by algorithm/implementation of this trait, but may be due to: + /// - length restrictions on the password and/or salt + /// - algorithm-specific internal error fn hash_password_with_salt(&self, password: &[u8], salt: &[u8]) -> Result; /// Compute the hash `H` from the given password, potentially using configuration stored in /// `&self` for the parameters, or otherwise the recommended defaults. /// /// A large random salt will be generated automatically. + /// + /// # Errors + /// These will vary by algorithm/implementation of this trait, but may be due to: + /// - length restrictions on the password + /// - algorithm-specific internal error + /// - RNG internal error #[cfg(feature = "getrandom")] fn hash_password(&self, password: &[u8]) -> Result { let salt = try_generate_salt()?; @@ -102,6 +113,12 @@ pub trait PasswordHasher { /// `&self` for the parameters, or otherwise the recommended defaults. /// /// A large random salt will be generated automatically from the provided RNG. + /// + /// # Errors + /// These will vary by algorithm/implementation of this trait, but may be due to: + /// - length restrictions on the password + /// - algorithm-specific internal error + /// - RNG internal error #[cfg(feature = "rand_core")] fn hash_password_with_rng( &self, @@ -121,11 +138,15 @@ pub trait CustomizedPasswordHasher { /// Algorithm-specific parameters. type Params: Clone + Debug + Default; - /// Compute a [`PasswordHash`] from the provided password using an - /// explicit set of customized algorithm parameters as opposed to the - /// defaults. + /// Compute a [`PasswordHash`] from the provided password using an explicit set of customized + /// algorithm parameters as opposed to the defaults. /// /// When in doubt, use [`PasswordHasher::hash_password`] instead. + /// + /// # Errors + /// These will vary by algorithm/implementation of this trait, but may be due to: + /// - length restrictions on the password and/or salt + /// - algorithm-specific params or internal error fn hash_password_customized( &self, password: &[u8], @@ -137,6 +158,11 @@ pub trait CustomizedPasswordHasher { /// Compute a [`PasswordHash`] using customized parameters only, using the default /// algorithm and version. + /// + /// # Errors + /// These will vary by algorithm/implementation of this trait, but may be due to: + /// - length restrictions on the password and/or salt + /// - algorithm-specific params or internal error fn hash_password_with_params( &self, password: &[u8], @@ -156,9 +182,14 @@ pub trait CustomizedPasswordHasher { /// This trait is object safe and can be used to implement abstractions over /// multiple password hashing algorithms. pub trait PasswordVerifier { - /// Compute this password hashing function against the provided password - /// using the parameters from the provided password hash and see if the - /// computed output matches. + /// Compute this password hashing function against the provided password using the parameters + /// from the provided password hash and see if the computed output matches. + /// + /// # Errors + /// - Returns `Error::Algorithm` if the algorithm being requested by the hash `H` is unsupported + /// - Returns `Error::PasswordInvalid` if the hash for the supplied password does not match + /// the provided hash + /// - May return other algorithm-specific errors fn verify_password(&self, password: &[u8], hash: &H) -> Result<()>; } @@ -207,17 +238,27 @@ pub trait McfHasher { /// /// MCF hashes are otherwise largely unstructured and parsed according to /// algorithm-specific rules so hashers must parse a raw string themselves. + /// + /// # Errors + /// Returns errors if the the hash couldn't be converted fn upgrade_mcf_hash(&self, hash: &str) -> Result; } /// Generate a random salt value of the recommended length using the system's secure RNG. +/// +/// # Panics +/// If the system's secure RNG experiences an internal failure. #[cfg(feature = "getrandom")] +#[must_use] pub fn generate_salt() -> [u8; RECOMMENDED_SALT_LEN] { try_generate_salt().expect("RNG failure") } /// Try generating a random salt value of the recommended length using the system's secure RNG, /// returning errors if they occur. +/// +/// # Errors +/// If the system's secure RNG experiences an internal failure. #[cfg(feature = "getrandom")] pub fn try_generate_salt() -> core::result::Result<[u8; RECOMMENDED_SALT_LEN], getrandom::Error> { let mut salt = [0u8; RECOMMENDED_SALT_LEN]; diff --git a/password-hash/tests/traits.rs b/password-hash/tests/traits.rs index dd5e24062..4bc17ce46 100644 --- a/password-hash/tests/traits.rs +++ b/password-hash/tests/traits.rs @@ -1,6 +1,7 @@ //! Password hashing tests #![cfg(feature = "phc")] +#![allow(missing_copy_implementations, missing_debug_implementations)] use core::{fmt::Display, str::FromStr}; use password_hash::{CustomizedPasswordHasher, Error, PasswordHasher, Result}; @@ -58,7 +59,7 @@ impl PasswordHasher for StubPasswordHasher { pub struct StubParams; impl Display for StubParams { - fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, _: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { Ok(()) } } From 35e0e9ab4a9c8d79ae256f41ccb167e8405a50ba Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 9 Mar 2026 16:54:18 -0600 Subject: [PATCH 17/75] password-hash: remove `McfHasher` trait (#2334) The crate is now generic around password hash string formats, so having an MCF-specific trait like this doesn't make sense. The functionality for upgrading MCF hashes to PHC hashes using algorithm-specific rules is worth retaining, but we can probably move this trait or add a similarly shaped one to e.g. the `mcf` crate which is better equipped to deal with MCF-specific concerns. --- password-hash/src/lib.rs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/password-hash/src/lib.rs b/password-hash/src/lib.rs index adde8fde8..c24f8ec8b 100644 --- a/password-hash/src/lib.rs +++ b/password-hash/src/lib.rs @@ -224,26 +224,6 @@ where } } -/// Trait for password hashing algorithms which support the legacy -/// [Modular Crypt Format (MCF)][MCF]. -/// -/// [MCF]: https://passlib.readthedocs.io/en/stable/modular_crypt_format.html -#[cfg(feature = "phc")] -pub trait McfHasher { - /// Upgrade an MCF hash to a PHC hash. MCF follow this rough format: - /// - /// ```text - /// $$ - /// ``` - /// - /// MCF hashes are otherwise largely unstructured and parsed according to - /// algorithm-specific rules so hashers must parse a raw string themselves. - /// - /// # Errors - /// Returns errors if the the hash couldn't be converted - fn upgrade_mcf_hash(&self, hash: &str) -> Result; -} - /// Generate a random salt value of the recommended length using the system's secure RNG. /// /// # Panics From ae7d4bee2aebed8c7f1a2dcae82db37ab02b3714 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 9 Mar 2026 17:18:17 -0600 Subject: [PATCH 18/75] password-hash: rustdoc fixups (#2336) --- password-hash/src/lib.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/password-hash/src/lib.rs b/password-hash/src/lib.rs index c24f8ec8b..98b9ed97b 100644 --- a/password-hash/src/lib.rs +++ b/password-hash/src/lib.rs @@ -133,12 +133,12 @@ pub trait PasswordHasher { /// Trait for password hashing functions which support customization. /// -/// Generic around a password hash to be returned (typically [`PasswordHash`]) +/// Generic around a password hash to be returned (typically [`phc::PasswordHash`]). pub trait CustomizedPasswordHasher { /// Algorithm-specific parameters. type Params: Clone + Debug + Default; - /// Compute a [`PasswordHash`] from the provided password using an explicit set of customized + /// Compute a password hash from the provided password using an explicit set of customized /// algorithm parameters as opposed to the defaults. /// /// When in doubt, use [`PasswordHasher::hash_password`] instead. @@ -156,8 +156,8 @@ pub trait CustomizedPasswordHasher { params: Self::Params, ) -> Result; - /// Compute a [`PasswordHash`] using customized parameters only, using the default - /// algorithm and version. + /// Compute a password hash using customized parameters only, using the default algorithm and + /// version. /// /// # Errors /// These will vary by algorithm/implementation of this trait, but may be due to: @@ -175,20 +175,20 @@ pub trait CustomizedPasswordHasher { /// Trait for password verification. /// -/// Generic around a password hash to be returned (typically [`phc::PasswordHash`]) +/// Generic around a password hash to be returned (typically [`phc::PasswordHash`]). /// /// Automatically impl'd for type that impl [`PasswordHasher`] with [`phc::PasswordHash`] as `H`. /// -/// This trait is object safe and can be used to implement abstractions over -/// multiple password hashing algorithms. +/// This trait is object safe and can be used to implement abstractions over multiple password +/// hashing algorithms. pub trait PasswordVerifier { /// Compute this password hashing function against the provided password using the parameters /// from the provided password hash and see if the computed output matches. /// /// # Errors - /// - Returns `Error::Algorithm` if the algorithm being requested by the hash `H` is unsupported - /// - Returns `Error::PasswordInvalid` if the hash for the supplied password does not match - /// the provided hash + /// - Returns [`Error::Algorithm`] if the algorithm requested by the hash `H` is unsupported + /// - Returns [`Error::PasswordInvalid`] if the computed hash for the supplied password does not + /// match the expected hash /// - May return other algorithm-specific errors fn verify_password(&self, password: &[u8], hash: &H) -> Result<()>; } From 4c2365ee72dbf3d279be60fda8ab6a46072410ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:21:25 -0600 Subject: [PATCH 19/75] build(deps): bump the all-deps group with 4 updates (#2335) --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9eddf7866..b5f2fc3ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -270,9 +270,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "getrandom" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", @@ -329,9 +329,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b229d73f5803b562cc26e4da0396c8610a4ee209f4fac8fa4f8d709166dc45" +checksum = "8655f91cd07f2b9d0c24137bd650fe69617773435ee5ec83022377777ce65ef1" dependencies = [ "subtle", "typenum", @@ -392,9 +392,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.182" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "log" @@ -523,9 +523,9 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.3.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "radium" From 866ef69a45640fbc206f6d76caed0a173428f9d4 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 9 Mar 2026 17:21:56 -0600 Subject: [PATCH 20/75] password-hash: add `Error::RngFailure` (#2337) Fixes a TODO by adding a specific error variant for RNG failures --- password-hash/src/error.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/password-hash/src/error.rs b/password-hash/src/error.rs index eb290b8ad..d807c2510 100644 --- a/password-hash/src/error.rs +++ b/password-hash/src/error.rs @@ -39,6 +39,9 @@ pub enum Error { /// Invalid password. PasswordInvalid, + /// Random number generator failure. + RngFailure, + /// Invalid salt. SaltInvalid, @@ -58,6 +61,7 @@ impl fmt::Display for Error { Self::ParamInvalid { name } => write!(f, "invalid parameter: {name:?}"), Self::ParamsInvalid => write!(f, "invalid parameters"), Self::PasswordInvalid => write!(f, "invalid password"), + Self::RngFailure => write!(f, "rng failure"), Self::SaltInvalid => write!(f, "invalid salt"), Self::Version => write!(f, "invalid algorithm version"), } @@ -69,8 +73,7 @@ impl core::error::Error for Error {} #[cfg(feature = "getrandom")] impl From for Error { fn from(_: getrandom::Error) -> Self { - // TODO(tarcieri): should we have a specific variant for RNGs errors? - Error::Crypto + Error::RngFailure } } From 01b44a63246728af4318588c63233709c55f7106 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 9 Mar 2026 18:33:13 -0600 Subject: [PATCH 21/75] password-hash v0.6.0 (#2338) ## Added - Generic `H` param to traits to support multiple string formats e.g. PHC, MCF (#2110) - Implement `From` for `Error` (#2124) - `rand_core` feature (#2126) - Salt generating helper functions `(try_)generate_salt` (#2128) - `Error::RngFailure` variant (#2337) ## Changed - Edition changed to 2024 and MSRV bumped to 1.85 (#1759) - Extract `CustomizedPasswordHasher` trait (#2105) - Bump `getrandom` to v0.4 (#2258) ## Removed - `Encoding` enum (#2102) - PHC types moved to the `phc` crate, which is re-exported as `password_hash::phc` when the `phc` crate feature is enabled (#2103, #2116): - `Ident` - `Output` - `ParamsString` - `PasswordHash` - `PasswordHashString` - `Salt` - `SaltString` - `Value` - `McfHasher` trait (#2334) --- Cargo.lock | 2 +- password-hash/CHANGELOG.md | 36 +++++++++++++++++++++++++++++++++--- password-hash/Cargo.toml | 4 ++-- password-hash/LICENSE-MIT | 2 +- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b5f2fc3ce..a33486e08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -449,7 +449,7 @@ dependencies = [ [[package]] name = "password-hash" -version = "0.6.0-rc.12" +version = "0.6.0" dependencies = [ "getrandom", "phc", diff --git a/password-hash/CHANGELOG.md b/password-hash/CHANGELOG.md index b7898ad59..1cc235314 100644 --- a/password-hash/CHANGELOG.md +++ b/password-hash/CHANGELOG.md @@ -5,15 +5,45 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.6.0 (UNRELEASED) +## 0.6.0 (2026-03-10) +### Added +- Generic `H` param to traits to support multiple string formats e.g. PHC, MCF ([#2110]) +- Implement `From` for `Error` ([#2124]) +- `rand_core` feature ([#2126]) +- Salt generating helper functions `(try_)generate_salt` ([#2128]) +- `Error::RngFailure` variant ([#2337]) + ### Changed - Edition changed to 2024 and MSRV bumped to 1.85 ([#1759]) -- Bump `rand_core` to v0.10 ([#2250]) +- Extract `CustomizedPasswordHasher` trait ([#2105]) - Bump `getrandom` to v0.4 ([#2258]) +### Removed +- `Encoding` enum ([#2102]) +- PHC types moved to the `phc` crate, which is re-exported as `password_hash::phc` when the `phc` + crate feature is enabled ([#2103], [#2116]): + - `Ident` + - `Output` + - `ParamsString` + - `PasswordHash` + - `PasswordHashString` + - `Salt` + - `SaltString` + - `Value` +- `McfHasher` trait ([#2334]) + [#1759]: https://github.com/RustCrypto/traits/pull/1759 -[#2250]: https://github.com/RustCrypto/traits/pull/2250 +[#2102]: https://github.com/RustCrypto/traits/pull/2102 +[#2103]: https://github.com/RustCrypto/traits/pull/2103 +[#2105]: https://github.com/RustCrypto/traits/pull/2105 +[#2110]: https://github.com/RustCrypto/traits/pull/2110 +[#2116]: https://github.com/RustCrypto/traits/pull/2116 +[#2124]: https://github.com/RustCrypto/traits/pull/2124 +[#2126]: https://github.com/RustCrypto/traits/pull/2126 +[#2128]: https://github.com/RustCrypto/traits/pull/2128 [#2258]: https://github.com/RustCrypto/traits/pull/2258 +[#2334]: https://github.com/RustCrypto/traits/pull/2334 +[#2337]: https://github.com/RustCrypto/traits/pull/2337 ## 0.5.0 (2023-03-04) ### Added diff --git a/password-hash/Cargo.toml b/password-hash/Cargo.toml index 38ba951b8..478fb69f9 100644 --- a/password-hash/Cargo.toml +++ b/password-hash/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "password-hash" -version = "0.6.0-rc.12" +version = "0.6.0" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" @@ -12,7 +12,7 @@ categories = ["authentication", "cryptography", "no-std"] keywords = ["crypt", "mcf", "password", "pbkdf", "phc"] description = """ Traits which describe the functionality of password hashing algorithms, with optional support for a -`no_std`-friendly implementation of the PHC string format, as well as generic support for other +`no_std`/`no_alloc`-friendly implementation of the PHC string format, as well as generic support for other formats (e.g. Modular Crypt Format) """ diff --git a/password-hash/LICENSE-MIT b/password-hash/LICENSE-MIT index b723e3eee..ede6f74f2 100644 --- a/password-hash/LICENSE-MIT +++ b/password-hash/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2020-2025 RustCrypto Developers +Copyright (c) 2020-2026 RustCrypto Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated From a250cbd123625097feaab33d479ab10381c88775 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 10 Mar 2026 10:58:50 -0600 Subject: [PATCH 22/75] elliptic-curve: bump `sec1` to v0.8 (#2339) Release PR: RustCrypto/formats#2259 --- Cargo.lock | 4 ++-- elliptic-curve/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a33486e08..04e120bbb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -579,9 +579,9 @@ dependencies = [ [[package]] name = "sec1" -version = "0.8.0-rc.13" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2400ed44a13193820aa528a19f376c3843141a8ce96ff34b11104cc79763f2" +checksum = "f46b9a5ab87780a3189a1d704766579517a04ad59de653b7aad7d38e8a15f7dc" dependencies = [ "base16ct", "ctutils", diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index 994ab2266..a327584db 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -34,7 +34,7 @@ hex-literal = { version = "1", optional = true } once_cell = { version = "1.21", optional = true, default-features = false } pem-rfc7468 = { version = "1", optional = true, features = ["alloc"] } pkcs8 = { version = "0.11.0-rc.10", optional = true, default-features = false } -sec1 = { version = "0.8.0-rc.13", optional = true, features = ["ctutils", "subtle", "zeroize"] } +sec1 = { version = "0.8", optional = true, features = ["ctutils", "subtle", "zeroize"] } serdect = { version = "0.4", optional = true, default-features = false, features = ["alloc"] } [dev-dependencies] From 6954eabaafdc52bb01a9a15644327bc33ffe2434 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 10 Mar 2026 11:10:48 -0600 Subject: [PATCH 23/75] elliptic-curve v0.14.0-rc.29 (#2340) --- Cargo.lock | 6 +++--- elliptic-curve/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 04e120bbb..5dce6f671 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,9 +170,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f438b626cb7c9dd48a613a9826e6bad9db71097f9d628f7237af2f6bc13c0ec" +checksum = "9fde2467e74147f492aebb834985186b2c74761927b8b9b3bd303bcb2e72199d" dependencies = [ "cpubits", "ctutils", @@ -229,7 +229,7 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.14.0-rc.28" +version = "0.14.0-rc.29" dependencies = [ "base16ct", "crypto-bigint", diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index a327584db..11244f029 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "elliptic-curve" -version = "0.14.0-rc.28" +version = "0.14.0-rc.29" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" From 84476d3c0d005820b39be4780c52b864ca43335f Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 13 Mar 2026 05:51:37 -0600 Subject: [PATCH 24/75] digest: remove `Clone` from `MacTraits` (#2341) NOTE: this is a breaking change! We are doing it in spite of `digest` having a stable release as the downstream crates that depend on this functionality have not yet had stable releases, so it should only impact people who are currently relying on prereleases --- Cargo.lock | 11 +++++------ Cargo.toml | 1 + digest/CHANGELOG.md | 12 +++++++++++- digest/src/block_api.rs | 4 ++-- digest/src/buffer_macros/fixed.rs | 7 +++---- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5dce6f671..1af1edccc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -321,8 +321,7 @@ dependencies = [ [[package]] name = "hmac" version = "0.13.0-rc.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef451d73f36d8a3f93ad32c332ea01146c9650e1ec821a9b0e46c01277d544f8" +source = "git+https://github.com/RustCrypto/MACs#2c51e3b76e6f50c13d85577c3faac7df66e24306" dependencies = [ "digest", ] @@ -439,9 +438,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" dependencies = [ "critical-section", "portable-atomic", @@ -514,9 +513,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] diff --git a/Cargo.toml b/Cargo.toml index 79c85b5b2..68f11e216 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,3 +57,4 @@ unused_qualifications = "warn" crypto-common = { path = "crypto-common" } digest = { path = "digest" } signature = { path = "signature" } +hmac = { git = "https://github.com/RustCrypto/MACs" } diff --git a/digest/CHANGELOG.md b/digest/CHANGELOG.md index 314c7f187..83e512f59 100644 --- a/digest/CHANGELOG.md +++ b/digest/CHANGELOG.md @@ -5,7 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.11.1 (2026-02-25) +## 0.11.2 (UNRELEASED) +### Changed +- Do not implement `Clone` as part of `(Reset)MacTraits` in the `buffer_fixed!` macro ([#2341]) +- `EagerHash` trait to be a sub-trait of `Clone` ([#2341]) + +[#2341]: https://github.com/RustCrypto/traits/pull/2341 + +## 0.11.1 (2026-02-25) [YANKED] +Note: this version was yanked because v0.11.2 introduces minor breaking changes +affecting only pre-release versions of downstream crates. + ### Added - `SmallBlockSizeUser` helper trait. The trait is a sub-trait of `BlockSizeUser` with `BlockSize` bounded by `block_buffer::BlockSizes`. ([#2309]) diff --git a/digest/src/block_api.rs b/digest/src/block_api.rs index 7edf8fce6..c417dbe32 100644 --- a/digest/src/block_api.rs +++ b/digest/src/block_api.rs @@ -52,7 +52,7 @@ pub trait BufferKindUser: SmallBlockSizeUser { } /// Trait implemented by eager hashes which expose their block-level core. -pub trait EagerHash: SmallBlockSizeUser + Digest { +pub trait EagerHash: SmallBlockSizeUser + Digest + Clone { /// Block-level core type of the hash. type Core: HashMarker + UpdateCore @@ -65,7 +65,7 @@ pub trait EagerHash: SmallBlockSizeUser + Digest { impl EagerHash for T where - T: CoreProxy + SmallBlockSizeUser + Digest, + T: CoreProxy + SmallBlockSizeUser + Digest + Clone, ::Core: HashMarker + UpdateCore + FixedOutputCore diff --git a/digest/src/buffer_macros/fixed.rs b/digest/src/buffer_macros/fixed.rs index f17e68376..f238b0dd5 100644 --- a/digest/src/buffer_macros/fixed.rs +++ b/digest/src/buffer_macros/fixed.rs @@ -65,8 +65,7 @@ macro_rules! buffer_fixed { }; // Implements the set of traits common for MAC functions: - // `Debug`, `BlockSizeUser`, `OutputSizeUser`, `CoreProxy`, `Update`, `FixedOutput`, - // `Clone`, `MacMarker`. + // `Debug`, `BlockSizeUser`, `OutputSizeUser`, `CoreProxy`, `Update`, `FixedOutput`, `MacMarker` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? @@ -75,13 +74,13 @@ macro_rules! buffer_fixed { ) => { $crate::buffer_fixed!( impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); - BaseFixedTraits Clone MacMarker $($trait_name)*; + BaseFixedTraits MacMarker $($trait_name)*; ); }; // Implements the set of traits common for resettable MAC functions: // `Debug`, `BlockSizeUser`, `OutputSizeUser`, `CoreProxy`, `Update`, `FixedOutput`, - // `Clone`, `MacMarker`, `Reset`, `FixedOutputReset`. + // `MacMarker`, `Reset`, `FixedOutputReset`. ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? From a87b56713fb66f0a657c422affad5ac6f8d58003 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 13 Mar 2026 19:37:22 +0300 Subject: [PATCH 25/75] Release `digest` v0.11.2 (#2342) Note: v0.11.1 was yanked because v0.11.2 introduces minor breaking changes affecting only pre-release versions of downstream crates. ### Changed - Do not implement `Clone` as part of `(Reset)MacTraits` in the `buffer_fixed!` macro ([#2341]) - `EagerHash` trait to be a sub-trait of `Clone` ([#2341]) [#2341]: https://github.com/RustCrypto/traits/pull/2341 --- digest/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/digest/CHANGELOG.md b/digest/CHANGELOG.md index 83e512f59..e513c926c 100644 --- a/digest/CHANGELOG.md +++ b/digest/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.11.2 (UNRELEASED) +## 0.11.2 (2026-03-13) ### Changed - Do not implement `Clone` as part of `(Reset)MacTraits` in the `buffer_fixed!` macro ([#2341]) - `EagerHash` trait to be a sub-trait of `Clone` ([#2341]) From 2465f98a7ebc9f1c8d10dab0e5f30113505a1826 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 13 Mar 2026 19:45:28 +0300 Subject: [PATCH 26/75] digest: bump version to v0.11.2 (#2343) --- Cargo.lock | 2 +- digest/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1af1edccc..211d383a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -216,7 +216,7 @@ dependencies = [ [[package]] name = "digest" -version = "0.11.1" +version = "0.11.2" dependencies = [ "blobby", "block-buffer", diff --git a/digest/Cargo.toml b/digest/Cargo.toml index bc08a55c7..93dd6eed0 100644 --- a/digest/Cargo.toml +++ b/digest/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "digest" -version = "0.11.1" +version = "0.11.2" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" From a573881c03e38423d0ce24a8a908c26d22125bb5 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 25 Mar 2026 12:45:08 -0600 Subject: [PATCH 27/75] digest: bump `sha2` `dev-dependency` to v0.11 (#2345) --- Cargo.lock | 8 ++++---- digest/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 211d383a2..a6d093562 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -141,9 +141,9 @@ checksum = "5ef0c543070d296ea414df2dd7625d1b24866ce206709d8a4a424f28377f5861" [[package]] name = "cpufeatures" -version = "0.2.17" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] @@ -651,9 +651,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.11.0-rc.5" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c5f3b1e2dc8aad28310d8410bd4d7e180eca65fca176c52ab00d364475d0024" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", "cpufeatures", diff --git a/digest/Cargo.toml b/digest/Cargo.toml index 93dd6eed0..476e0d41c 100644 --- a/digest/Cargo.toml +++ b/digest/Cargo.toml @@ -23,7 +23,7 @@ ctutils = { version = "0.4", optional = true } zeroize = { version = "1.7", optional = true, default-features = false } [dev-dependencies] -sha2 = "0.11.0-rc.5" +sha2 = "0.11" [features] default = ["block-api"] From b7c764a79f8e6863d9284823e7cb4a5223acebfa Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 25 Mar 2026 13:30:23 -0600 Subject: [PATCH 28/75] Cargo.lock: bump `crypto-bigint` to v0.7.3 (#2346) This clears the security audit --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a6d093562..fb09e38cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,9 +170,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fde2467e74147f492aebb834985186b2c74761927b8b9b3bd303bcb2e72199d" +checksum = "42a0d26b245348befa0c121944541476763dcc46ede886c88f9d12e1697d27c3" dependencies = [ "cpubits", "ctutils", From 1c96506e27d9e6bb8531f7c19b06112597692d02 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 30 Mar 2026 08:48:29 -0600 Subject: [PATCH 29/75] elliptic-curve: bump `hkdf` dependency to v0.13 (#2349) Release PR: RustCrypto/KDFs#195 --- Cargo.lock | 9 +++++---- Cargo.toml | 1 - elliptic-curve/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fb09e38cc..521a4c6c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -311,17 +311,18 @@ checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" [[package]] name = "hkdf" -version = "0.13.0-rc.5" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbb55385998ae66b8d2d5143c05c94b9025ab863966f0c94ce7a5fde30105092" +checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018" dependencies = [ "hmac", ] [[package]] name = "hmac" -version = "0.13.0-rc.5" -source = "git+https://github.com/RustCrypto/MACs#2c51e3b76e6f50c13d85577c3faac7df66e24306" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" dependencies = [ "digest", ] diff --git a/Cargo.toml b/Cargo.toml index 68f11e216..79c85b5b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,4 +57,3 @@ unused_qualifications = "warn" crypto-common = { path = "crypto-common" } digest = { path = "digest" } signature = { path = "signature" } -hmac = { git = "https://github.com/RustCrypto/MACs" } diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index 11244f029..04d08eac1 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -29,7 +29,7 @@ zeroize = { version = "1.7", default-features = false } digest = { version = "0.11", optional = true } ff = { version = "0.14.0-rc.0", package = "rustcrypto-ff", optional = true, default-features = false } group = { version = "0.14.0-rc.0", package = "rustcrypto-group", optional = true, default-features = false } -hkdf = { version = "0.13.0-rc.5", optional = true, default-features = false } +hkdf = { version = "0.13", optional = true, default-features = false } hex-literal = { version = "1", optional = true } once_cell = { version = "1.21", optional = true, default-features = false } pem-rfc7468 = { version = "1", optional = true, features = ["alloc"] } From ea57736ece709174832ff7be0c1ff4f777b9a9f1 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 2 Apr 2026 19:18:28 -0600 Subject: [PATCH 30/75] kem: add basic usage with example (#2354) --- kem/src/lib.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/kem/src/lib.rs b/kem/src/lib.rs index 5a1e64f6e..bd9a9a567 100644 --- a/kem/src/lib.rs +++ b/kem/src/lib.rs @@ -8,6 +8,49 @@ #![forbid(unsafe_code)] #![warn(missing_docs, unused_qualifications, missing_debug_implementations)] +//! # Usage +//! +//! There are two roles in a KEM: +//! +//! - Encapsulator: the holder of the public key (a.k.a. encapsulation key), which provides an +//! operation that simultaneously generates both the plaintext and ciphertext of a random +//! "shared key" whose ciphertext (a.k.a. encapsulation) can be sent to the party with the +//! decapsulator key. +//! - Decapsulator: holder secret/private key (a.k.a. decapsulation key), which can be used to +//! decrypt the encrypted (a.k.a. encapsulated) "shared key" which was randomly generated by +//! the encapsulator. +//! +//! The following example illustrates the workflow of using this crate's traits with a hypothetical +//! KEM named `K` : +//! +#![cfg_attr(feature = "getrandom", doc = "```")] +#![cfg_attr(not(feature = "getrandom"), doc = "```ignore")] +//! // NOTE: requires the `getrandom` feature is enabled +//! +//! use kem::{Decapsulate, Encapsulate, Kem}; +//! +//! # pub fn kem_workflow_example>() { +//! // Generate a decapsulation/encapsulation keypair. The first one is the secret one. +//! let (dk, ek) = K::generate_keypair(); +//! +//! // Encapsulator: +//! // +//! // Randomly generates and encapsulates/encrypts a shared key which can be decrypted by the +//! // holder of the decapsulation key, obtaining the ciphertext and plaintext of the shared key. +//! let (ct, k_send) = ek.encapsulate(); +//! +//! // Decapsulator: +//! // +//! // Decapsulates the encrypted/encapsulated shared key, obtaining its plaintext. +//! let k_recv = dk.decapsulate(&ct); +//! +//! // We've now established a shared key. +//! assert_eq!(k_send, k_recv); +//! # } +//! ``` +//! +//! [RFC 9180]: https://www.rfc-editor.org/info/rfc9180 + pub use common::{ self, Generate, InvalidKey, Key, KeyExport, KeyInit, KeySizeUser, TryKeyInit, typenum::consts, }; From 13beea5bab69eccd5ecf45081c0541a3175d5f02 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 2 Apr 2026 19:30:46 -0600 Subject: [PATCH 31/75] kem: add serialization docs (#2355) --- kem/src/lib.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kem/src/lib.rs b/kem/src/lib.rs index bd9a9a567..508005bd6 100644 --- a/kem/src/lib.rs +++ b/kem/src/lib.rs @@ -49,6 +49,17 @@ //! # } //! ``` //! +//! ## Serialization +//! +//! The [`KeyInit`] and [`KeyExport`] traits can be used to load and store encoded decapsulation +//! and encapsulation keys from their byte serialization. +//! +//! Decapsulation keys are often initialized from a compact representation known as a [`Seed`]. +//! The [`FromSeed`] trait provides an extension to the [`Kem`] trait for initializing keypairs +//! from a seed value. We recommend the [`KeyInit`] and [`KeyExport`] trait impls on +//! decapsulation keys operate on seed values when there is a choice of multiple key formats +//! (e.g. expanded decapsulation keys). +//! //! [RFC 9180]: https://www.rfc-editor.org/info/rfc9180 pub use common::{ From 23118eab10a60fb31ee81785bd02dac7ccb12681 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 3 Apr 2026 07:42:46 -0600 Subject: [PATCH 32/75] kem v0.3.0 (#2356) This release is effectively a complete rewrite of the `kem` crate. Any similarities between trait names in this release and previous releases is coincidental. The log below highlights some of the new parts of the API but will provide an incomplete picture of changes. ## Added - `Encapsulate` and `Decapsulate` traits (#1509) - `getrandom` feature (#2140) - Re-exports from `crypto-common` (#2222) - re-exports `crypto-common` itself as `common` - re-exports `KeyInit`, which is useful for seeds - re-exports `Key` as the type for representing serialized encapsulation and decapsulation keys - re-exports `InvalidKey` as the error when `TryKeyInit` fails - `TryDecapsulate` trait (#2220, #2235) - `Kem` trait for the whole algorithm type family (#2243) - `FromSeed` trait and `Seed` type alias (#2284) ## Changed - `Decapsulator` trait replaced with new implementation (#2282) ## Removed - Previous implementation (#1509) --- Cargo.lock | 2 +- kem/CHANGELOG.md | 34 +++++++++++++++++++++++++++++++++- kem/Cargo.toml | 2 +- kem/LICENSE-MIT | 2 +- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 521a4c6c1..321eb3da5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -378,7 +378,7 @@ version = "0.1.0" [[package]] name = "kem" -version = "0.3.0-rc.6" +version = "0.3.0" dependencies = [ "crypto-common", "rand_core", diff --git a/kem/CHANGELOG.md b/kem/CHANGELOG.md index 076390b45..2e59ed6c8 100644 --- a/kem/CHANGELOG.md +++ b/kem/CHANGELOG.md @@ -4,7 +4,39 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.3.0 (UNRELEASED) +## 0.3.0 (2026-02-04) + +This release is effectively a complete rewrite of the `kem` crate. Any similarities between trait +names in this release and previous releases is coincidental. The log below highlights some of the +new parts of the API but will provide an incomplete picture of changes. + +### Added +- `Encapsulate` and `Decapsulate` traits ([#1509]) +- `getrandom` feature ([#2140]) +- Re-exports from `crypto-common` ([#2222]) + - re-exports `crypto-common` itself as `common` + - re-exports `KeyInit`, which is useful for seeds + - re-exports `Key` as the type for representing serialized encapsulation and decapsulation keys + - re-exports `InvalidKey` as the error when `TryKeyInit` fails +- `TryDecapsulate` trait ([#2220], [#2235]) +- `Kem` trait for the whole algorithm type family ([#2243]) +- `FromSeed` trait and `Seed` type alias ([#2284]) + +### Changed +- `Decapsulator` trait replaced with new implementation ([#2282]) + +### Removed +- Previous implementation ([#1509]) + +[#1509]: https://github.com/RustCrypto/traits/pull/1509 +[#2140]: https://github.com/RustCrypto/traits/pull/2140 +[#2140]: https://github.com/RustCrypto/traits/pull/2140 +[#2222]: https://github.com/RustCrypto/traits/pull/2222 +[#2220]: https://github.com/RustCrypto/traits/pull/2220 +[#2235]: https://github.com/RustCrypto/traits/pull/2235 +[#2243]: https://github.com/RustCrypto/traits/pull/2243 +[#2284]: https://github.com/RustCrypto/traits/pull/2284 + ### Changed - Edition changed to 2024 and MSRV bumped to 1.85 ([#1759]) - Bump `rand_core` to v0.10 ([#2250]) diff --git a/kem/Cargo.toml b/kem/Cargo.toml index 9d21b49e8..e6d3cda0a 100644 --- a/kem/Cargo.toml +++ b/kem/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kem" -version = "0.3.0-rc.6" +version = "0.3.0" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" diff --git a/kem/LICENSE-MIT b/kem/LICENSE-MIT index d1c716154..4296756c6 100644 --- a/kem/LICENSE-MIT +++ b/kem/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2021-2025 RustCrypto Developers +Copyright (c) 2021-2026 RustCrypto Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated From fb3f1eaa908ea5360dbddafb244966d547cdad69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 18:02:00 -0600 Subject: [PATCH 33/75] build(deps): bump the all-deps group across 1 directory with 11 updates (#2369) --- Cargo.lock | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 321eb3da5..d5c6d9761 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -123,9 +123,9 @@ dependencies = [ [[package]] name = "cmov" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0758edba32d61d1fd9f4d69491b47604b91ee2f7e6b33de7e54ca4ebe55dc3" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" [[package]] name = "const-oid" @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "ctutils" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1005a6d4446f5120ef475ad3d2af2b30c49c2c9c6904258e3bb30219bebed5e4" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" dependencies = [ "cmov", "subtle", @@ -329,9 +329,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8655f91cd07f2b9d0c24137bd650fe69617773435ee5ec83022377777ce65ef1" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" dependencies = [ "subtle", "typenum", @@ -346,9 +346,9 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -368,9 +368,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "kdf" @@ -392,9 +392,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.183" +version = "0.2.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" [[package]] name = "log" @@ -541,9 +541,9 @@ checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" [[package]] name = "rustcrypto-ff" -version = "0.14.0-rc.0" +version = "0.14.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5db129183b2c139d7d87d08be57cba626c715789db17aec65c8866bfd767d1f" +checksum = "fd2a8adb347447693cd2ba0d218c4b66c62da9b0a5672b17b981e4291ec65ff6" dependencies = [ "bitvec", "rand_core", @@ -568,9 +568,9 @@ dependencies = [ [[package]] name = "rustcrypto-group" -version = "0.14.0-rc.0" +version = "0.14.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c4b1463f274a3ff6fb2f44da43e576cb9424367bd96f185ead87b52fe00523" +checksum = "369f9b61aa45933c062c9f6b5c3c50ab710687eca83dd3802653b140b43f85ed" dependencies = [ "rand_core", "rustcrypto-ff", @@ -579,9 +579,9 @@ dependencies = [ [[package]] name = "sec1" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46b9a5ab87780a3189a1d704766579517a04ad59de653b7aad7d38e8a15f7dc" +checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d" dependencies = [ "base16ct", "ctutils", @@ -594,9 +594,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -671,9 +671,9 @@ dependencies = [ [[package]] name = "spki" -version = "0.8.0-rc.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80" +checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f" dependencies = [ "base64ct", "der", From adcbc4401f8d1ace88708a1f05833b07aeb31bb8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2026 18:02:30 -0600 Subject: [PATCH 34/75] build(deps): bump crate-ci/typos from 1.44.0 to 1.45.0 (#2368) --- .github/workflows/workspace.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index 062506f40..9f39d6e3a 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -56,7 +56,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - uses: crate-ci/typos@v1.44.0 + - uses: crate-ci/typos@v1.45.0 lock: name: Check Cargo.lock From f18bb8094fe909a7f749b1036775afce340704ee Mon Sep 17 00:00:00 2001 From: Greg Rubin Date: Tue, 7 Apr 2026 03:18:56 -0700 Subject: [PATCH 35/75] digest: add `dev::initialized_mac_test` function (#2367) --- digest/CHANGELOG.md | 6 ++++++ digest/src/dev/mac.rs | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/digest/CHANGELOG.md b/digest/CHANGELOG.md index e513c926c..de9d690e9 100644 --- a/digest/CHANGELOG.md +++ b/digest/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.11.3 (UNRELEASED) +### Added +- `dev::initialized_mac_test` function ([#2367]) + +[#2367]: https://github.com/RustCrypto/traits/pull/2367 + ## 0.11.2 (2026-03-13) ### Changed - Do not implement `Clone` as part of `(Reset)MacTraits` in the `buffer_fixed!` macro ([#2341]) diff --git a/digest/src/dev/mac.rs b/digest/src/dev/mac.rs index 294704f37..9a3581285 100644 --- a/digest/src/dev/mac.rs +++ b/digest/src/dev/mac.rs @@ -31,6 +31,17 @@ pub fn mac_test( return Err("Failed to initialize MAC instance"); }; + initialized_mac_test(mac0, input, tag, trunc_side) +} + +/// Run the MAC test directly on an initialized MAC. +/// This is useful for when custom initialization is needed +pub fn initialized_mac_test( + mac0: M, + input: &[u8], + tag: &[u8], + trunc_side: MacTruncSide, +) -> Result<(), &'static str> { let mut mac = mac0.clone(); mac.update(input); let result = mac.finalize().into_bytes(); From 2501d4f5454caaf2a22de6ccc33467b9c3282260 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 7 Apr 2026 14:23:11 -0600 Subject: [PATCH 36/75] password-hash: change bounds for PHC verify blanket impl [BREAKING] (#2370) Changes the `TryFrom` bound for constructing `T::Params` to accept a full `phc::PasswordHash` as the input type, rather than just its `phc::ParamsString`. This is actually how it used to work in prior releases, but regressed: https://docs.rs/password-hash/0.5.0/src/password_hash/traits.rs.html#63 This is needed so the params can include the output size for the hash. This is unfortunately a breaking change, but fortunately we haven't yet released any password hash crates, so it will only impact prerelease users. Closes #2352. --- password-hash/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/password-hash/src/lib.rs b/password-hash/src/lib.rs index 98b9ed97b..e4117151b 100644 --- a/password-hash/src/lib.rs +++ b/password-hash/src/lib.rs @@ -196,7 +196,7 @@ pub trait PasswordVerifier { #[cfg(feature = "phc")] impl> PasswordVerifier for T where - T::Params: for<'a> TryFrom<&'a phc::ParamsString, Error = Error>, + T::Params: for<'a> TryFrom<&'a phc::PasswordHash, Error = Error>, { fn verify_password(&self, password: &[u8], hash: &phc::PasswordHash) -> Result<()> { #[allow(clippy::single_match)] @@ -207,7 +207,7 @@ where salt, Some(hash.algorithm.as_str()), hash.version, - T::Params::try_from(&hash.params)?, + T::Params::try_from(hash)?, )?; if let Some(computed_output) = &computed_hash.hash { From d1954d88cbde6b6ee839d3a2f78e5b03fd4eaa1d Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 7 Apr 2026 18:59:57 -0600 Subject: [PATCH 37/75] password-hash v0.6.1 (#2371) ## Changed - [BREAKING] `PasswordVerifier` blanket impl bounds for `phc::PasswordHash` (#2370) --- Cargo.lock | 2 +- password-hash/CHANGELOG.md | 11 ++++++++++- password-hash/Cargo.toml | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d5c6d9761..37be0bee3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -449,7 +449,7 @@ dependencies = [ [[package]] name = "password-hash" -version = "0.6.0" +version = "0.6.1" dependencies = [ "getrandom", "phc", diff --git a/password-hash/CHANGELOG.md b/password-hash/CHANGELOG.md index 1cc235314..473617343 100644 --- a/password-hash/CHANGELOG.md +++ b/password-hash/CHANGELOG.md @@ -5,7 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.6.0 (2026-03-10) +## 0.6.1 (2026-04-07) +### Changed +- Bounds for blanket impl of `PasswordVerifier` for `phc::PasswordHash` [BREAKING] ([#2370]) + +[#2370]: https://github.com/RustCrypto/traits/pull/2370 + +## 0.6.0 (2026-03-10) [YANKED] + +NOTE: this release was yanked to accommodate breaking changes introduced in v0.6.1. + ### Added - Generic `H` param to traits to support multiple string formats e.g. PHC, MCF ([#2110]) - Implement `From` for `Error` ([#2124]) diff --git a/password-hash/Cargo.toml b/password-hash/Cargo.toml index 478fb69f9..d51c8166f 100644 --- a/password-hash/Cargo.toml +++ b/password-hash/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "password-hash" -version = "0.6.0" +version = "0.6.1" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" From 2b8c0c5e058885ec3da91de9d7249fd5529f7393 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 8 Apr 2026 15:36:28 -0600 Subject: [PATCH 38/75] elliptic-curve: bump `ff`/`group` dependencies to v0.14.0-rc.1 (#2372) These notably include the workarounds to make wNAF work --- elliptic-curve/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index 04d08eac1..2b0155b21 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -27,8 +27,8 @@ zeroize = { version = "1.7", default-features = false } # optional dependencies digest = { version = "0.11", optional = true } -ff = { version = "0.14.0-rc.0", package = "rustcrypto-ff", optional = true, default-features = false } -group = { version = "0.14.0-rc.0", package = "rustcrypto-group", optional = true, default-features = false } +ff = { version = "0.14.0-rc.1", package = "rustcrypto-ff", optional = true, default-features = false } +group = { version = "0.14.0-rc.1", package = "rustcrypto-group", optional = true, default-features = false } hkdf = { version = "0.13", optional = true, default-features = false } hex-literal = { version = "1", optional = true } once_cell = { version = "1.21", optional = true, default-features = false } From cf5b81033c8179707d54d560b9185fca458fe5e3 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 8 Apr 2026 16:07:11 -0600 Subject: [PATCH 39/75] elliptic-curve v0.14.0-rc.30 (#2373) Includes preliminary support for wNAF --- Cargo.lock | 2 +- elliptic-curve/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 37be0bee3..0b5095447 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -229,7 +229,7 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.14.0-rc.29" +version = "0.14.0-rc.30" dependencies = [ "base16ct", "crypto-bigint", diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index 2b0155b21..5e5922601 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "elliptic-curve" -version = "0.14.0-rc.29" +version = "0.14.0-rc.30" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" From ac679706c5fd0255a5b585ffe4303c7daa4b7a5c Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 8 Apr 2026 21:46:32 -0600 Subject: [PATCH 40/75] elliptic-curve: add `PointWithBasepointTable` trait (#2376) Adds a trait with an associated `BASEPOINT_TABLE` constant which provides a place to access a particular curve group's `BasepointTable` from a generic context. --- elliptic-curve/src/point.rs | 2 +- elliptic-curve/src/point/basepoint_table.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/elliptic-curve/src/point.rs b/elliptic-curve/src/point.rs index e3153cf2f..916d6f3df 100644 --- a/elliptic-curve/src/point.rs +++ b/elliptic-curve/src/point.rs @@ -8,7 +8,7 @@ mod non_identity; pub use {self::non_identity::NonIdentity, lookup_table::LookupTable}; #[cfg(feature = "basepoint-table")] -pub use self::basepoint_table::BasepointTable; +pub use self::basepoint_table::{BasepointTable, PointWithBasepointTable}; use crate::{Curve, FieldBytes}; use subtle::{Choice, CtOption}; diff --git a/elliptic-curve/src/point/basepoint_table.rs b/elliptic-curve/src/point/basepoint_table.rs index df218f72c..528c27a80 100644 --- a/elliptic-curve/src/point/basepoint_table.rs +++ b/elliptic-curve/src/point/basepoint_table.rs @@ -6,7 +6,7 @@ #[cfg(not(any(feature = "critical-section", feature = "std")))] compile_error!("`basepoint-table` feature requires either `critical-section` or `std`"); -use crate::point::LookupTable; +use super::LookupTable; use group::Group; use subtle::ConditionallySelectable; use {core::ops::Deref, ff::PrimeField}; @@ -16,6 +16,12 @@ use once_cell::sync::Lazy as LazyLock; #[cfg(all(feature = "std", not(feature = "critical-section")))] use std::sync::LazyLock; +/// Associate a precomputed `BASEPOINT_TABLE` constant with a curve point. +pub trait PointWithBasepointTable: Group { + /// Basepoint table for this curve. + const BASEPOINT_TABLE: &'static BasepointTable; +} + /// Precomputed lookup table of multiples of a base point, a.k.a. generator. /// /// This type leverages lazy computation, and requires one of the following crate features to be From caa96381bcdf6de5ffaaa49114c05aa5d33ce98f Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 9 Apr 2026 07:28:23 -0600 Subject: [PATCH 41/75] elliptic-curve: add `VartimeBasepointTable` (#2374) Uses the same strategy as our existing `BasepointTable` type, i.e. using either `std::sync::LazyLock` if `std` is available, or if not optionally falling back on `once_cell` with the `critical-section` feature enabled, to enable a lazily computed basepoint table with a `const fn new` constructor that is backed by `WnafBase`. Like `BasepointTable` it requires the `basepoint-table` feature (which cannot be enabled unless one of `critical-section` or `std` is enabled so we have a `LazyLock` type available), but also additionally requires the `alloc` feature as it's needed for `group::WnafBase`. The type has a single method `VartimeBasepointTable::mul` that performs a scalar multiplication by the provided `Point::Scalar`. --- elliptic-curve/src/point.rs | 7 +- elliptic-curve/src/point/basepoint_table.rs | 79 +++++++++++++++++++-- 2 files changed, 76 insertions(+), 10 deletions(-) diff --git a/elliptic-curve/src/point.rs b/elliptic-curve/src/point.rs index 916d6f3df..e57491b50 100644 --- a/elliptic-curve/src/point.rs +++ b/elliptic-curve/src/point.rs @@ -4,11 +4,12 @@ mod basepoint_table; mod lookup_table; mod non_identity; -#[cfg(feature = "arithmetic")] -pub use {self::non_identity::NonIdentity, lookup_table::LookupTable}; - +#[cfg(all(feature = "alloc", feature = "basepoint-table"))] +pub use self::basepoint_table::vartime::{PointWithVartimeBasepointTable, VartimeBasepointTable}; #[cfg(feature = "basepoint-table")] pub use self::basepoint_table::{BasepointTable, PointWithBasepointTable}; +#[cfg(feature = "arithmetic")] +pub use {self::non_identity::NonIdentity, lookup_table::LookupTable}; use crate::{Curve, FieldBytes}; use subtle::{Choice, CtOption}; diff --git a/elliptic-curve/src/point/basepoint_table.rs b/elliptic-curve/src/point/basepoint_table.rs index 528c27a80..b8e1da3b6 100644 --- a/elliptic-curve/src/point/basepoint_table.rs +++ b/elliptic-curve/src/point/basepoint_table.rs @@ -30,11 +30,11 @@ pub trait PointWithBasepointTable: Group { /// - `critical-section`: leverages `once_cell::sync::Lazy` via the `critical-section` crate, /// enabling the feature to be used in `no_std` contexts. #[derive(Debug)] -pub struct BasepointTable { - tables: LazyLock<[LookupTable; N]>, +pub struct BasepointTable { + tables: LazyLock<[LookupTable; WINDOW_SIZE]>, } -impl BasepointTable +impl BasepointTable where Point: ConditionallySelectable + Default + Group, { @@ -77,7 +77,7 @@ where } } -impl Default for BasepointTable +impl Default for BasepointTable where Point: ConditionallySelectable + Default + Group, { @@ -86,11 +86,76 @@ where } } -impl Deref for BasepointTable { - type Target = [LookupTable; N]; +impl Deref for BasepointTable { + type Target = [LookupTable; WINDOW_SIZE]; #[inline] - fn deref(&self) -> &[LookupTable; N] { + fn deref(&self) -> &[LookupTable; WINDOW_SIZE] { &self.tables } } + +#[cfg(feature = "alloc")] +pub(super) mod vartime { + use super::LazyLock; + use core::ops::Mul; + use group::{Group, WnafBase, WnafScalar}; + + /// Associate a precomputed `VARTIME_BASEPOINT_TABLE` constant with a curve point. + pub trait PointWithVartimeBasepointTable: Group { + /// Basepoint table for this curve. + const VARTIME_BASEPOINT_TABLE: &'static VartimeBasepointTable; + } + + /// Window table for a curve's base point (a.k.a. generator) precomputed to improve the speed of + /// variable-time scalar multiplication. + /// + ///

+ /// Security Warning + /// + /// Variable-time scalar multiplication can potentially leak secret values and should NOT be + /// used with them. + ///
+ /// + /// This type leverages lazy computation, and requires one of the following crate features to be + /// enabled in order to work: + /// - `std`: leverages `std::sync::LazyLock` + /// - `critical-section`: leverages `once_cell::sync::Lazy` via the `critical-section` crate, + /// enabling the feature to be used in `no_std` contexts. + #[derive(Debug)] + pub struct VartimeBasepointTable { + table: LazyLock>, + } + + impl VartimeBasepointTable { + /// Create a new [`VartimeBasepointTable`] which is lazily initialized on first use and can + /// be bound to a constant. + /// + /// Computed using the `Point`'s [`Group::generator`] as the base point. + pub const fn new() -> Self { + /// Inner function to initialize the wNAF context. + fn init_wnaf() -> WnafBase + where + Point: Group, + { + WnafBase::new(Point::generator()) + } + + Self { + table: LazyLock::new(init_wnaf), + } + } + + /// Multiply `Point::generator` by the given scalar in variable-time, using the precomputed + /// window table to accelerate the scalar multiplication. + pub fn mul(&self, scalar: &Point::Scalar) -> Point { + self.table.mul(&WnafScalar::new(scalar)) + } + } + + impl Default for VartimeBasepointTable { + fn default() -> Self { + Self::new() + } + } +} From 4f084d393e5ed3fdff56dc4cf3093e815516842a Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 9 Apr 2026 08:15:10 -0600 Subject: [PATCH 42/75] elliptic-curve: use `*Vartime` as a suffix (#2378) As suggested in #2377, this follows precedent from `crypto-bigint` and makes `*Vartime` a suffix in trait and type names, so we can use `*_vartime` method names and they will be consistent with the trait names. --- elliptic-curve/src/point.rs | 2 +- elliptic-curve/src/point/basepoint_table.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/elliptic-curve/src/point.rs b/elliptic-curve/src/point.rs index e57491b50..bcc76165e 100644 --- a/elliptic-curve/src/point.rs +++ b/elliptic-curve/src/point.rs @@ -5,7 +5,7 @@ mod lookup_table; mod non_identity; #[cfg(all(feature = "alloc", feature = "basepoint-table"))] -pub use self::basepoint_table::vartime::{PointWithVartimeBasepointTable, VartimeBasepointTable}; +pub use self::basepoint_table::vartime::{BasepointTableVartime, PointWithBasepointTableVartime}; #[cfg(feature = "basepoint-table")] pub use self::basepoint_table::{BasepointTable, PointWithBasepointTable}; #[cfg(feature = "arithmetic")] diff --git a/elliptic-curve/src/point/basepoint_table.rs b/elliptic-curve/src/point/basepoint_table.rs index b8e1da3b6..fe3d88ea1 100644 --- a/elliptic-curve/src/point/basepoint_table.rs +++ b/elliptic-curve/src/point/basepoint_table.rs @@ -101,10 +101,10 @@ pub(super) mod vartime { use core::ops::Mul; use group::{Group, WnafBase, WnafScalar}; - /// Associate a precomputed `VARTIME_BASEPOINT_TABLE` constant with a curve point. - pub trait PointWithVartimeBasepointTable: Group { + /// Associate a precomputed `BASEPOINT_TABLE_VARTIME` constant with a curve point. + pub trait PointWithBasepointTableVartime: Group { /// Basepoint table for this curve. - const VARTIME_BASEPOINT_TABLE: &'static VartimeBasepointTable; + const BASEPOINT_TABLE_VARTIME: &'static BasepointTableVartime; } /// Window table for a curve's base point (a.k.a. generator) precomputed to improve the speed of @@ -123,12 +123,12 @@ pub(super) mod vartime { /// - `critical-section`: leverages `once_cell::sync::Lazy` via the `critical-section` crate, /// enabling the feature to be used in `no_std` contexts. #[derive(Debug)] - pub struct VartimeBasepointTable { + pub struct BasepointTableVartime { table: LazyLock>, } - impl VartimeBasepointTable { - /// Create a new [`VartimeBasepointTable`] which is lazily initialized on first use and can + impl BasepointTableVartime { + /// Create a new [`BasepointTableVartime`] which is lazily initialized on first use and can /// be bound to a constant. /// /// Computed using the `Point`'s [`Group::generator`] as the base point. @@ -153,7 +153,7 @@ pub(super) mod vartime { } } - impl Default for VartimeBasepointTable { + impl Default for BasepointTableVartime { fn default() -> Self { Self::new() } From d4c0d469169b2c8238efdb99fe7ecc7288de710c Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 9 Apr 2026 08:49:12 -0600 Subject: [PATCH 43/75] elliptic-curve: add `ops::MulVartime` trait and bound `Scalar` (#2379) Adds a variable-time equivalent of the `Mul` trait with a corresponding `mul_vartime` method. This provides a place to plug in wNAF which is otherwise always available (and can fall back on constant-time operations if the `alloc` feature isn't enabled). The trait has been added to the bounds for `CurveArithmetic::Scalar`, with requirements to support variable-time multiplication for affine and projective points. --- elliptic-curve/src/arithmetic.rs | 6 +++++- elliptic-curve/src/dev/mock_curve.rs | 30 ++++++++++++++++++++++++++-- elliptic-curve/src/ops.rs | 15 ++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 7a0025e41..8622d4bd0 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -3,7 +3,7 @@ use crate::{ Curve, CurveGroup, Error, FieldBytes, Group, NonZeroScalar, PrimeCurve, ScalarValue, ctutils::{CtEq, CtSelect}, - ops::{Invert, LinearCombination, Mul, Reduce}, + ops::{Invert, LinearCombination, Mul, MulVartime, Reduce}, point::{AffineCoordinates, NonIdentity}, scalar::{FromUintUnchecked, IsHigh}, }; @@ -88,9 +88,13 @@ pub trait CurveArithmetic: Curve { + Invert> + IsHigh + Mul + + MulVartime + for<'a> Mul<&'a Self::AffinePoint, Output = Self::ProjectivePoint> + + for<'a> MulVartime<&'a Self::AffinePoint> + Mul + + MulVartime + for<'a> Mul<&'a Self::ProjectivePoint, Output = Self::ProjectivePoint> + + for<'a> MulVartime<&'a Self::ProjectivePoint> + PartialOrd + Reduce + Reduce> diff --git a/elliptic-curve/src/dev/mock_curve.rs b/elliptic-curve/src/dev/mock_curve.rs index 0d546ae77..6c3108b9f 100644 --- a/elliptic-curve/src/dev/mock_curve.rs +++ b/elliptic-curve/src/dev/mock_curve.rs @@ -10,7 +10,10 @@ use crate::{ bigint::{Limb, Odd, U256, modular::Retrieve}, ctutils, error::{Error, Result}, - ops::{Invert, LinearCombination, Reduce, ShrAssign}, + ops::{ + Add, AddAssign, Invert, LinearCombination, Mul, MulAssign, MulVartime, Neg, Reduce, + ShrAssign, Sub, SubAssign, + }, point::{AffineCoordinates, NonIdentity}, rand_core::{TryCryptoRng, TryRng}, scalar::{FromUintUnchecked, IsHigh}, @@ -21,7 +24,6 @@ use crate::{ use core::{ array, iter::{Product, Sum}, - ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}, }; use ff::{Field, PrimeField}; use hex_literal::hex; @@ -296,6 +298,12 @@ impl Mul for Scalar { } } +impl MulVartime for Scalar { + fn mul_vartime(self, _other: AffinePoint) -> ProjectivePoint { + unimplemented!(); + } +} + impl Mul<&AffinePoint> for Scalar { type Output = ProjectivePoint; @@ -304,6 +312,12 @@ impl Mul<&AffinePoint> for Scalar { } } +impl MulVartime<&AffinePoint> for Scalar { + fn mul_vartime(self, _other: &AffinePoint) -> ProjectivePoint { + unimplemented!(); + } +} + impl Mul for Scalar { type Output = ProjectivePoint; @@ -312,6 +326,12 @@ impl Mul for Scalar { } } +impl MulVartime for Scalar { + fn mul_vartime(self, _other: ProjectivePoint) -> ProjectivePoint { + unimplemented!(); + } +} + impl Mul<&ProjectivePoint> for Scalar { type Output = ProjectivePoint; @@ -320,6 +340,12 @@ impl Mul<&ProjectivePoint> for Scalar { } } +impl MulVartime<&ProjectivePoint> for Scalar { + fn mul_vartime(self, _other: &ProjectivePoint) -> ProjectivePoint { + unimplemented!(); + } +} + impl MulAssign for Scalar { fn mul_assign(&mut self, _rhs: Scalar) { unimplemented!(); diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index 84dddd60d..c8c344b10 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -183,6 +183,21 @@ where } } +/// Variable-time equivalent of the [`Mul`] trait. +/// +/// Should always compute the same results as [`Mul`], but may provide a faster implementation. +/// +///
+/// Security Warning +/// +/// Variable-time operations should only be used on non-secret values, and may potentially leak +/// secret values! +///
+pub trait MulVartime: Mul { + /// Multiply `self` by `rhs` in variable-time. + fn mul_vartime(self, rhs: Rhs) -> >::Output; +} + /// Modular reduction to a non-zero output. /// /// This trait is primarily intended for use by curve implementations such From b48dd1eb7647bb96ba213cc339bc985577e66c7e Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 10 Apr 2026 09:04:00 -0600 Subject: [PATCH 44/75] elliptic-curve: `MulVartime` fixups (#2380) - Adds `MulVartime` to `AffinePoint` and `ProjectivePoint` bounds - Adds boilerplate `MulVartime` impls to `scalar_mul_impls!` - Uses `scalar_mul_impls!` for `MockCurve` --- elliptic-curve/src/arithmetic.rs | 4 + elliptic-curve/src/dev/mock_curve.rs | 107 +++++++++++++-------------- elliptic-curve/src/macros.rs | 82 +++++++++++++++++++- 3 files changed, 135 insertions(+), 58 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 8622d4bd0..067840211 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -29,6 +29,8 @@ pub trait CurveArithmetic: Curve { + Eq + From> + Generate + + MulVartime + + for<'a> MulVartime<&'a Self::Scalar> + PartialEq + Sized + Send @@ -58,6 +60,8 @@ pub trait CurveArithmetic: Curve { + Into + LinearCombination<[(Self::ProjectivePoint, Self::Scalar)]> + LinearCombination<[(Self::ProjectivePoint, Self::Scalar); 2]> + + MulVartime + + for<'a> MulVartime<&'a Self::Scalar> + TryInto, Error = Error> + CurveGroup + Group; diff --git a/elliptic-curve/src/dev/mock_curve.rs b/elliptic-curve/src/dev/mock_curve.rs index 6c3108b9f..0d85fc7a1 100644 --- a/elliptic-curve/src/dev/mock_curve.rs +++ b/elliptic-curve/src/dev/mock_curve.rs @@ -274,9 +274,10 @@ impl SubAssign<&Scalar> for Scalar { } } +crate::scalar_mul_impls!(MockCurve, Scalar); + impl Mul for Scalar { type Output = Scalar; - fn mul(self, _other: Scalar) -> Scalar { unimplemented!(); } @@ -290,62 +291,6 @@ impl Mul<&Scalar> for Scalar { } } -impl Mul for Scalar { - type Output = ProjectivePoint; - - fn mul(self, _other: AffinePoint) -> ProjectivePoint { - unimplemented!(); - } -} - -impl MulVartime for Scalar { - fn mul_vartime(self, _other: AffinePoint) -> ProjectivePoint { - unimplemented!(); - } -} - -impl Mul<&AffinePoint> for Scalar { - type Output = ProjectivePoint; - - fn mul(self, _other: &AffinePoint) -> ProjectivePoint { - unimplemented!(); - } -} - -impl MulVartime<&AffinePoint> for Scalar { - fn mul_vartime(self, _other: &AffinePoint) -> ProjectivePoint { - unimplemented!(); - } -} - -impl Mul for Scalar { - type Output = ProjectivePoint; - - fn mul(self, _other: ProjectivePoint) -> ProjectivePoint { - unimplemented!(); - } -} - -impl MulVartime for Scalar { - fn mul_vartime(self, _other: ProjectivePoint) -> ProjectivePoint { - unimplemented!(); - } -} - -impl Mul<&ProjectivePoint> for Scalar { - type Output = ProjectivePoint; - - fn mul(self, _other: &ProjectivePoint) -> ProjectivePoint { - unimplemented!(); - } -} - -impl MulVartime<&ProjectivePoint> for Scalar { - fn mul_vartime(self, _other: &ProjectivePoint) -> ProjectivePoint { - unimplemented!(); - } -} - impl MulAssign for Scalar { fn mul_assign(&mut self, _rhs: Scalar) { unimplemented!(); @@ -622,6 +567,34 @@ impl ToSec1Point for AffinePoint { } } +impl Mul for AffinePoint { + type Output = ProjectivePoint; + + fn mul(self, _scalar: Scalar) -> ProjectivePoint { + unimplemented!(); + } +} + +impl Mul<&Scalar> for AffinePoint { + type Output = ProjectivePoint; + + fn mul(self, _scalar: &Scalar) -> ProjectivePoint { + unimplemented!(); + } +} + +impl MulVartime for AffinePoint { + fn mul_vartime(self, _scalar: Scalar) -> ProjectivePoint { + unimplemented!() + } +} + +impl MulVartime<&Scalar> for AffinePoint { + fn mul_vartime(self, _scalar: &Scalar) -> ProjectivePoint { + unimplemented!() + } +} + impl Mul for AffinePoint { type Output = AffinePoint; @@ -982,6 +955,26 @@ impl Mul<&Scalar> for ProjectivePoint { } } +impl Mul<&Scalar> for &ProjectivePoint { + type Output = ProjectivePoint; + + fn mul(self, _scalar: &Scalar) -> ProjectivePoint { + unimplemented!(); + } +} + +impl MulVartime for ProjectivePoint { + fn mul_vartime(self, _scalar: Scalar) -> ProjectivePoint { + unimplemented!() + } +} + +impl MulVartime<&Scalar> for ProjectivePoint { + fn mul_vartime(self, _scalar: &Scalar) -> ProjectivePoint { + unimplemented!() + } +} + impl MulAssign for ProjectivePoint { fn mul_assign(&mut self, _rhs: Scalar) { unimplemented!(); diff --git a/elliptic-curve/src/macros.rs b/elliptic-curve/src/macros.rs index 871ac5ffc..19d60a165 100644 --- a/elliptic-curve/src/macros.rs +++ b/elliptic-curve/src/macros.rs @@ -69,7 +69,7 @@ macro_rules! scalar_from_impls { }; } -/// Writes a series of `Mul` impls for an elliptic curve's scalar field +/// Writes a series of `Mul` impls for an elliptic curve's scalar field. #[macro_export] macro_rules! scalar_mul_impls { ($curve:path, $scalar:ty) => { @@ -144,5 +144,85 @@ macro_rules! scalar_mul_impls { rhs * self } } + + impl $crate::ops::MulVartime<$crate::AffinePoint<$curve>> for $scalar { + #[inline] + fn mul_vartime( + self, + rhs: $crate::AffinePoint<$curve>, + ) -> $crate::ProjectivePoint<$curve> { + $crate::ops::MulVartime::mul_vartime(rhs, self) + } + } + + impl $crate::ops::MulVartime<&$crate::AffinePoint<$curve>> for $scalar { + #[inline] + fn mul_vartime( + self, + rhs: &$crate::AffinePoint<$curve>, + ) -> $crate::ProjectivePoint<$curve> { + $crate::ops::MulVartime::mul_vartime(*rhs, &self) + } + } + + impl $crate::ops::MulVartime<$crate::AffinePoint<$curve>> for &$scalar { + #[inline] + fn mul_vartime( + self, + rhs: $crate::AffinePoint<$curve>, + ) -> $crate::ProjectivePoint<$curve> { + $crate::ops::MulVartime::mul_vartime(rhs, self) + } + } + + impl $crate::ops::MulVartime<&$crate::AffinePoint<$curve>> for &$scalar { + #[inline] + fn mul_vartime( + self, + rhs: &$crate::AffinePoint<$curve>, + ) -> $crate::ProjectivePoint<$curve> { + $crate::ops::MulVartime::mul_vartime(*rhs, self) + } + } + + impl $crate::ops::MulVartime<$crate::ProjectivePoint<$curve>> for $scalar { + #[inline] + fn mul_vartime( + self, + rhs: $crate::ProjectivePoint<$curve>, + ) -> $crate::ProjectivePoint<$curve> { + $crate::ops::MulVartime::mul_vartime(rhs, self) + } + } + + impl $crate::ops::MulVartime<&$crate::ProjectivePoint<$curve>> for $scalar { + #[inline] + fn mul_vartime( + self, + rhs: &$crate::ProjectivePoint<$curve>, + ) -> $crate::ProjectivePoint<$curve> { + $crate::ops::MulVartime::mul_vartime(*rhs, &self) + } + } + + impl $crate::ops::MulVartime<$crate::ProjectivePoint<$curve>> for &$scalar { + #[inline] + fn mul_vartime( + self, + rhs: $crate::ProjectivePoint<$curve>, + ) -> $crate::ProjectivePoint<$curve> { + $crate::ops::MulVartime::mul_vartime(rhs, self) + } + } + + impl $crate::ops::MulVartime<&$crate::ProjectivePoint<$curve>> for &$scalar { + #[inline] + fn mul_vartime( + self, + rhs: &$crate::ProjectivePoint<$curve>, + ) -> $crate::ProjectivePoint<$curve> { + $crate::ops::MulVartime::mul_vartime(*rhs, self) + } + } }; } From 45489da6f3bcda203adacf89e7c1069bc16b6e14 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 10 Apr 2026 19:53:42 -0600 Subject: [PATCH 45/75] elliptic-curve: add `MulByGeneratorVartime` trait (#2381) Closes #2375 We now have variable-time precomputed basepoint tables that use wNAF when the `basepoint-table` and `alloc` features are enabled, which can be opportunistically used when these features are enabled to accelerate this operation. We use `Group::mul_by_generator` for the constant-time basepoint tables, however for an extension trait this is captured as `MulByGeneratorVartime::mul_by_generator_vartime`. As discussed in the above issue, and inspired by `curve25519-dalek`'s `EdwardsPoint::vartime_double_scalar_mul_basepoint` function, this adds `MulByGeneratorVartime::mul_by_generator_and_mul_add_point_vartime` as a provided method. This function is the core of many signature algorithms, and when the basepoint tables and alloc are unavailable it can fall back to a linear combination and still provide better performance than the naive constant time version. --- elliptic-curve/src/ops.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index c8c344b10..e5c1a2c9f 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -6,6 +6,7 @@ pub use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Shr, ShrAssign, Sub, Su use crate::CurveGroup; use core::iter; use ff::Field; +use group::Group; use subtle::{Choice, CtOption}; #[cfg(feature = "alloc")] @@ -198,6 +199,35 @@ pub trait MulVartime: Mul { fn mul_vartime(self, rhs: Rhs) -> >::Output; } +/// Variable-time multiplication by the generator of the curve group. +/// +///
+/// Security Warning +/// +/// Variable-time operations should only be used on non-secret values, and may potentially leak +/// secret values! +///
+pub trait MulByGeneratorVartime: Group + for<'a> MulVartime<&'a Self::Scalar> { + /// Multiply by the generator of the prime-order subgroup. + /// + /// Variable-time equivalent of [`Group::mul_by_generator`]. + fn mul_by_generator_vartime(scalar: &Self::Scalar) -> Self { + Self::generator().mul_vartime(scalar) + } + + /// Multiply `a` by the generator of the prime-order subgroup, adding the result to the point + /// `B` multiplied by the scalar `b`, i.e. compute `aG + bB`. + /// + /// This operation is the core of many signature verification algorithms. + fn mul_by_generator_and_mul_add_point_vartime( + a: &Self::Scalar, + b_scalar: &Self::Scalar, + b_point: &Self, + ) -> Self { + Self::mul_by_generator_vartime(a) + b_point.mul_vartime(b_scalar) + } +} + /// Modular reduction to a non-zero output. /// /// This trait is primarily intended for use by curve implementations such From 403d4d134df62322beaff2612818ed47d1a8946a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 18:05:23 -0600 Subject: [PATCH 46/75] build(deps): bump the all-deps group with 3 updates (#2383) --- Cargo.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b5095447..7165b7c1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -293,9 +293,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "heck" @@ -346,12 +346,12 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "indexmap" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -392,9 +392,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.184" +version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" [[package]] name = "log" @@ -535,9 +535,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "rustcrypto-ff" From ac069b2c44020b32c1efac4bce63b7aa46d2f003 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 15 Apr 2026 12:24:43 -0600 Subject: [PATCH 47/75] elliptic-curve: add `MulByGeneratorVartime` to bounds (#2384) Adds it to the bounds on `CurveArithmetic::ProjectivePoint` --- elliptic-curve/src/arithmetic.rs | 3 ++- elliptic-curve/src/dev/mock_curve.rs | 6 ++++-- elliptic-curve/src/ops.rs | 8 ++++---- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/elliptic-curve/src/arithmetic.rs b/elliptic-curve/src/arithmetic.rs index 067840211..57c550b96 100644 --- a/elliptic-curve/src/arithmetic.rs +++ b/elliptic-curve/src/arithmetic.rs @@ -3,7 +3,7 @@ use crate::{ Curve, CurveGroup, Error, FieldBytes, Group, NonZeroScalar, PrimeCurve, ScalarValue, ctutils::{CtEq, CtSelect}, - ops::{Invert, LinearCombination, Mul, MulVartime, Reduce}, + ops::{Invert, LinearCombination, Mul, MulByGeneratorVartime, MulVartime, Reduce}, point::{AffineCoordinates, NonIdentity}, scalar::{FromUintUnchecked, IsHigh}, }; @@ -60,6 +60,7 @@ pub trait CurveArithmetic: Curve { + Into + LinearCombination<[(Self::ProjectivePoint, Self::Scalar)]> + LinearCombination<[(Self::ProjectivePoint, Self::Scalar); 2]> + + MulByGeneratorVartime + MulVartime + for<'a> MulVartime<&'a Self::Scalar> + TryInto, Error = Error> diff --git a/elliptic-curve/src/dev/mock_curve.rs b/elliptic-curve/src/dev/mock_curve.rs index 0d85fc7a1..33c83c044 100644 --- a/elliptic-curve/src/dev/mock_curve.rs +++ b/elliptic-curve/src/dev/mock_curve.rs @@ -11,8 +11,8 @@ use crate::{ ctutils, error::{Error, Result}, ops::{ - Add, AddAssign, Invert, LinearCombination, Mul, MulAssign, MulVartime, Neg, Reduce, - ShrAssign, Sub, SubAssign, + Add, AddAssign, Invert, LinearCombination, Mul, MulAssign, MulByGeneratorVartime, + MulVartime, Neg, Reduce, ShrAssign, Sub, SubAssign, }, point::{AffineCoordinates, NonIdentity}, rand_core::{TryCryptoRng, TryRng}, @@ -963,6 +963,8 @@ impl Mul<&Scalar> for &ProjectivePoint { } } +impl MulByGeneratorVartime for ProjectivePoint {} + impl MulVartime for ProjectivePoint { fn mul_vartime(self, _scalar: Scalar) -> ProjectivePoint { unimplemented!() diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index e5c1a2c9f..ff97786f4 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -216,15 +216,15 @@ pub trait MulByGeneratorVartime: Group + for<'a> MulVartime<&'a Self::Scalar> { } /// Multiply `a` by the generator of the prime-order subgroup, adding the result to the point - /// `B` multiplied by the scalar `b`, i.e. compute `aG + bB`. + /// `P` multiplied by the scalar `b`, i.e. compute `aG + bP`. /// /// This operation is the core of many signature verification algorithms. fn mul_by_generator_and_mul_add_point_vartime( a: &Self::Scalar, - b_scalar: &Self::Scalar, - b_point: &Self, + b: &Self::Scalar, + p: &Self, ) -> Self { - Self::mul_by_generator_vartime(a) + b_point.mul_vartime(b_scalar) + Self::mul_by_generator_vartime(a) + p.mul_vartime(b) } } From 4aa20faef303aa04f61892d33c229314bdcea43f Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 15 Apr 2026 12:36:33 -0600 Subject: [PATCH 48/75] elliptic-curve: shorten name of `mul_by_generator_and_mul_add_vartime` (#2385) It's already obnoxiously long, but this removes `*_point_*` from the previous `mul_by_generator_and_mul_add_point_vartime`. The RHS of the addition (`bP`) is a point-scalar multiplication, so just "point" alone doesn't add much additional clarity, and also the operation is already defined on e.g. `ProjectivePoint` making it somewhat redundant. --- elliptic-curve/src/ops.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index ff97786f4..1ff2860e5 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -219,11 +219,7 @@ pub trait MulByGeneratorVartime: Group + for<'a> MulVartime<&'a Self::Scalar> { /// `P` multiplied by the scalar `b`, i.e. compute `aG + bP`. /// /// This operation is the core of many signature verification algorithms. - fn mul_by_generator_and_mul_add_point_vartime( - a: &Self::Scalar, - b: &Self::Scalar, - p: &Self, - ) -> Self { + fn mul_by_generator_and_mul_add_vartime(a: &Self::Scalar, b: &Self::Scalar, p: &Self) -> Self { Self::mul_by_generator_vartime(a) + p.mul_vartime(b) } } From b397bd3d6a14320a46d52f8540fda4d34afe681d Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 15 Apr 2026 13:06:25 -0600 Subject: [PATCH 49/75] elliptic-curve v0.14.0-rc.31 (#2386) --- Cargo.lock | 2 +- elliptic-curve/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7165b7c1b..7b1eaf0ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -229,7 +229,7 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.14.0-rc.30" +version = "0.14.0-rc.31" dependencies = [ "base16ct", "crypto-bigint", diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index 5e5922601..4542758df 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "elliptic-curve" -version = "0.14.0-rc.30" +version = "0.14.0-rc.31" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" From f7e7c3de8fb51d9b388425dbbcd72e944814eefe Mon Sep 17 00:00:00 2001 From: Douman Date: Fri, 17 Apr 2026 00:54:09 +0900 Subject: [PATCH 50/75] Implement SecretKey::from_pem to decode variety of keys (#2387) As suggested in https://github.com/RustCrypto/signatures/pull/1305 created API to decode SecretKey from variety of PEM encodings --------- Co-authored-by: Tony Arcieri --- elliptic-curve/src/secret_key.rs | 82 ++++++++++++++++++++++++++++++++ elliptic-curve/tests/pkcs8.rs | 23 +++++++-- 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/elliptic-curve/src/secret_key.rs b/elliptic-curve/src/secret_key.rs index 989e219af..830b8d3bd 100644 --- a/elliptic-curve/src/secret_key.rs +++ b/elliptic-curve/src/secret_key.rs @@ -293,6 +293,88 @@ where } } +#[cfg(feature = "pem")] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum PemParseError { + ///Indicates invalid PEM string + Pem(pem_rfc7468::Error), + ///Indicates invalid pkcs8 EC key + Pkcs8(::pkcs8::Error), + ///Indicates invalid Sec1 EC key + Sec1(::sec1::Error), + ///Unable to recognize document label + UnknownLabel, +} + +#[cfg(feature = "pem")] +impl From for PemParseError { + #[inline(always)] + fn from(error: pem_rfc7468::Error) -> Self { + Self::Pem(error) + } +} + +#[cfg(feature = "pem")] +impl From<::pkcs8::Error> for PemParseError { + #[inline(always)] + fn from(error: ::pkcs8::Error) -> Self { + Self::Pkcs8(error) + } +} + +#[cfg(feature = "pem")] +impl From<::sec1::Error> for PemParseError { + #[inline(always)] + fn from(error: ::sec1::Error) -> Self { + Self::Sec1(error) + } +} + +#[cfg(feature = "pem")] +impl fmt::Display for PemParseError { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Pem(error) => fmt.write_fmt(format_args!("Failed to parse PEM: {error}")), + Self::UnknownLabel => fmt.write_str("Unrecognized key label"), + Self::Pkcs8(error) => fmt.write_fmt(format_args!("Faoled to parse Pkcs8 key: {error}")), + Self::Sec1(error) => fmt.write_fmt(format_args!("Faoled to parse SEC1 key: {error}")), + } + } +} + +#[cfg(feature = "pem")] +impl core::error::Error for PemParseError {} + +#[cfg(feature = "pem")] +impl SecretKey +where + C: AssociatedOid + Curve + ValidatePublicKey, + FieldBytesSize: ModulusSize, +{ + /// Parse [`SecretKey`] from PEM-encoded private key. + /// + /// Supported formats: + /// - `SEC1` - requires feature `sec1` + /// - `PKCS #8` - requires feature `pkcs8` + /// + /// # Errors + /// - If `pem` is not valid PEM encoded private key + /// - If label within `pem` is not known valid label + /// - If label is valid, but unable to decode DER content of the PEM file + #[cfg(feature = "pem")] + pub fn from_pem(pem: &str) -> ::core::result::Result { + let label = pem_rfc7468::decode_label(pem.as_bytes()).map_err(PemParseError::Pem)?; + + if ::pkcs8::PrivateKeyInfoRef::validate_pem_label(label).is_ok() { + return ::pkcs8::DecodePrivateKey::from_pkcs8_pem(pem).map_err(PemParseError::Pkcs8); + } else if ::sec1::EcPrivateKey::validate_pem_label(label).is_ok() { + return ::sec1::DecodeEcPrivateKey::from_sec1_pem(pem).map_err(PemParseError::Sec1); + } + + Err(PemParseError::UnknownLabel) + } +} + impl ConstantTimeEq for SecretKey where C: Curve, diff --git a/elliptic-curve/tests/pkcs8.rs b/elliptic-curve/tests/pkcs8.rs index 7320de2b6..5291e481c 100644 --- a/elliptic-curve/tests/pkcs8.rs +++ b/elliptic-curve/tests/pkcs8.rs @@ -23,17 +23,34 @@ const EXAMPLE_SCALAR: [u8; 32] = hex!("AABBCCDDEEFF0000000000000000000000000000000000000000000000000001"); /// Example PKCS#8 private key -fn example_private_key() -> der::SecretDocument { +fn example_private_key_der() -> der::SecretDocument { SecretKey::from_slice(&EXAMPLE_SCALAR) .unwrap() .to_pkcs8_der() .unwrap() } +#[cfg(feature = "pem")] +/// Example PKCS#8 private key +fn example_private_key_pem() -> impl AsRef { + SecretKey::from_slice(&EXAMPLE_SCALAR) + .unwrap() + .to_pkcs8_pem(Default::default()) + .unwrap() +} + #[test] fn decode_pkcs8_private_key_from_der() { - dbg!(example_private_key().as_bytes()); - let secret_key = SecretKey::from_pkcs8_der(example_private_key().as_bytes()).unwrap(); + dbg!(example_private_key_der().as_bytes()); + let secret_key = SecretKey::from_pkcs8_der(example_private_key_der().as_bytes()).unwrap(); + assert_eq!(secret_key.to_bytes().as_slice(), &EXAMPLE_SCALAR); +} + +#[cfg(feature = "pem")] +#[test] +fn decode_pkcs8_private_key_from_pem() { + dbg!(example_private_key_pem().as_ref()); + let secret_key = SecretKey::from_pem(example_private_key_pem().as_ref()).unwrap(); assert_eq!(secret_key.to_bytes().as_slice(), &EXAMPLE_SCALAR); } From 30a48abdd75d1420e816bbc00f3c419409eac03d Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 17 Apr 2026 10:09:43 -0600 Subject: [PATCH 51/75] elliptic-curve: add `mul_by_generator(_vartime)` benchmarks (#2389) These are helpful for seeing the speedups when we add basepoint tables --- elliptic-curve/src/dev.rs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/elliptic-curve/src/dev.rs b/elliptic-curve/src/dev.rs index 4093cc24e..5b3de512c 100644 --- a/elliptic-curve/src/dev.rs +++ b/elliptic-curve/src/dev.rs @@ -14,7 +14,7 @@ pub use mock_curve::*; /// Write a series of `criterion`-based benchmarks for arithmetic on a projective curve point. #[macro_export] macro_rules! bench_projective { - ($name:ident, $desc:expr, $point_a:expr, $point_b:expr, $scalar:expr) => { + ($name:ident, $point_type:ty, $point_a:expr, $point_b:expr, $scalar:expr) => { fn bench_add( group: &mut ::criterion::BenchmarkGroup<'_, M>, ) { @@ -38,20 +38,35 @@ macro_rules! bench_projective { group.bench_function("neg", |b| b.iter(|| -x)); } - fn bench_scalar_mul( + fn bench_point_mul( group: &mut ::criterion::BenchmarkGroup<'_, M>, ) { let p = core::hint::black_box($point_a); let s = core::hint::black_box($scalar); - group.bench_function("scalar mul", |b| b.iter(|| p * s)); + group.bench_function("point-scalar mul", |b| b.iter(|| p * s)); + } + + fn bench_point_mul_by_generator( + group: &mut ::criterion::BenchmarkGroup<'_, M>, + ) { + use $crate::{group::Group, ops::MulByGeneratorVartime}; + + let s = core::hint::black_box($scalar); + group.bench_function("generator-scalar mul", |b| { + b.iter(|| ProjectivePoint::mul_by_generator(&s)) + }); + group.bench_function("generator-scalar mul (variable-time)", |b| { + b.iter(|| ProjectivePoint::mul_by_generator_vartime(&s)) + }); } pub fn $name(c: &mut ::criterion::Criterion) { - let mut group = c.benchmark_group($desc); + let mut group = c.benchmark_group(stringify!($point_type)); bench_add(&mut group); bench_sub(&mut group); bench_neg(&mut group); - bench_scalar_mul(&mut group); + bench_point_mul(&mut group); + bench_point_mul_by_generator(&mut group); group.finish(); } }; From 375378fd939d5b2952416e717364e91fc2bd7515 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Fri, 17 Apr 2026 18:15:15 +0200 Subject: [PATCH 52/75] elliptic-curve: consistent PKCS#8 / SEC1 naming in secret_key.rs (#2388) Corrects typo from https://github.com/RustCrypto/traits/pull/2387 --- elliptic-curve/src/secret_key.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/elliptic-curve/src/secret_key.rs b/elliptic-curve/src/secret_key.rs index 830b8d3bd..c0c07474b 100644 --- a/elliptic-curve/src/secret_key.rs +++ b/elliptic-curve/src/secret_key.rs @@ -296,13 +296,13 @@ where #[cfg(feature = "pem")] #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum PemParseError { - ///Indicates invalid PEM string + /// Indicates invalid PEM string Pem(pem_rfc7468::Error), - ///Indicates invalid pkcs8 EC key + /// Indicates invalid PKCS#8 EC key Pkcs8(::pkcs8::Error), - ///Indicates invalid Sec1 EC key + /// Indicates invalid SEC1 EC key Sec1(::sec1::Error), - ///Unable to recognize document label + /// Unable to recognize document label UnknownLabel, } @@ -336,8 +336,10 @@ impl fmt::Display for PemParseError { match self { Self::Pem(error) => fmt.write_fmt(format_args!("Failed to parse PEM: {error}")), Self::UnknownLabel => fmt.write_str("Unrecognized key label"), - Self::Pkcs8(error) => fmt.write_fmt(format_args!("Faoled to parse Pkcs8 key: {error}")), - Self::Sec1(error) => fmt.write_fmt(format_args!("Faoled to parse SEC1 key: {error}")), + Self::Pkcs8(error) => { + fmt.write_fmt(format_args!("Failed to parse PKCS#8 key: {error}")) + } + Self::Sec1(error) => fmt.write_fmt(format_args!("Failed to parse SEC1 key: {error}")), } } } @@ -355,7 +357,7 @@ where /// /// Supported formats: /// - `SEC1` - requires feature `sec1` - /// - `PKCS #8` - requires feature `pkcs8` + /// - `PKCS#8` - requires feature `pkcs8` /// /// # Errors /// - If `pem` is not valid PEM encoded private key From 5cb62a4def587d8da5e4b27f5f53cd5c3a4cb104 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 23 Apr 2026 08:56:20 -0600 Subject: [PATCH 53/75] signature: enable/fix workspace-level lints; reformat docs (#2391) Note: lint config was added in #2270 --- signature/Cargo.toml | 3 + signature/src/error.rs | 2 + signature/src/hazmat.rs | 107 ++++++++++--------- signature/src/lib.rs | 9 -- signature/src/signer.rs | 217 +++++++++++++++++++++++--------------- signature/src/verifier.rs | 33 +++--- 6 files changed, 213 insertions(+), 158 deletions(-) diff --git a/signature/Cargo.toml b/signature/Cargo.toml index d1951bf88..21a28883d 100644 --- a/signature/Cargo.toml +++ b/signature/Cargo.toml @@ -20,5 +20,8 @@ rand_core = { version = "0.10", optional = true, default-features = false } alloc = [] rand_core = ["dep:rand_core"] +[lints] +workspace = true + [package.metadata.docs.rs] all-features = true diff --git a/signature/src/error.rs b/signature/src/error.rs index 8a831dea6..846456575 100644 --- a/signature/src/error.rs +++ b/signature/src/error.rs @@ -30,6 +30,7 @@ pub struct Error { impl Error { /// Create a new error with no associated source + #[must_use] pub fn new() -> Self { Self::default() } @@ -90,6 +91,7 @@ impl core::error::Error for Error { None } #[cfg(feature = "alloc")] + #[allow(trivial_casts)] { self.source .as_ref() diff --git a/signature/src/hazmat.rs b/signature/src/hazmat.rs index 075fc489e..eeb84ed83 100644 --- a/signature/src/hazmat.rs +++ b/signature/src/hazmat.rs @@ -1,10 +1,14 @@ //! Hazardous Materials: low-level APIs which can be insecure if misused. //! -//! The traits in this module are not generally recommended, and should only be -//! used in special cases where they are specifically needed. +//! The traits in this module are not generally recommended, and should only be used in special +//! cases where they are specifically needed. //! -//! Using them incorrectly can introduce security vulnerabilities. Please -//! carefully read the documentation before attempting to use them. +//!
+//! Security Warning +//! +//! Using these traits incorrectly can introduce security vulnerabilities. Please carefully read the +//! documentation before attempting to use them. +//!
use crate::Error; @@ -13,36 +17,38 @@ use crate::rand_core::TryCryptoRng; /// Sign the provided message prehash, returning a digital signature. pub trait PrehashSigner { - /// Attempt to sign the given message digest, returning a digital signature - /// on success, or an error if something went wrong. + /// Attempt to sign the given message digest, returning a digital signature on success, or an + /// error if something went wrong. + /// + /// The `prehash` parameter should be the output of a secure cryptographic hash function. /// - /// The `prehash` parameter should be the output of a secure cryptographic - /// hash function. + /// This API takes a `prehash` byte slice as there can potentially be many compatible lengths + /// for the message digest for a given concrete signature algorithm. /// - /// This API takes a `prehash` byte slice as there can potentially be many - /// compatible lengths for the message digest for a given concrete signature - /// algorithm. + /// Allowed lengths are algorithm-dependent and up to a particular implementation to decide. /// - /// Allowed lengths are algorithm-dependent and up to a particular - /// implementation to decide. + /// # Errors + /// Returns [`Error`] in the event `prehash` is an invalid length. fn sign_prehash(&self, prehash: &[u8]) -> Result; } -/// Sign the provided message prehash using the provided external randomness source, returning a digital signature. +/// Sign the provided message prehash using the provided external randomness source, returning a +/// digital signature. #[cfg(feature = "rand_core")] pub trait RandomizedPrehashSigner { - /// Attempt to sign the given message digest, returning a digital signature - /// on success, or an error if something went wrong. + /// Attempt to sign the given message digest, returning a digital signature on success, or an + /// error if something went wrong. /// - /// The `prehash` parameter should be the output of a secure cryptographic - /// hash function. + /// The `prehash` parameter should be the output of a secure cryptographic hash function. /// - /// This API takes a `prehash` byte slice as there can potentially be many - /// compatible lengths for the message digest for a given concrete signature - /// algorithm. + /// This API takes a `prehash` byte slice as there can potentially be many compatible lengths + /// for the message digest for a given concrete signature algorithm. /// - /// Allowed lengths are algorithm-dependent and up to a particular - /// implementation to decide. + /// Allowed lengths are algorithm-dependent and up to a particular implementation to decide. + /// + /// # Errors + /// Returns [`Error`] in the event `prehash` is an invalid length, or if an internal error + /// in the provided `rng` occurs. fn sign_prehash_with_rng( &self, rng: &mut R, @@ -52,57 +58,54 @@ pub trait RandomizedPrehashSigner { /// Verify the provided message prehash using `Self` (e.g. a public key) pub trait PrehashVerifier { - /// Use `Self` to verify that the provided signature for a given message - /// `prehash` is authentic. + /// Use `Self` to verify that the provided signature for a given message `prehash` is authentic. + /// + /// The `prehash` parameter MUST be the output of a secure cryptographic hash function. /// - /// The `prehash` parameter should be the output of a secure cryptographic - /// hash function. + ///
+ /// Security Warning /// - /// Returns `Error` if it is inauthentic or some other error occurred, or - /// otherwise returns `Ok(())`. + /// If `prehash` is something other than the output of a cryptographically secure hash function, + /// an attacker can potentially forge signatures by e.g. solving a system of linear equations. + ///
/// - /// # ⚠️ Security Warning + /// Returns `Ok(())` if the signature verified successfully. /// - /// If `prehash` is something other than the output of a cryptographically - /// secure hash function, an attacker can potentially forge signatures by - /// solving a system of linear equations. + /// # Errors + /// Returns [`Error`] in the event the signature fails to verify or if `prehash` is an invalid + /// length. fn verify_prehash(&self, prehash: &[u8], signature: &S) -> Result<(), Error>; } /// Asynchronously sign the provided message prehash, returning a digital signature. #[allow(async_fn_in_trait)] pub trait AsyncPrehashSigner { - /// Attempt to sign the given message digest, returning a digital signature - /// on success, or an error if something went wrong. + /// Attempt to sign the given message digest, returning a digital signature on success, or an + /// error if something went wrong. /// - /// The `prehash` parameter should be the output of a secure cryptographic - /// hash function. + /// The `prehash` parameter should be the output of a secure cryptographic hash function. /// - /// This API takes a `prehash` byte slice as there can potentially be many - /// compatible lengths for the message digest for a given concrete signature - /// algorithm. + /// This API takes a `prehash` byte slice as there can potentially be many compatible lengths + /// for the message digest for a given concrete signature algorithm. /// - /// Allowed lengths are algorithm-dependent and up to a particular - /// implementation to decide. + /// Allowed lengths are algorithm-dependent and up to a particular implementation to decide. async fn sign_prehash_async(&self, prehash: &[u8]) -> Result; } -/// Asynchronously sign the provided message prehash using the provided external randomness source, returning a digital signature. +/// Asynchronously sign the provided message prehash using the provided external randomness source, +/// returning a digital signature. #[cfg(feature = "rand_core")] #[allow(async_fn_in_trait)] pub trait AsyncRandomizedPrehashSigner { - /// Attempt to sign the given message digest, returning a digital signature - /// on success, or an error if something went wrong. + /// Attempt to sign the given message digest, returning a digital signature on success, or an + /// error if something went wrong. /// - /// The `prehash` parameter should be the output of a secure cryptographic - /// hash function. + /// The `prehash` parameter should be the output of a secure cryptographic hash function. /// - /// This API takes a `prehash` byte slice as there can potentially be many - /// compatible lengths for the message digest for a given concrete signature - /// algorithm. + /// This API takes a `prehash` byte slice as there can potentially be many compatible lengths + /// for the message digest for a given concrete signature algorithm. /// - /// Allowed lengths are algorithm-dependent and up to a particular - /// implementation to decide. + /// Allowed lengths are algorithm-dependent and up to a particular implementation to decide. async fn sign_prehash_with_rng_async( &self, rng: &mut R, diff --git a/signature/src/lib.rs b/signature/src/lib.rs index e0a7b3453..dbd2d49ac 100644 --- a/signature/src/lib.rs +++ b/signature/src/lib.rs @@ -7,15 +7,6 @@ )] #![forbid(unsafe_code)] #![allow(async_fn_in_trait)] -#![warn( - clippy::mod_module_files, - clippy::unwrap_used, - missing_docs, - rust_2018_idioms, - unused_lifetimes, - missing_debug_implementations, - unused_qualifications -)] //! # Design //! diff --git a/signature/src/signer.rs b/signature/src/signer.rs index c75a90066..1057b6b07 100644 --- a/signature/src/signer.rs +++ b/signature/src/signer.rs @@ -1,4 +1,4 @@ -//! Traits for generating digital signatures +//! Traits for generating digital signatures. use crate::error::Error; @@ -8,50 +8,59 @@ use crate::digest::Update; #[cfg(feature = "rand_core")] use crate::rand_core::{CryptoRng, TryCryptoRng}; -/// Sign the provided message bytestring using `Self` (e.g. a cryptographic key -/// or connection to an HSM), returning a digital signature. +/// Sign the provided message bytestring using `Self` (e.g. a cryptographic key or connection to an +/// HSM), returning a digital signature. pub trait Signer { - /// Sign the given message and return a digital signature + /// Sign the given message and return a digital signature. fn sign(&self, msg: &[u8]) -> S { self.try_sign(msg).expect("signature operation failed") } - /// Attempt to sign the given message, returning a digital signature on - /// success, or an error if something went wrong. + /// Attempt to sign the given message, returning a digital signature on success, or an error if + /// something went wrong. + /// + /// The main intended use case for signing errors is when communicating with external signers, + /// e.g. cloud KMS, HSMs, or other hardware tokens. /// - /// The main intended use case for signing errors is when communicating - /// with external signers, e.g. cloud KMS, HSMs, or other hardware tokens. + /// # Errors + /// Returns implementation-specific errors in the event signing failed (e.g. KMS or HSM + /// communication error). fn try_sign(&self, msg: &[u8]) -> Result; } /// Equivalent of [`Signer`] but the message is provided in non-contiguous byte slices. pub trait MultipartSigner { - /// Equivalent of [`Signer::sign()`] but the message - /// is provided in non-contiguous byte slices. + /// Equivalent of [`Signer::sign()`] but the message is provided in non-contiguous byte slices. fn multipart_sign(&self, msg: &[&[u8]]) -> S { self.try_multipart_sign(msg) .expect("signature operation failed") } - /// Equivalent of [`Signer::try_sign()`] but the - /// message is provided in non-contiguous byte slices. + /// Equivalent of [`Signer::try_sign()`] but the message is provided in non-contiguous byte + /// slices. + /// + /// # Errors + /// Returns implementation-specific errors in the event signing failed (e.g. KMS or HSM + /// communication error). fn try_multipart_sign(&self, msg: &[&[u8]]) -> Result; } -/// Sign the provided message bytestring using `&mut Self` (e.g. an evolving -/// cryptographic key such as a stateful hash-based signature), returning a -/// digital signature. +/// Sign the provided message bytestring using `&mut Self` (e.g. an evolving cryptographic key such +/// as a stateful hash-based signature), returning a digital signature. pub trait SignerMut { /// Sign the given message, update the state, and return a digital signature. + /// + /// # Panics + /// In the event of a signing error. fn sign(&mut self, msg: &[u8]) -> S { self.try_sign(msg).expect("signature operation failed") } - /// Attempt to sign the given message, updating the state, and returning a - /// digital signature on success, or an error if something went wrong. + /// Attempt to sign the given message, updating the state, and returning a digital signature on + /// success, or an error if something went wrong. /// - /// Signing can fail, e.g., if the number of time periods allowed by the - /// current key is exceeded. + /// # Errors + /// Signing can fail, e.g. if the number of time periods allowed by the current key is exceeded. fn try_sign(&mut self, msg: &[u8]) -> Result; } @@ -59,30 +68,28 @@ pub trait SignerMut { /// /// ## Notes /// -/// This trait is primarily intended for signature algorithms based on the -/// [Fiat-Shamir heuristic], a method for converting an interactive -/// challenge/response-based proof-of-knowledge protocol into an offline -/// digital signature through the use of a random oracle, i.e. a digest -/// function. +/// This trait is primarily intended for signature algorithms based on the [Fiat-Shamir heuristic], +/// a method for converting an interactive challenge/response-based proof-of-knowledge protocol into +/// an offline digital signature through the use of a random oracle, i.e. a digest function. /// -/// The security of such protocols critically rests upon the inability of -/// an attacker to solve for the output of the random oracle, as generally -/// otherwise such signature algorithms are a system of linear equations and -/// therefore doing so would allow the attacker to trivially forge signatures. +/// The security of such protocols critically rests upon the inability of an attacker to solve for +/// the output of the random oracle, as generally otherwise such signature algorithms are a system +/// of linear equations and therefore doing so would allow the attacker to trivially forge +/// signatures. /// -/// To prevent misuse which would potentially allow this to be possible, this -/// API accepts a `Digest` instance, rather than a raw digest value. +/// To prevent misuse which would potentially allow this to be possible, this API accepts a `Digest` +/// instance, rather than a raw digest value. /// /// [Fiat-Shamir heuristic]: https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic #[cfg(feature = "digest")] pub trait DigestSigner { - /// Sign a message by updating the received `Digest` with it, - /// returning a signature. + /// Sign a message by updating the received `Digest` with it, returning a signature. /// - /// The given function can be invoked multiple times. It is expected that - /// in each invocation the `Digest` is updated with the entire equal message. + /// The given function can be invoked multiple times. It is expected that in each invocation the + /// `Digest` is updated with the entire equal message. /// - /// Panics in the event of a signing error. + /// # Panics + /// In the event of a signing error. fn sign_digest(&self, f: F) -> S { self.try_sign_digest(|digest| { f(digest); @@ -91,11 +98,15 @@ pub trait DigestSigner { .expect("signature operation failed") } - /// Attempt to sign a message by updating the received `Digest` with it, - /// returning a digital signature on success, or an error if something went wrong. + /// Attempt to sign a message by updating the received `Digest` with it, returning a digital + /// signature on success, or an error if something went wrong. /// - /// The given function can be invoked multiple times. It is expected that - /// in each invocation the `Digest` is updated with the entire equal message. + /// The given function can be invoked multiple times. It is expected that in each invocation the + /// `Digest` is updated with the entire equal message. + /// + /// # Errors + /// Returns implementation-specific errors in the event signing failed (e.g. KMS or HSM + /// communication error). fn try_sign_digest Result<(), Error>>(&self, f: F) -> Result; } @@ -108,11 +119,15 @@ pub trait RandomizedSigner { .expect("signature operation failed") } - /// Attempt to sign the given message, returning a digital signature on - /// success, or an error if something went wrong. + /// Attempt to sign the given message, returning a digital signature on success, or an error if + /// something went wrong. + /// + /// The main intended use case for signing errors is when communicating with external signers, + /// e.g. cloud KMS, HSMs, or other hardware tokens. /// - /// The main intended use case for signing errors is when communicating - /// with external signers, e.g. cloud KMS, HSMs, or other hardware tokens. + /// # Errors + /// Returns implementation-specific errors in the event signing failed (e.g. KMS or HSM + /// communication error), or if the provided `rng` experiences an internal failure. fn try_sign_with_rng( &self, rng: &mut R, @@ -123,15 +138,19 @@ pub trait RandomizedSigner { /// Equivalent of [`RandomizedSigner`] but the message is provided in non-contiguous byte slices. #[cfg(feature = "rand_core")] pub trait RandomizedMultipartSigner { - /// Equivalent of [`RandomizedSigner::sign_with_rng()`] but - /// the message is provided in non-contiguous byte slices. + /// Equivalent of [`RandomizedSigner::sign_with_rng()`] but the message is provided in + /// non-contiguous byte slices. fn multipart_sign_with_rng(&self, rng: &mut R, msg: &[&[u8]]) -> S { self.try_multipart_sign_with_rng(rng, msg) .expect("signature operation failed") } - /// Equivalent of [`RandomizedSigner::try_sign_with_rng()`] but - /// the message is provided in non-contiguous byte slices. + /// Equivalent of [`RandomizedSigner::try_sign_with_rng()`] but the message is provided in + /// non-contiguous byte slices. + /// + /// # Errors + /// Returns implementation-specific errors in the event signing failed (e.g. KMS or HSM + /// communication error), or if the provided `rng` experiences an internal failure. fn try_multipart_sign_with_rng( &self, rng: &mut R, @@ -139,17 +158,17 @@ pub trait RandomizedMultipartSigner { ) -> Result; } -/// Combination of [`DigestSigner`] and [`RandomizedSigner`] with support for -/// computing a signature over a digest which requires entropy from an RNG. +/// Combination of [`DigestSigner`] and [`RandomizedSigner`] with support for computing a signature +/// over a digest which requires entropy from an RNG. #[cfg(all(feature = "digest", feature = "rand_core"))] pub trait RandomizedDigestSigner { - /// Sign a message by updating the received `Digest` with it, - /// returning a signature. + /// Sign a message by updating the received `Digest` with it, returning a signature. /// - /// The given function can be invoked multiple times. It is expected that - /// in each invocation the `Digest` is updated with the entire equal message. + /// The given function can be invoked multiple times. It is expected that in each invocation the + /// `Digest` is updated with the entire equal message. /// - /// Panics in the event of a signing error. + /// # Panics + /// In the event of a signing error. fn sign_digest_with_rng(&self, rng: &mut R, f: F) -> S { self.try_sign_digest_with_rng(rng, |digest| { f(digest); @@ -158,11 +177,15 @@ pub trait RandomizedDigestSigner { .expect("signature operation failed") } - /// Attempt to sign a message by updating the received `Digest` with it, - /// returning a digital signature on success, or an error if something went wrong. + /// Attempt to sign a message by updating the received `Digest` with it, returning a digital + /// signature on success, or an error if something went wrong. + /// + /// The given function can be invoked multiple times. It is expected that in each invocation the + /// `Digest` is updated with the entire equal message. /// - /// The given function can be invoked multiple times. It is expected that - /// in each invocation the `Digest` is updated with the entire equal message. + /// # Errors + /// Returns implementation-specific errors in the event signing failed (e.g. KMS or HSM + /// communication error), or if the provided `rng` experiences an internal failure. fn try_sign_digest_with_rng Result<(), Error>>( &self, rng: &mut R, @@ -170,22 +193,26 @@ pub trait RandomizedDigestSigner { ) -> Result; } -/// Sign the provided message bytestring using `&mut Self` (e.g. an evolving -/// cryptographic key such as a stateful hash-based signature), and a per-signature -/// randomizer, returning a digital signature. +/// Sign the provided message bytestring using `&mut Self` (e.g. an evolving cryptographic key such +/// as a stateful hash-based signature), and a per-signature randomizer, returning a digital +/// signature. #[cfg(feature = "rand_core")] pub trait RandomizedSignerMut { /// Sign the given message, update the state, and return a digital signature. + /// + /// # Panics + /// In the event of a signing error. fn sign_with_rng(&mut self, rng: &mut R, msg: &[u8]) -> S { self.try_sign_with_rng(rng, msg) .expect("signature operation failed") } - /// Attempt to sign the given message, updating the state, and returning a - /// digital signature on success, or an error if something went wrong. + /// Attempt to sign the given message, updating the state, and returning a digital signature on + /// success, or an error if something went wrong. /// - /// Signing can fail, e.g., if the number of time periods allowed by the - /// current key is exceeded. + /// # Errors + /// Signing can fail, e.g. if the number of time periods allowed by the current key is exceeded, + /// or if the provided `rng` experiences an internal failure. fn try_sign_with_rng( &mut self, rng: &mut R, @@ -196,15 +223,22 @@ pub trait RandomizedSignerMut { /// Equivalent of [`RandomizedSignerMut`] but the message is provided in non-contiguous byte slices. #[cfg(feature = "rand_core")] pub trait RandomizedMultipartSignerMut { - /// Equivalent of [`RandomizedSignerMut::sign_with_rng()`] but - /// the message is provided in non-contiguous byte slices. + /// Equivalent of [`RandomizedSignerMut::sign_with_rng()`] but the message is provided in + /// non-contiguous byte slices. + /// + /// # Panics + /// In the event of a signing error. fn multipart_sign_with_rng(&mut self, rng: &mut R, msg: &[&[u8]]) -> S { self.try_multipart_sign_with_rng(rng, msg) .expect("signature operation failed") } - /// Equivalent of [`RandomizedSignerMut::try_sign_with_rng()`] - /// but the message is provided in non-contiguous byte slices. + /// Equivalent of [`RandomizedSignerMut::try_sign_with_rng()`] but the message is provided in + /// non-contiguous byte slices. + /// + /// # Errors + /// Signing can fail, e.g. if the number of time periods allowed by the current key is exceeded, + /// or if the provided `rng` experiences an internal failure. fn try_multipart_sign_with_rng( &mut self, rng: &mut R, @@ -224,16 +258,20 @@ impl> RandomizedSignerMut for T { } } -/// Asynchronously sign the provided message bytestring using `Self` -/// (e.g. client for a Cloud KMS or HSM), returning a digital signature. +/// Asynchronously sign the provided message bytestring using `Self` (e.g. client for a Cloud KMS or +/// HSM), returning a digital signature. /// /// This trait is an async equivalent of the [`Signer`] trait. pub trait AsyncSigner { - /// Attempt to sign the given message, returning a digital signature on - /// success, or an error if something went wrong. + /// Attempt to sign the given message, returning a digital signature on success, or an error if + /// something went wrong. + /// + /// The main intended use case for signing errors is when communicating with external signers, + /// e.g. cloud KMS, HSMs, or other hardware tokens. /// - /// The main intended use case for signing errors is when communicating - /// with external signers, e.g. cloud KMS, HSMs, or other hardware tokens. + /// # Errors + /// Returns implementation-specific errors in the event signing failed (e.g. KMS or HSM + /// communication error). async fn sign_async(&self, msg: &[u8]) -> Result; } @@ -254,11 +292,15 @@ pub trait AsyncDigestSigner where D: Update, { - /// Attempt to sign a message by updating the received `Digest` with it, - /// returning a digital signature on success, or an error if something went wrong. + /// Attempt to sign a message by updating the received `Digest` with it, returning a digital + /// signature on success, or an error if something went wrong. /// - /// The given function can be invoked multiple times. It is expected that - /// in each invocation the `Digest` is updated with the entire equal message. + /// The given function can be invoked multiple times. It is expected that in each invocation the + /// `Digest` is updated with the entire equal message. + /// + /// # Errors + /// Returns implementation-specific errors in the event signing failed (e.g. KMS or HSM + /// communication error). async fn sign_digest_async Result<(), Error>>( &self, f: F, @@ -268,18 +310,25 @@ where /// Sign the given message using the provided external randomness source. #[cfg(feature = "rand_core")] pub trait AsyncRandomizedSigner { - /// Sign the given message and return a digital signature + /// Sign the given message and return a digital signature. + /// + /// # Panics + /// In the event of a signing error. async fn sign_with_rng_async(&self, rng: &mut R, msg: &[u8]) -> S { self.try_sign_with_rng_async(rng, msg) .await .expect("signature operation failed") } - /// Attempt to sign the given message, returning a digital signature on - /// success, or an error if something went wrong. + /// Attempt to sign the given message, returning a digital signature on success, or an error if + /// something went wrong. + /// + /// The main intended use case for signing errors is when communicating with external signers, + /// e.g. cloud KMS, HSMs, or other hardware tokens. /// - /// The main intended use case for signing errors is when communicating - /// with external signers, e.g. cloud KMS, HSMs, or other hardware tokens. + /// # Errors + /// Returns implementation-specific errors in the event signing failed (e.g. KMS or HSM + /// communication error), or if the provided `rng` experiences an internal failure. async fn try_sign_with_rng_async( &self, rng: &mut R, diff --git a/signature/src/verifier.rs b/signature/src/verifier.rs index 0d17163e3..edaf1f924 100644 --- a/signature/src/verifier.rs +++ b/signature/src/verifier.rs @@ -1,28 +1,33 @@ -//! Trait for verifying digital signatures +//! Trait for verifying digital signatures. use crate::error::Error; #[cfg(feature = "digest")] use crate::digest::Update; -/// Verify the provided message bytestring using `Self` (e.g. a public key) +/// Verify the provided message bytestring using `Self` (e.g. a public key). pub trait Verifier { - /// Use `Self` to verify that the provided signature for a given message - /// bytestring is authentic. + /// Use `Self` (e.g. a verifying key) to verify that the provided `signature` is authentic + /// for a given message bytestring. /// - /// Returns `Error` if it is inauthentic, or otherwise returns `()`. + /// Returns `Ok(())` if the `signature` is authentic for the given message. + /// + /// # Errors + /// Returns [`Error`] if the provided `signature` is inauthentic for the given message. fn verify(&self, msg: &[u8], signature: &S) -> Result<(), Error>; } /// Equivalent of [`Verifier`] but the message is provided in non-contiguous byte slices. pub trait MultipartVerifier { - /// Equivalent of [`Verifier::verify()`] but the - /// message is provided in non-contiguous byte slices. + /// Equivalent of [`Verifier::verify()`] but the message is provided in non-contiguous byte + /// slices. + /// + /// # Errors + /// Returns [`Error`] if the provided `signature` is inauthentic for the given message. fn multipart_verify(&self, msg: &[&[u8]], signature: &S) -> Result<(), Error>; } -/// Verify the provided signature for the given prehashed message `Digest` -/// is authentic. +/// Verify the provided signature for the given prehashed message `Digest` is authentic. /// /// ## Notes /// @@ -44,11 +49,13 @@ pub trait MultipartVerifier { /// [Fiat-Shamir heuristic]: https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic #[cfg(feature = "digest")] pub trait DigestVerifier { - /// Verify the signature against the received `Digest` output, - /// by updating it with the message. + /// Verify the signature against the received `Digest` output, by updating it with the message. + /// + /// The given function can be invoked multiple times. It is expected that in each invocation the + /// `Digest` is updated with the entire equal message. /// - /// The given function can be invoked multiple times. It is expected that - /// in each invocation the `Digest` is updated with the entire equal message. + /// # Errors + /// Returns [`Error`] if the provided `signature` is inauthentic for the given message digest. fn verify_digest Result<(), Error>>( &self, f: F, From 54e464f9c64f4cdd4a9a292aa2ffa076e60a3ebf Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 23 Apr 2026 09:04:46 -0600 Subject: [PATCH 54/75] signature: remove long-winded intro section in rustdoc (#2392) Much of this is out-of-date (signature types are no longer bag-of-bytes, for example), and probably not generally helpful for understanding the litany of traits available in this crate. It might make sense to add back a similar section but it should probably be written from scratch given the current state of the crate. --- signature/src/lib.rs | 111 +++++-------------------------------------- 1 file changed, 12 insertions(+), 99 deletions(-) diff --git a/signature/src/lib.rs b/signature/src/lib.rs index dbd2d49ac..949cb78ee 100644 --- a/signature/src/lib.rs +++ b/signature/src/lib.rs @@ -10,115 +10,28 @@ //! # Design //! -//! This crate provides a common set of traits for signing and verifying -//! digital signatures intended to be implemented by libraries which produce -//! or contain implementations of digital signature algorithms, and used by -//! libraries which want to produce or verify digital signatures while -//! generically supporting any compatible backend. -//! -//! ## Goals -//! -//! The traits provided by this crate were designed with the following goals -//! in mind: -//! -//! - Provide an easy-to-use, misuse resistant API optimized for consumers -//! (as opposed to implementers) of its traits. -//! - Support common type-safe wrappers around "bag-of-bytes" representations -//! which can be directly parsed from or written to the "wire". -//! - Expose a trait/object-safe API where signers/verifiers spanning multiple -//! homogeneous provider implementations can be seamlessly leveraged together -//! in the same logical "keyring" so long as they operate on the same -//! underlying signature type. -//! - Allow one provider type to potentially implement support (including -//! being generic over) several signature types. -//! - Keep signature algorithm customizations / "knobs" out-of-band from the -//! signing/verification APIs, ideally pushing such concerns into the type -//! system so that algorithm mismatches are caught as type errors. -//! - Opaque error type which minimizes information leaked from cryptographic -//! failures, as "rich" error types in these scenarios are often a source -//! of sidechannel information for attackers (e.g. [BB'06]) -//! -//! [BB'06]: https://en.wikipedia.org/wiki/Daniel_Bleichenbacher -//! -//! ## Implementation -//! -//! To accomplish the above goals, the [`Signer`] and [`Verifier`] traits -//! provided by this are generic over a signature value, and use generic -//! parameters rather than associated types. Notably, they use such a parameter -//! for the return value, allowing it to be inferred by the type checker based -//! on the desired signature type. -//! -//! ## Alternatives considered -//! -//! This crate is based on many years of exploration of how to encapsulate -//! digital signature systems in the most flexible, developer-friendly way. -//! During that time many design alternatives were explored, tradeoffs -//! compared, and ultimately the provided API was selected. -//! -//! The tradeoffs made in this API have all been to improve simplicity, -//! ergonomics, type safety, and flexibility for *consumers* of the traits. -//! At times, this has come at a cost to implementers. Below are some concerns -//! we are cognizant of which were considered in the design of the API: -//! -//! - "Bag-of-bytes" serialization precludes signature providers from using -//! their own internal representation of a signature, which can be helpful -//! for many reasons (e.g. advanced signature system features like batch -//! verification). -//! - Associated types, rather than generic parameters of traits, could allow -//! more customization of the types used by a particular signature system, -//! e.g. using custom error types. -//! -//! It may still make sense to continue to explore the above tradeoffs, but -//! with a *new* set of traits which are intended to be implementor-friendly, -//! rather than consumer friendly. The existing [`Signer`] and [`Verifier`] -//! traits could have blanket impls for the "provider-friendly" traits. -//! However, as noted above this is a design space easily explored after -//! stabilizing the consumer-oriented traits, and thus we consider these -//! more important. -//! -//! That said, below are some caveats of trying to design such traits, and -//! why we haven't actively pursued them: -//! -//! - Generics in the return position are already used to select which trait -//! impl to use, i.e. for a particular signature algorithm/system. Avoiding -//! a unified, concrete signature type adds another dimension to complexity -//! and compiler errors, and in our experience makes them unsuitable for this -//! sort of API. We believe such an API is the natural one for signature -//! systems, reflecting the natural way they are written absent a trait. -//! - Associated types preclude multiple implementations of the same trait. -//! These parameters are common in signature systems, notably ones which -//! support different serializations of a signature (e.g. raw vs ASN.1). -//! - Digital signatures are almost always larger than the present 32-entry -//! trait impl limitation on array types, which complicates bounds -//! for these types (particularly things like `From` or `Borrow` bounds). +//! This crate provides a common set of traits for signing and verifying digital signatures intended +//! to be implemented by libraries which produce or contain implementations of digital signature +//! algorithms, and used by libraries which want to produce or verify digital signatures +//! generically. //! //! ## Unstable features //! -//! Despite being post-1.0, this crate includes off-by-default unstable -//! optional features, each of which depends on a pre-1.0 -//! crate. +//! Despite being post-1.0, this crate includes off-by-default unstable optional features, each of +//! which depends on a pre-1.0 crate. //! -//! These features are considered exempt from SemVer. See the -//! [SemVer policy](#semver-policy) above for more information. +//! These features are considered exempt from SemVer. See "SemVer Policy Exemptions" for more +//! information. //! //! The following unstable features are presently supported: //! -//! - `digest`: enables the [`DigestSigner`] and [`DigestVerifier`] -//! traits which are based on the [`Digest`] trait from the [`digest`] crate. -//! These traits are used for representing signature systems based on the -//! [Fiat-Shamir heuristic] which compute a random challenge value to sign -//! by computing a cryptographically secure digest of the input message. -//! - `rand_core`: enables the [`RandomizedSigner`] trait for signature -//! systems which rely on a cryptographically secure random number generator -//! for security. -//! -//! NOTE: the [`async-signature`] crate contains experimental `async` support -//! for [`Signer`] and [`DigestSigner`]. +//! - `digest`: enables the [`DigestSigner`] and [`DigestVerifier`] traits which are based on the +//! [`Digest`] trait from the [`digest`] crate. +//! - `rand_core`: enables the [`RandomizedSigner`] trait for signature systems which rely on a +//! cryptographically secure random number generator for security. //! -//! [`async-signature`]: https://docs.rs/async-signature //! [`digest`]: https://docs.rs/digest/ //! [`Digest`]: https://docs.rs/digest/latest/digest/trait.Digest.html -//! [Fiat-Shamir heuristic]: https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic #[cfg(feature = "alloc")] extern crate alloc; From 8250383d7e6b570c9ebe625e489c56f2dd6029a6 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 27 Apr 2026 11:04:44 -0600 Subject: [PATCH 55/75] elliptic-curve: bump `pkcs8` to v0.11.0-rc.12 (#2396) Looks like there weren't any breaking changes here --- Cargo.lock | 4 ++-- elliptic-curve/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7b1eaf0ed..141f0fb92 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -479,9 +479,9 @@ dependencies = [ [[package]] name = "pkcs8" -version = "0.11.0-rc.11" +version = "0.11.0-rc.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12922b6296c06eb741b02d7b5161e3aaa22864af38dfa025a1a3ba3f68c84577" +checksum = "9d71d6da5a0e652b5c694049095a52f5e564012b8ee5001cf10d84a4ca9a7f9d" dependencies = [ "der", "spki", diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index 4542758df..9d0f28441 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -33,7 +33,7 @@ hkdf = { version = "0.13", optional = true, default-features = false } hex-literal = { version = "1", optional = true } once_cell = { version = "1.21", optional = true, default-features = false } pem-rfc7468 = { version = "1", optional = true, features = ["alloc"] } -pkcs8 = { version = "0.11.0-rc.10", optional = true, default-features = false } +pkcs8 = { version = "0.11.0-rc.12", optional = true, default-features = false } sec1 = { version = "0.8", optional = true, features = ["ctutils", "subtle", "zeroize"] } serdect = { version = "0.4", optional = true, default-features = false, features = ["alloc"] } From f2069a20c987f69438c26944ef4d8e0fc81facad Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 27 Apr 2026 15:10:01 -0600 Subject: [PATCH 56/75] elliptic-curve: bump `pkcs8` to v0.11 (#2397) Release PR: RustCrypto/formats#2314 --- Cargo.lock | 4 ++-- elliptic-curve/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 141f0fb92..e9a3efa98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -479,9 +479,9 @@ dependencies = [ [[package]] name = "pkcs8" -version = "0.11.0-rc.12" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d71d6da5a0e652b5c694049095a52f5e564012b8ee5001cf10d84a4ca9a7f9d" +checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7" dependencies = [ "der", "spki", diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index 9d0f28441..70e9c09f8 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -33,7 +33,7 @@ hkdf = { version = "0.13", optional = true, default-features = false } hex-literal = { version = "1", optional = true } once_cell = { version = "1.21", optional = true, default-features = false } pem-rfc7468 = { version = "1", optional = true, features = ["alloc"] } -pkcs8 = { version = "0.11.0-rc.12", optional = true, default-features = false } +pkcs8 = { version = "0.11", optional = true, default-features = false } sec1 = { version = "0.8", optional = true, features = ["ctutils", "subtle", "zeroize"] } serdect = { version = "0.4", optional = true, default-features = false, features = ["alloc"] } From c6d4dd7bd6253329161c32cb81a424e85f943429 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 28 Apr 2026 09:08:06 -0600 Subject: [PATCH 57/75] elliptic-curve v0.14.0-rc.32 (#2399) Includes `pkcs8` v0.11 update --- Cargo.lock | 2 +- elliptic-curve/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e9a3efa98..2fb09ac88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -229,7 +229,7 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.14.0-rc.31" +version = "0.14.0-rc.32" dependencies = [ "base16ct", "crypto-bigint", diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index 70e9c09f8..38e95b5df 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "elliptic-curve" -version = "0.14.0-rc.31" +version = "0.14.0-rc.32" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" From 7b029ba3b65016a6c3e1070d3b1eb740b0a072ae Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili <21236+Gozala@users.noreply.github.com> Date: Fri, 1 May 2026 06:35:44 -0700 Subject: [PATCH 58/75] signature: add `AsyncVerifier`, `AsyncMultipartVerifier`, `AsyncDigestVerifier` (#2288) Submission per #2287 --- signature/src/verifier.rs | 55 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/signature/src/verifier.rs b/signature/src/verifier.rs index edaf1f924..b6b2d396b 100644 --- a/signature/src/verifier.rs +++ b/signature/src/verifier.rs @@ -62,3 +62,58 @@ pub trait DigestVerifier { signature: &S, ) -> Result<(), Error>; } + +/// Asynchronously verify the provided message bytestring using `Self`. +/// +/// This trait is an async equivalent of the [`Verifier`] trait. +pub trait AsyncVerifier { + /// Asynchronously verify that the provided signature for a given message + /// bytestring is authentic. + /// + /// Returns `Error` if it is inauthentic, or otherwise returns `()`. + async fn verify_async(&self, msg: &[u8], signature: &S) -> Result<(), Error>; +} + +impl AsyncVerifier for T +where + T: Verifier, +{ + async fn verify_async(&self, msg: &[u8], signature: &S) -> Result<(), Error> { + self.verify(msg, signature) + } +} + +/// Asynchronous equivalent of [`MultipartVerifier`] where the message is +/// provided in non-contiguous byte slices. +/// +/// This trait is an async equivalent of the [`MultipartVerifier`] trait. +pub trait AsyncMultipartVerifier { + /// Async equivalent of [`MultipartVerifier::multipart_verify()`] where the + /// message is provided in non-contiguous byte slices. + async fn multipart_verify_async(&self, msg: &[&[u8]], signature: &S) -> Result<(), Error>; +} + +impl AsyncMultipartVerifier for T +where + T: MultipartVerifier, +{ + async fn multipart_verify_async(&self, msg: &[&[u8]], signature: &S) -> Result<(), Error> { + self.multipart_verify(msg, signature) + } +} + +/// Asynchronously verify the provided signature for the given prehashed +/// message `Digest` is authentic. +#[cfg(feature = "digest")] +pub trait AsyncDigestVerifier { + /// Asynchronously verify the signature against the received `Digest` + /// output, by updating it with the message. + /// + /// The given function can be invoked multiple times. It is expected that + /// in each invocation the `Digest` is updated with the entire equal message. + async fn verify_digest_async Result<(), Error>>( + &self, + f: F, + signature: &S, + ) -> Result<(), Error>; +} From 2917d19a11b3fd6345d6e5b801e3372d27f56ef9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 08:26:27 -0600 Subject: [PATCH 59/75] build(deps): bump the all-deps group across 1 directory with 4 updates (#2398) --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2fb09ac88..a18550531 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,9 +56,9 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "bitvec" @@ -329,9 +329,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" +checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" dependencies = [ "subtle", "typenum", @@ -392,9 +392,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.185" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "log" @@ -715,9 +715,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "unicode-ident" From 9488e7ea66763b5cbdc7a4814a96421e0114dc97 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 2 May 2026 10:29:07 -0600 Subject: [PATCH 60/75] signature v3.0.0 (#2400) ## Added - `RandomizedSignerMut` trait (#1448) - `core::error::Error` support (#1711) - Async traits incorporated from the `async-signature` crate (#1720, #2288) - `MultipartSigner` and `MultipartVerifier` traits (#1880) ## Changed - Edition changed to 2024 and MSRV bumped to 1.85 (#1759) - Use `Fn(&mut D)` for `*DigestSigner`/`*DigestVerifier` (#2004) - Bump `rand_core` to v0.10 (#2250) - Bump `digest` to v0.11 (#2300) ## Removed - Error source from display message (#1689) - `std` feature (#1829) - `derive` feature (#1843) - `SignerMut` blanket implementation for `Signer` (#1915) - `PrehashSignature` trait (#1924) --- Cargo.lock | 2 +- signature/CHANGELOG.md | 27 ++++++++++++++++++++++----- signature/Cargo.toml | 2 +- signature/LICENSE-MIT | 2 +- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a18550531..25c3d3d66 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -663,7 +663,7 @@ dependencies = [ [[package]] name = "signature" -version = "3.0.0-rc.10" +version = "3.0.0" dependencies = [ "digest", "rand_core", diff --git a/signature/CHANGELOG.md b/signature/CHANGELOG.md index 97d19b94c..866b67382 100644 --- a/signature/CHANGELOG.md +++ b/signature/CHANGELOG.md @@ -4,23 +4,40 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 3.0.0 (UNRELEASED) +## 3.0.0 (2026-05-02) ### Added - `RandomizedSignerMut` trait ([#1448]) +- `core::error::Error` support ([#1711]) +- Async traits incorporated from the `async-signature` crate ([#1720], [#2288]) +- `MultipartSigner` and `MultipartVerifier` traits ([#1880]) ### Changed - Edition changed to 2024 and MSRV bumped to 1.85 ([#1759]) +- Use `Fn(&mut D)` for `*DigestSigner`/`*DigestVerifier` ([#2004]) - Bump `rand_core` to v0.10 ([#2250]) +- Bump `digest` to v0.11 ([#2300]) ### Removed -- `std` feature - replaced with `core::error::Error` -- `derive` feature -- `SignerMut` blanket implementation for `Signer` -- `PrehashSignature` trait +- Error source from display message ([#1689]) +- `std` feature ([#1829]) +- `derive` feature ([#1843]) +- `SignerMut` blanket implementation for `Signer` ([#1915]) +- `PrehashSignature` trait ([#1924]) [#1448]: https://github.com/RustCrypto/traits/pull/1448 +[#1689]: https://github.com/RustCrypto/traits/pull/1689 +[#1711]: https://github.com/RustCrypto/traits/pull/1711 +[#1720]: https://github.com/RustCrypto/traits/pull/1720 [#1759]: https://github.com/RustCrypto/traits/pull/1759 +[#1829]: https://github.com/RustCrypto/traits/pull/1829 +[#1843]: https://github.com/RustCrypto/traits/pull/1843 +[#1880]: https://github.com/RustCrypto/traits/pull/1880 +[#1915]: https://github.com/RustCrypto/traits/pull/1915 +[#1924]: https://github.com/RustCrypto/traits/pull/1924 +[#2004]: https://github.com/RustCrypto/traits/pull/2004 [#2250]: https://github.com/RustCrypto/traits/pull/2250 +[#2288]: https://github.com/RustCrypto/traits/pull/2288 +[#2300]: https://github.com/RustCrypto/traits/pull/2300 ## 2.2.0 (2023-11-12) ### Changed diff --git a/signature/Cargo.toml b/signature/Cargo.toml index 21a28883d..f61b5d83e 100644 --- a/signature/Cargo.toml +++ b/signature/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "signature" -version = "3.0.0-rc.10" +version = "3.0.0" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" diff --git a/signature/LICENSE-MIT b/signature/LICENSE-MIT index d767644da..b887850cc 100644 --- a/signature/LICENSE-MIT +++ b/signature/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2018-2025 RustCrypto Developers +Copyright (c) 2018-2026 RustCrypto Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated From 086cf3848998dae35542088cc4d95b5c7f581827 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Sun, 3 May 2026 15:48:55 +0300 Subject: [PATCH 61/75] digest: add `TryCustomizedInit` trait (#2395) Some algorithms (e.g. Ascon-CXOF128 and `bash-prg-hash`) place restrictions on customization strings, so with the current version of `digest` we either have to panic on invalid strings or use inherent methods. This PR amends this by introducing a fallible variant of `CustomizedInit` with the blanket impl to act as a bridge between the traits. --- digest/CHANGELOG.md | 2 ++ digest/src/lib.rs | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/digest/CHANGELOG.md b/digest/CHANGELOG.md index de9d690e9..82e084678 100644 --- a/digest/CHANGELOG.md +++ b/digest/CHANGELOG.md @@ -8,8 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 0.11.3 (UNRELEASED) ### Added - `dev::initialized_mac_test` function ([#2367]) +- `TryCustomizedInit` trait ([#2395]) [#2367]: https://github.com/RustCrypto/traits/pull/2367 +[#2395]: https://github.com/RustCrypto/traits/pull/2395 ## 0.11.2 (2026-03-13) ### Changed diff --git a/digest/src/lib.rs b/digest/src/lib.rs index 704556f3a..95492c96e 100644 --- a/digest/src/lib.rs +++ b/digest/src/lib.rs @@ -205,6 +205,27 @@ pub trait CustomizedInit: Sized { fn new_customized(customization: &[u8]) -> Self; } +/// Trait for hash functions with customization string for domain separation which place +/// restrictions on customization strings. +pub trait TryCustomizedInit: Sized { + /// Error returned for invalid customization strings. + type Error; + + /// Create new hasher instance with the given customization string. + /// + /// # Errors + /// If the provided customization string is not valid for the hash function. + fn try_new_customized(customization: &[u8]) -> Result; +} + +impl TryCustomizedInit for T { + type Error = core::convert::Infallible; + + fn try_new_customized(customization: &[u8]) -> Result { + Ok(Self::new_customized(customization)) + } +} + /// Types with a certain collision resistance. pub trait CollisionResistance { /// Collision resistance in bytes. From 2fb9ed8922e244117040bb037a7d141a6a2b8228 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Sun, 3 May 2026 15:53:30 +0300 Subject: [PATCH 62/75] Release digest v0.11.3 (#2402) ### Added - `dev::initialized_mac_test` function ([#2367]) - `TryCustomizedInit` trait ([#2395]) [#2367]: https://github.com/RustCrypto/traits/pull/2367 [#2395]: https://github.com/RustCrypto/traits/pull/2395 --- Cargo.lock | 20 +++++++++++++------- digest/CHANGELOG.md | 2 +- digest/Cargo.toml | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 25c3d3d66..b6447f941 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -135,9 +135,9 @@ checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" [[package]] name = "cpubits" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef0c543070d296ea414df2dd7625d1b24866ce206709d8a4a424f28377f5861" +checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" [[package]] name = "cpufeatures" @@ -216,7 +216,7 @@ dependencies = [ [[package]] name = "digest" -version = "0.11.2" +version = "0.11.3" dependencies = [ "blobby", "block-buffer", @@ -741,11 +741,11 @@ dependencies = [ [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.46.0", ] [[package]] @@ -754,7 +754,7 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.51.0", ] [[package]] @@ -791,6 +791,12 @@ dependencies = [ "semver", ] +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + [[package]] name = "wit-bindgen" version = "0.51.0" diff --git a/digest/CHANGELOG.md b/digest/CHANGELOG.md index 82e084678..9d0759017 100644 --- a/digest/CHANGELOG.md +++ b/digest/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.11.3 (UNRELEASED) +## 0.11.3 (2026-04-03) ### Added - `dev::initialized_mac_test` function ([#2367]) - `TryCustomizedInit` trait ([#2395]) diff --git a/digest/Cargo.toml b/digest/Cargo.toml index 476e0d41c..a696a82e8 100644 --- a/digest/Cargo.toml +++ b/digest/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "digest" -version = "0.11.2" +version = "0.11.3" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" From 226be946ce949b5af00499a8a579557d897d2b87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 05:47:30 +0300 Subject: [PATCH 63/75] ci: bump crate-ci/typos from 1.45.0 to 1.46.0 (#2403) --- .github/workflows/workspace.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index 9f39d6e3a..191c5e49d 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -56,7 +56,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - uses: crate-ci/typos@v1.45.0 + - uses: crate-ci/typos@v1.46.0 lock: name: Check Cargo.lock From f896a76d4468f1ff855b651124fd5b5378a3417f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 07:18:21 -0600 Subject: [PATCH 64/75] build(deps): bump serdect from 0.4.2 to 0.4.3 in the all-deps group (#2404) --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b6447f941..3cb0426da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -642,9 +642,9 @@ dependencies = [ [[package]] name = "serdect" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9af4a3e75ebd5599b30d4de5768e00b5095d518a79fefc3ecbaf77e665d1ec06" +checksum = "66cf8fedced2fcf12406bcb34223dffb92eaf34908ede12fed414c82b7f00b3e" dependencies = [ "base16ct", "serde", From 95838a01bd186da138211685a338cac7185f950e Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 6 May 2026 21:38:45 -0600 Subject: [PATCH 65/75] elliptic-curve: add `BasepointTableVartime::lincomb` (#2405) Uses `WnafBase::multiscalar_mul` added in RustCrypto/group#14 to provide a variable-time linear combination operation which can use the precomputed wNAF for a basepoint. This has been tested in `p256` where it provides a 25% speedup for ECDSA verification. --- Cargo.lock | 3 +- Cargo.toml | 2 ++ elliptic-curve/src/point/basepoint_table.rs | 31 +++++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3cb0426da..ba3167679 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -569,8 +569,7 @@ dependencies = [ [[package]] name = "rustcrypto-group" version = "0.14.0-rc.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "369f9b61aa45933c062c9f6b5c3c50ab710687eca83dd3802653b140b43f85ed" +source = "git+https://github.com/RustCrypto/group#d5ef2775cb66a10085c9ec48432c51cad4e7b3ee" dependencies = [ "rand_core", "rustcrypto-ff", diff --git a/Cargo.toml b/Cargo.toml index 79c85b5b2..ec248c5ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,3 +57,5 @@ unused_qualifications = "warn" crypto-common = { path = "crypto-common" } digest = { path = "digest" } signature = { path = "signature" } + +rustcrypto-group = { git = "https://github.com/RustCrypto/group" } diff --git a/elliptic-curve/src/point/basepoint_table.rs b/elliptic-curve/src/point/basepoint_table.rs index fe3d88ea1..125dd20ef 100644 --- a/elliptic-curve/src/point/basepoint_table.rs +++ b/elliptic-curve/src/point/basepoint_table.rs @@ -98,6 +98,7 @@ impl Deref for BasepointTable Point { self.table.mul(&WnafScalar::new(scalar)) } + + /// Multiply `Point::generator` by the given scalar in variable-time, then compute a linear + /// combination of the remaining points and scalars, i.e. + /// + /// ```text + /// scalar * G + scalars[0] * Points[0] + ... + /// ``` + pub fn lincomb( + &self, + scalar: &Point::Scalar, + points_and_scalars: &[(Point, Point::Scalar)], + ) -> Point { + let mut bases = Vec::with_capacity(points_and_scalars.len() + 1); + bases.push(self.table.clone()); + bases.extend( + points_and_scalars + .iter() + .map(|(point, _)| WnafBase::new(*point)), + ); + + let mut scalars = Vec::with_capacity(points_and_scalars.len() + 1); + scalars.push(WnafScalar::new(scalar)); + scalars.extend( + points_and_scalars + .iter() + .map(|(_, scalar)| WnafScalar::new(scalar)), + ); + + WnafBase::multiscalar_mul(scalars.iter(), bases.iter()) + } } impl Default for BasepointTableVartime { From e4f7a9173a370bd90834a4fde68a01126b6c59cb Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 11 May 2026 15:54:26 -0600 Subject: [PATCH 66/75] elliptic-curve: add `SecretKey::from_der` (#2408) Adds a method that attempts parsing as either PKCS#8 or SEC1, depending on enabled crate features. This also exposes the decoding error type as `DecodeError`. --- elliptic-curve/src/error.rs | 71 ++++++++++ elliptic-curve/src/lib.rs | 2 + elliptic-curve/src/secret_key.rs | 214 ++++++++++++++----------------- 3 files changed, 169 insertions(+), 118 deletions(-) diff --git a/elliptic-curve/src/error.rs b/elliptic-curve/src/error.rs index 1944839bc..d7bafd013 100644 --- a/elliptic-curve/src/error.rs +++ b/elliptic-curve/src/error.rs @@ -5,6 +5,10 @@ use core::fmt::{self, Display}; /// Result type with the `elliptic-curve` crate's [`Error`] type. pub type Result = core::result::Result; +/// Result type for [`DecodeError`]. +#[cfg(any(feature = "pkcs8", feature = "sec1"))] +pub type DecodeResult = core::result::Result; + /// Elliptic curve errors. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Error; @@ -42,3 +46,70 @@ impl From for Error { Error } } + +/// Decoding errors for elliptic curve keys. +#[cfg(feature = "sec1")] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum DecodeError { + /// Invalid PEM. + #[cfg(feature = "pem")] + Pem(pem_rfc7468::Error), + + /// Indicates invalid PKCS#8 EC key + #[cfg(feature = "pkcs8")] + Pkcs8(::pkcs8::Error), + + /// Indicates invalid SEC1 EC key + Sec1(::sec1::Error), +} + +#[cfg(feature = "pem")] +impl From for DecodeError { + #[inline(always)] + fn from(error: pem_rfc7468::Error) -> Self { + Self::Pem(error) + } +} + +#[cfg(feature = "pkcs8")] +impl From<::pkcs8::Error> for DecodeError { + #[inline(always)] + fn from(error: ::pkcs8::Error) -> Self { + Self::Pkcs8(error) + } +} + +#[cfg(feature = "sec1")] +impl From<::sec1::Error> for DecodeError { + #[inline(always)] + fn from(error: ::sec1::Error) -> Self { + Self::Sec1(error) + } +} + +#[cfg(feature = "sec1")] +impl Display for DecodeError { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + #[cfg(feature = "pem")] + Self::Pem(error) => write!(fmt, "couldn't parse PEM: {error}"), + #[cfg(feature = "pkcs8")] + Self::Pkcs8(error) => write!(fmt, "couldn't parse PKCS#8 key: {error}"), + Self::Sec1(error) => write!(fmt, "couldn't parse SEC1 key: {error}"), + } + } +} + +#[cfg(feature = "sec1")] +impl core::error::Error for DecodeError { + fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { + match self { + #[cfg(feature = "pem")] + Self::Pem(error) => Some(error), + #[cfg(feature = "pkcs8")] + Self::Pkcs8(error) => Some(error), + Self::Sec1(error) => Some(error), + } + } +} diff --git a/elliptic-curve/src/lib.rs b/elliptic-curve/src/lib.rs index e2f3c3a12..0ee691ebb 100644 --- a/elliptic-curve/src/lib.rs +++ b/elliptic-curve/src/lib.rs @@ -114,6 +114,8 @@ pub use { group::{self, Curve as CurveGroup, Group}, }; +#[cfg(any(feature = "pkcs8", feature = "sec1"))] +pub use crate::error::{DecodeError, DecodeResult}; #[cfg(feature = "pkcs8")] pub use pkcs8; diff --git a/elliptic-curve/src/secret_key.rs b/elliptic-curve/src/secret_key.rs index c0c07474b..1011130b6 100644 --- a/elliptic-curve/src/secret_key.rs +++ b/elliptic-curve/src/secret_key.rs @@ -16,24 +16,14 @@ use rand_core::{CryptoRng, TryCryptoRng}; use subtle::{Choice, ConstantTimeEq, CtOption}; use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing}; -#[cfg(feature = "arithmetic")] -use crate::{CurveArithmetic, NonZeroScalar, PublicKey}; - #[cfg(feature = "ecdh")] use crate::ecdh; - +#[cfg(feature = "arithmetic")] +use crate::{CurveArithmetic, NonZeroScalar, PublicKey}; +#[cfg(all(feature = "arithmetic", feature = "pem"))] +use alloc::string::String; #[cfg(feature = "pem")] use pem_rfc7468::{self as pem, PemLabel}; - -#[cfg(feature = "sec1")] -use { - crate::{ - FieldBytesSize, - sec1::{ModulusSize, Sec1Point, ValidatePublicKey}, - }, - sec1::der::{self, Decode, oid::AssociatedOid}, -}; - #[cfg(all(feature = "alloc", feature = "arithmetic", feature = "sec1"))] use { crate::{ @@ -43,9 +33,14 @@ use { alloc::vec::Vec, sec1::der::Encode, }; - -#[cfg(all(feature = "arithmetic", feature = "pem"))] -use alloc::string::String; +#[cfg(feature = "sec1")] +use { + crate::{ + DecodeError, DecodeResult, FieldBytesSize, + sec1::{ModulusSize, Sec1Point, ValidatePublicKey}, + }, + sec1::der::{self, Decode, oid::AssociatedOid}, +}; #[cfg(all(doc, feature = "pkcs8"))] use {crate::pkcs8::DecodePrivateKey, core::str::FromStr}; @@ -88,7 +83,7 @@ where /// Minimum allowed size of an elliptic curve secret key in bytes. /// /// This provides the equivalent of 96-bits of symmetric security. - const MIN_SIZE: usize = 24; + pub const MIN_SIZE: usize = 24; /// Create a new secret key from a scalar value. /// @@ -102,22 +97,22 @@ where /// Borrow the inner secret [`ScalarValue`] value. /// - /// # ⚠️ Warning - /// - /// This value is key material. + ///
+ /// Security Warning /// - /// Please treat it with the care it deserves! + /// This value is key material. Please treat it with the care it deserves! + ///
pub fn as_scalar_value(&self) -> &ScalarValue { &self.inner } /// Get the secret [`NonZeroScalar`] value for this key. /// - /// # ⚠️ Warning + ///
+ /// Security Warning /// - /// This value is key material. - /// - /// Please treat it with the care it deserves! + /// This value is key material. Please treat it with the care it deserves! + ///
#[cfg(feature = "arithmetic")] pub fn to_nonzero_scalar(&self) -> NonZeroScalar where @@ -194,20 +189,87 @@ where ecdh::diffie_hellman(self.to_nonzero_scalar(), public_key.as_affine()) } + /// Decode [`SecretKey`] from DER-encoded private key. + /// + /// # Supported formats + /// - PKCS#8: requires `pkcs8` feature + /// - SEC1: requires `sec1` feature + /// + /// If you are expecting one format over the other, it's better to use a more specific method: + /// - PKCS#8: [`::pkcs8::DecodePrivateKey::from_pkcs8_der`] + /// - SEC1: [`::sec1::DecodeEcPrivateKey::from_sec1_der`] + /// + /// # Errors + /// - Returns [`DecodeError::Pkcs8`] if PKCS#8 key could not be decoded + /// - Returns [`DecodeError::Sec1`] if SEC1 key could not be decoded + #[cfg(any(feature = "pkcs8", feature = "sec1"))] + #[allow(clippy::missing_panics_doc, reason = "should not panic")] + pub fn from_der(der_bytes: &[u8]) -> DecodeResult + where + C: AssociatedOid + Curve + ValidatePublicKey, + FieldBytesSize: ModulusSize, + { + #[allow(unused_assignments)] + let mut err: Option = None; + + #[cfg(feature = "pkcs8")] + match ::pkcs8::DecodePrivateKey::from_pkcs8_der(der_bytes) { + Ok(sk) => return Ok(sk), + Err(e) => err = Some(e.into()), + } + + #[cfg(feature = "sec1")] + match Self::from_sec1_der(der_bytes) { + Ok(sk) => return Ok(sk), + Err(e) => { + // Insert if we don't already have a PKCS#8 error + let _ = err.get_or_insert(e); + } + } + + Err(err.expect("should be set")) + } + + /// Decode [`SecretKey`] from PEM-encoded private key. + /// + /// If you are expecting one format over the other, it's better to use a more specific method: + /// - PKCS#8: [`::pkcs8::DecodePrivateKey::from_pkcs8_pem`] + /// - SEC1: [`::sec1::DecodeEcPrivateKey::from_sec1_pem`] + /// + /// # Errors + /// - Returns [`DecodeError::Pem`] if PEM label is invalid or otherwise malformed + /// - Returns [`DecodeError::Pkcs8`] if PKCS#8 key detected but could not be decoded + /// - Returns [`DecodeError::Sec1`] if SEC1 key detected but could not be decoded + #[cfg(feature = "pem")] + pub fn from_pem(pem: &str) -> DecodeResult + where + C: AssociatedOid + Curve + ValidatePublicKey, + FieldBytesSize: ModulusSize, + { + let label = pem_rfc7468::decode_label(pem.as_bytes()).map_err(DecodeError::Pem)?; + + if ::pkcs8::PrivateKeyInfoRef::validate_pem_label(label).is_ok() { + return ::pkcs8::DecodePrivateKey::from_pkcs8_pem(pem).map_err(DecodeError::Pkcs8); + } else if ::sec1::EcPrivateKey::validate_pem_label(label).is_ok() { + return ::sec1::DecodeEcPrivateKey::from_sec1_pem(pem).map_err(DecodeError::Sec1); + } + + Err(pem_rfc7468::Error::Label.into()) + } + /// Deserialize secret key encoded in the SEC1 ASN.1 DER `ECPrivateKey` format. /// /// # Errors /// - if `der_bytes` does not encode a valid SEC1 private key /// - if the contained document does not encode a valid key for this curve #[cfg(feature = "sec1")] - pub fn from_sec1_der(der_bytes: &[u8]) -> Result + pub fn from_sec1_der(der_bytes: &[u8]) -> DecodeResult where C: AssociatedOid + Curve + ValidatePublicKey, FieldBytesSize: ModulusSize, { - sec1::EcPrivateKey::try_from(der_bytes)? - .try_into() - .map_err(|_| Error) + let sec1_key = sec1::EcPrivateKey::try_from(der_bytes)?; + Self::try_from(sec1_key).map_err(|e| DecodeError::Sec1(e.into())) } /// Serialize secret key in the SEC1 ASN.1 DER `ECPrivateKey` format. @@ -249,18 +311,18 @@ where /// - if the document cannot be decoded as PEM /// - if the PEM document does not encode a valid private key for this curve #[cfg(feature = "pem")] - pub fn from_sec1_pem(s: &str) -> Result + pub fn from_sec1_pem(s: &str) -> DecodeResult where C: AssociatedOid + Curve + ValidatePublicKey, FieldBytesSize: ModulusSize, { - let (label, der_bytes) = pem::decode_vec(s.as_bytes()).map_err(|_| Error)?; + let (label, der_bytes) = pem::decode_vec(s.as_bytes()).map_err(DecodeError::Pem)?; if label != sec1::EcPrivateKey::PEM_LABEL { - return Err(Error); + return Err(pem_rfc7468::Error::Label.into()); } - Self::from_sec1_der(&der_bytes).map_err(|_| Error) + Self::from_sec1_der(&der_bytes) } /// Serialize private key as self-zeroizing PEM-encoded SEC1 `ECPrivateKey` @@ -293,90 +355,6 @@ where } } -#[cfg(feature = "pem")] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum PemParseError { - /// Indicates invalid PEM string - Pem(pem_rfc7468::Error), - /// Indicates invalid PKCS#8 EC key - Pkcs8(::pkcs8::Error), - /// Indicates invalid SEC1 EC key - Sec1(::sec1::Error), - /// Unable to recognize document label - UnknownLabel, -} - -#[cfg(feature = "pem")] -impl From for PemParseError { - #[inline(always)] - fn from(error: pem_rfc7468::Error) -> Self { - Self::Pem(error) - } -} - -#[cfg(feature = "pem")] -impl From<::pkcs8::Error> for PemParseError { - #[inline(always)] - fn from(error: ::pkcs8::Error) -> Self { - Self::Pkcs8(error) - } -} - -#[cfg(feature = "pem")] -impl From<::sec1::Error> for PemParseError { - #[inline(always)] - fn from(error: ::sec1::Error) -> Self { - Self::Sec1(error) - } -} - -#[cfg(feature = "pem")] -impl fmt::Display for PemParseError { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Pem(error) => fmt.write_fmt(format_args!("Failed to parse PEM: {error}")), - Self::UnknownLabel => fmt.write_str("Unrecognized key label"), - Self::Pkcs8(error) => { - fmt.write_fmt(format_args!("Failed to parse PKCS#8 key: {error}")) - } - Self::Sec1(error) => fmt.write_fmt(format_args!("Failed to parse SEC1 key: {error}")), - } - } -} - -#[cfg(feature = "pem")] -impl core::error::Error for PemParseError {} - -#[cfg(feature = "pem")] -impl SecretKey -where - C: AssociatedOid + Curve + ValidatePublicKey, - FieldBytesSize: ModulusSize, -{ - /// Parse [`SecretKey`] from PEM-encoded private key. - /// - /// Supported formats: - /// - `SEC1` - requires feature `sec1` - /// - `PKCS#8` - requires feature `pkcs8` - /// - /// # Errors - /// - If `pem` is not valid PEM encoded private key - /// - If label within `pem` is not known valid label - /// - If label is valid, but unable to decode DER content of the PEM file - #[cfg(feature = "pem")] - pub fn from_pem(pem: &str) -> ::core::result::Result { - let label = pem_rfc7468::decode_label(pem.as_bytes()).map_err(PemParseError::Pem)?; - - if ::pkcs8::PrivateKeyInfoRef::validate_pem_label(label).is_ok() { - return ::pkcs8::DecodePrivateKey::from_pkcs8_pem(pem).map_err(PemParseError::Pkcs8); - } else if ::sec1::EcPrivateKey::validate_pem_label(label).is_ok() { - return ::sec1::DecodeEcPrivateKey::from_sec1_pem(pem).map_err(PemParseError::Sec1); - } - - Err(PemParseError::UnknownLabel) - } -} - impl ConstantTimeEq for SecretKey where C: Curve, From ff5fd17f3879ebc7e24db883f3927d0336dd1ef6 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Tue, 12 May 2026 16:47:19 +0300 Subject: [PATCH 67/75] elliptic-curve: disable minimal-versions CI job (#2412) The minimal versions job was broken (see [RustCrypto/actions#59]), fixing it reveals that `elliptic-curve` still can not be built with minimal dependency versions (see this [run][1]). [RustCrypto/actions#59]: https://github.com/RustCrypto/actions/pull/59 [1]: https://github.com/RustCrypto/traits/actions/runs/25738115143/job/75580587369 --- .github/workflows/elliptic-curve.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/elliptic-curve.yml b/.github/workflows/elliptic-curve.yml index 61381f529..3c0de3691 100644 --- a/.github/workflows/elliptic-curve.yml +++ b/.github/workflows/elliptic-curve.yml @@ -62,6 +62,7 @@ jobs: - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc,digest,ecdh,pem,pkcs8,sec1,serde minimal-versions: + if: false uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} From 4e999e39bc425d3c88a05183eb4b7b35b5932552 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Tue, 12 May 2026 16:50:45 +0300 Subject: [PATCH 68/75] digest: remove unused file (#2411) It was missed in https://github.com/RustCrypto/traits/pull/2043. Noticed by Francisco Gouveia. --- digest/src/dev/variable.rs | 79 -------------------------------------- 1 file changed, 79 deletions(-) delete mode 100644 digest/src/dev/variable.rs diff --git a/digest/src/dev/variable.rs b/digest/src/dev/variable.rs deleted file mode 100644 index aab77a38b..000000000 --- a/digest/src/dev/variable.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::{VariableOutput, VariableOutputReset, dev::TestVector}; - -/// Variable-output resettable digest test -pub fn variable_reset_test( - &TestVector { input, output }: &TestVector, -) -> Result<(), &'static str> { - let mut hasher = D::new(output.len()).unwrap(); - let mut buf = [0u8; 128]; - let buf = &mut buf[..output.len()]; - // Test that it works when accepting the message all at once - hasher.update(input); - let mut hasher2 = hasher.clone(); - hasher.finalize_variable(buf).unwrap(); - if buf != output { - return Err("whole message"); - } - buf.iter_mut().for_each(|b| *b = 0); - - // Test if reset works correctly - hasher2.reset(); - hasher2.update(input); - hasher2.finalize_variable_reset(buf).unwrap(); - if buf != output { - return Err("whole message after reset"); - } - buf.iter_mut().for_each(|b| *b = 0); - - // Test that it works when accepting the message in chunks - for n in 1..core::cmp::min(17, input.len()) { - let mut hasher = D::new(output.len()).unwrap(); - for chunk in input.chunks(n) { - hasher.update(chunk); - hasher2.update(chunk); - } - hasher.finalize_variable(buf).unwrap(); - if buf != output { - return Err("message in chunks"); - } - buf.iter_mut().for_each(|b| *b = 0); - - hasher2.finalize_variable_reset(buf).unwrap(); - if buf != output { - return Err("message in chunks"); - } - buf.iter_mut().for_each(|b| *b = 0); - } - - Ok(()) -} - -/// Variable-output resettable digest test -pub fn variable_test( - &TestVector { input, output }: &TestVector, -) -> Result<(), &'static str> { - let mut hasher = D::new(output.len()).unwrap(); - let mut buf = [0u8; 128]; - let buf = &mut buf[..output.len()]; - // Test that it works when accepting the message all at once - hasher.update(input); - hasher.finalize_variable(buf).unwrap(); - if buf != output { - return Err("whole message"); - } - buf.iter_mut().for_each(|b| *b = 0); - - // Test that it works when accepting the message in chunks - for n in 1..core::cmp::min(17, input.len()) { - let mut hasher = D::new(output.len()).unwrap(); - for chunk in input.chunks(n) { - hasher.update(chunk); - } - hasher.finalize_variable(buf).unwrap(); - if buf != output { - return Err("message in chunks"); - } - buf.iter_mut().for_each(|b| *b = 0); - } - Ok(()) -} From 5debc663a4f5d4d39ebba07277c2dc9e0b20971a Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 12 May 2026 08:14:02 -0600 Subject: [PATCH 69/75] elliptic-curve: fix minimal-versions check (#2414) The issue as reported in #2413 is buried deep in the transitive dependencies of `bitvec` which is in turn a transitive dependency of `ff`, so it's a bit annoying to debug. It turns out to be `wyz` does not correctly specify the version of `tap` it needs: it needs 1.0.1 but asks for 1 (I feel like I've probably encountered this before) Sidebar: alternatively we could drop the `bits` feature. I'm not sure if anyone's actually using it and I suppose I could look into that, but `bitvec` development seems stalled at this point and asking about it on Zulip's #t-opsem channel did not inspire confidence for cryptographic applications. --- .github/workflows/elliptic-curve.yml | 1 - Cargo.lock | 285 +++++++++++++-------------- elliptic-curve/Cargo.toml | 3 +- 3 files changed, 140 insertions(+), 149 deletions(-) diff --git a/.github/workflows/elliptic-curve.yml b/.github/workflows/elliptic-curve.yml index 3c0de3691..61381f529 100644 --- a/.github/workflows/elliptic-curve.yml +++ b/.github/workflows/elliptic-curve.yml @@ -62,7 +62,6 @@ jobs: - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc,digest,ecdh,pem,pkcs8,sec1,serde minimal-versions: - if: false uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: working-directory: ${{ github.workflow }} diff --git a/Cargo.lock b/Cargo.lock index ba3167679..71d28cea5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,13 +4,13 @@ version = 4 [[package]] name = "addchain" -version = "0.2.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e33f6a175ec6a9e0aca777567f9ff7c3deefc255660df887e7fa3585e9801d8" +checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" dependencies = [ "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.19", ] [[package]] @@ -26,21 +26,27 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + +[[package]] +name = "base16ct" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "d8b59d472eab27ade8d770dcb11da7201c11234bef9f82ce7aa517be028d462b" [[package]] name = "base16ct" @@ -50,21 +56,21 @@ checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" [[package]] name = "base64ct" -version = "1.8.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +checksum = "bb97d56060ee67d285efb8001fec9d2a4c710c32efd2e14b5cbb5ba71930fc2d" [[package]] name = "bitflags" -version = "2.11.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "bitvec" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b" dependencies = [ "funty", "radium", @@ -105,9 +111,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cfg-if" -version = "1.0.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cipher" @@ -123,21 +129,21 @@ dependencies = [ [[package]] name = "cmov" -version = "0.5.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" +checksum = "de0758edba32d61d1fd9f4d69491b47604b91ee2f7e6b33de7e54ca4ebe55dc3" [[package]] name = "const-oid" -version = "0.10.2" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" +checksum = "1cb3c4a0d3776f7535c32793be81d6d5fec0d48ac70955d9834e643aa249a52f" [[package]] name = "cpubits" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" +checksum = "5ef0c543070d296ea414df2dd7625d1b24866ce206709d8a4a424f28377f5861" [[package]] name = "cpufeatures" @@ -170,15 +176,15 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.7.3" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a0d26b245348befa0c121944541476763dcc46ede886c88f9d12e1697d27c3" +checksum = "e9b6a7421484856c90cb2e996b91068d608539bb4e6f0a111b16d70678824d09" dependencies = [ "cpubits", "ctutils", "getrandom", "hybrid-array", - "num-traits", + "num-traits 0.2.19", "rand_core", "subtle", "zeroize", @@ -195,9 +201,9 @@ dependencies = [ [[package]] name = "ctutils" -version = "0.4.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +checksum = "1005a6d4446f5120ef475ad3d2af2b30c49c2c9c6904258e3bb30219bebed5e4" dependencies = [ "cmov", "subtle", @@ -227,11 +233,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "dtoa" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5edd69c67b2f8e0911629b7e6b8a34cb3956613cd7c6e6414966dee349c2db4f" + [[package]] name = "elliptic-curve" version = "0.14.0-rc.32" dependencies = [ - "base16ct", + "base16ct 1.0.0", "crypto-bigint", "crypto-common", "digest", @@ -247,20 +259,21 @@ dependencies = [ "sec1", "serdect", "subtle", + "tap", "zeroize", ] [[package]] name = "equivalent" -version = "1.0.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" [[package]] name = "foldhash" -version = "0.1.5" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "33d5ac82bdbbd872ce0dfea4e848a678cfcfdc0d210a5b20549b8c659fec0392" [[package]] name = "funty" @@ -270,9 +283,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "getrandom" -version = "0.4.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "cd66c162c2a0609c0507f49814877c621d00cb85978e6fbbf04e88b8048c07c8" dependencies = [ "cfg-if", "libc", @@ -284,19 +297,13 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "foldhash", ] -[[package]] -name = "hashbrown" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" - [[package]] name = "heck" version = "0.5.0" @@ -305,9 +312,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hex-literal" -version = "1.1.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" +checksum = "bcaaec4551594c969335c98c903c1397853d4198408ea609190f420500f6be71" [[package]] name = "hkdf" @@ -329,9 +336,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.11" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" +checksum = "8655f91cd07f2b9d0c24137bd650fe69617773435ee5ec83022377777ce65ef1" dependencies = [ "subtle", "typenum", @@ -340,20 +347,19 @@ dependencies = [ [[package]] name = "id-arena" -version = "2.3.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" +checksum = "3a7250033feafee46a1cecd2c2616a64aec1d064f38c9ae2bdd297728542843e" [[package]] name = "indexmap" -version = "2.14.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.17.0", + "hashbrown", "serde", - "serde_core", ] [[package]] @@ -368,9 +374,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.18" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +checksum = "91fd9dc2c587067de817fec4ad355e3818c3d893a78cab32a0a474c7a15bb8d5" [[package]] name = "kdf" @@ -392,42 +398,46 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.186" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "log" -version = "0.4.29" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "memchr" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] [[package]] name = "num-bigint" -version = "0.3.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +checksum = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0" dependencies = [ "autocfg", "num-integer", - "num-traits", + "num-traits 0.2.19", ] [[package]] name = "num-integer" -version = "0.1.46" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" dependencies = [ - "num-traits", + "autocfg", + "num-traits 0.2.19", ] +[[package]] +name = "num-traits" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51eab148f171aefad295f8cece636fc488b9b392ef544da31ea4b8ef6b9e9c39" + [[package]] name = "num-traits" version = "0.2.19" @@ -439,9 +449,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.4" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +checksum = "cde51589ab56b20a6f686b2c68f7a0bd6add753d697abf720d63f8db3ab7b1ad" dependencies = [ "critical-section", "portable-atomic", @@ -467,9 +477,9 @@ dependencies = [ [[package]] name = "phc" -version = "0.6.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44dc769b75f93afdddd8c7fa12d685292ddeff1e66f7f0f3a234cf1818afe892" +checksum = "1c071858f76787264da1540c8fe6c73502767246b1a70d4ce31c94a38bdcac93" dependencies = [ "base64ct", "ctutils", @@ -489,43 +499,43 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.13.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" [[package]] name = "prettyplease" -version = "0.2.37" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.117", + "syn 2.0.89", ] [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "307e3004becf10f5a6e0d59d20f3cd28231b0e0827a96cd3e0ce6d14bc1e4bb3" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.45" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "6.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +checksum = "5a2af567ac9e1e7d2d11097ca14a1e463a5c06a2ee84c23c009b489b00afc1fc" [[package]] name = "radium" @@ -535,9 +545,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand_core" -version = "0.10.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" [[package]] name = "rustcrypto-ff" @@ -560,10 +570,10 @@ dependencies = [ "addchain", "num-bigint", "num-integer", - "num-traits", + "num-traits 0.2.19", "proc-macro2", "quote", - "syn 1.0.109", + "syn 1.0.0", ] [[package]] @@ -578,11 +588,11 @@ dependencies = [ [[package]] name = "sec1" -version = "0.8.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d" +checksum = "f46b9a5ab87780a3189a1d704766579517a04ad59de653b7aad7d38e8a15f7dc" dependencies = [ - "base16ct", + "base16ct 1.0.0", "ctutils", "der", "hybrid-array", @@ -593,59 +603,46 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.28" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +checksum = "76b5842e81eb9bbea19276a9dbbda22ac042532f390a67ab08b895617978abf3" [[package]] name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", -] - -[[package]] -name = "serde_core" -version = "1.0.228" +version = "1.0.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] +checksum = "2c911f4b04d7385c9035407a4eff5903bf4fe270fa046fda448b69e797f4fff0" [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.89", ] [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e9b1ec939469a124b27e208106550c38358ed4334d2b1b5b3825bc1ee37d946a" dependencies = [ + "dtoa", "itoa", - "memchr", + "num-traits 0.1.32", "serde", - "serde_core", - "zmij", ] [[package]] name = "serdect" -version = "0.4.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66cf8fedced2fcf12406bcb34223dffb92eaf34908ede12fed414c82b7f00b3e" +checksum = "d3ef0e35b322ddfaecbc60f34ab448e157e48531288ee49fafbb053696b8ffe2" dependencies = [ - "base16ct", + "base16ct 0.3.0", "serde", ] @@ -686,20 +683,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "1.0.109" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "9f8c8eab7d9f493cd89d4068085651d81ac7d39c56eb64f7158ea514b156e280" dependencies = [ "proc-macro2", "quote", - "unicode-ident", + "unicode-xid", ] [[package]] name = "syn" -version = "2.0.117" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -714,21 +711,21 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "typenum" -version = "1.20.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.24" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" [[package]] name = "unicode-xid" -version = "0.2.6" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "universal-hash" @@ -740,11 +737,11 @@ dependencies = [ [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.0+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24" dependencies = [ - "wit-bindgen 0.46.0", + "wit-bindgen 0.45.0", ] [[package]] @@ -785,16 +782,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags", - "hashbrown 0.15.5", + "hashbrown", "indexmap", "semver", ] [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" [[package]] name = "wit-bindgen" @@ -826,7 +823,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn 2.0.117", + "syn 2.0.89", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -842,7 +839,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.89", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -895,12 +892,6 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" - -[[package]] -name = "zmij" -version = "1.0.21" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index 38e95b5df..b6eb62d31 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -36,6 +36,7 @@ pem-rfc7468 = { version = "1", optional = true, features = ["alloc"] } pkcs8 = { version = "0.11", optional = true, default-features = false } sec1 = { version = "0.8", optional = true, features = ["ctutils", "subtle", "zeroize"] } serdect = { version = "0.4", optional = true, default-features = false, features = ["alloc"] } +tap = { version = "1.0.1", optional = true, default-features = false } # make `bitvec`'s `wyz` work with `minimal-versions` [dev-dependencies] hex-literal = "1" @@ -61,7 +62,7 @@ std = [ arithmetic = ["group"] basepoint-table = ["arithmetic"] critical-section = ["basepoint-table", "once_cell/critical-section"] -bits = ["arithmetic", "ff/bits"] +bits = ["dep:tap", "arithmetic", "ff/bits"] dev = ["arithmetic", "dep:hex-literal", "pem", "pkcs8"] ecdh = ["arithmetic", "digest", "dep:hkdf"] getrandom = ["arithmetic", "bigint/getrandom", "common/getrandom"] From 40f6b7b15b6fe12ae7752550488b222ba4322fc3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 May 2026 17:19:55 +0300 Subject: [PATCH 70/75] ci: bump crate-ci/typos from 1.46.0 to 1.46.1 (#2409) --- .github/workflows/workspace.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index 191c5e49d..2b31ab52f 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -56,7 +56,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - uses: crate-ci/typos@v1.46.0 + - uses: crate-ci/typos@v1.46.1 lock: name: Check Cargo.lock From d2cf1f996cf6d71d2400d5f64b3667265688e355 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Tue, 12 May 2026 17:33:39 +0300 Subject: [PATCH 71/75] Update Cargo.lock (#2415) --- Cargo.lock | 284 +++++++++++++++++++++++++++-------------------------- 1 file changed, 147 insertions(+), 137 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71d28cea5..b6c2c2aef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,13 +4,13 @@ version = 4 [[package]] name = "addchain" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" +checksum = "2e33f6a175ec6a9e0aca777567f9ff7c3deefc255660df887e7fa3585e9801d8" dependencies = [ "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", ] [[package]] @@ -26,27 +26,21 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.72" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arrayvec" -version = "0.7.0" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "autocfg" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" - -[[package]] -name = "base16ct" -version = "0.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b59d472eab27ade8d770dcb11da7201c11234bef9f82ce7aa517be028d462b" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "base16ct" @@ -56,21 +50,21 @@ checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" [[package]] name = "base64ct" -version = "1.7.1" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb97d56060ee67d285efb8001fec9d2a4c710c32efd2e14b5cbb5ba71930fc2d" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "bitvec" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", @@ -111,9 +105,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cipher" @@ -129,21 +123,21 @@ dependencies = [ [[package]] name = "cmov" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0758edba32d61d1fd9f4d69491b47604b91ee2f7e6b33de7e54ca4ebe55dc3" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" [[package]] name = "const-oid" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cb3c4a0d3776f7535c32793be81d6d5fec0d48ac70955d9834e643aa249a52f" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" [[package]] name = "cpubits" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef0c543070d296ea414df2dd7625d1b24866ce206709d8a4a424f28377f5861" +checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" [[package]] name = "cpufeatures" @@ -176,15 +170,15 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9b6a7421484856c90cb2e996b91068d608539bb4e6f0a111b16d70678824d09" +checksum = "42a0d26b245348befa0c121944541476763dcc46ede886c88f9d12e1697d27c3" dependencies = [ "cpubits", "ctutils", "getrandom", "hybrid-array", - "num-traits 0.2.19", + "num-traits", "rand_core", "subtle", "zeroize", @@ -201,9 +195,9 @@ dependencies = [ [[package]] name = "ctutils" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1005a6d4446f5120ef475ad3d2af2b30c49c2c9c6904258e3bb30219bebed5e4" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" dependencies = [ "cmov", "subtle", @@ -233,17 +227,11 @@ dependencies = [ "zeroize", ] -[[package]] -name = "dtoa" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5edd69c67b2f8e0911629b7e6b8a34cb3956613cd7c6e6414966dee349c2db4f" - [[package]] name = "elliptic-curve" version = "0.14.0-rc.32" dependencies = [ - "base16ct 1.0.0", + "base16ct", "crypto-bigint", "crypto-common", "digest", @@ -265,15 +253,15 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "foldhash" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d5ac82bdbbd872ce0dfea4e848a678cfcfdc0d210a5b20549b8c659fec0392" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "funty" @@ -283,9 +271,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "getrandom" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd66c162c2a0609c0507f49814877c621d00cb85978e6fbbf04e88b8048c07c8" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", @@ -297,13 +285,19 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + [[package]] name = "heck" version = "0.5.0" @@ -312,9 +306,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hex-literal" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcaaec4551594c969335c98c903c1397853d4198408ea609190f420500f6be71" +checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" [[package]] name = "hkdf" @@ -336,9 +330,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.8" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8655f91cd07f2b9d0c24137bd650fe69617773435ee5ec83022377777ce65ef1" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" dependencies = [ "subtle", "typenum", @@ -347,19 +341,20 @@ dependencies = [ [[package]] name = "id-arena" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a7250033feafee46a1cecd2c2616a64aec1d064f38c9ae2bdd297728542843e" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "indexmap" -version = "2.7.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.17.1", "serde", + "serde_core", ] [[package]] @@ -374,9 +369,9 @@ dependencies = [ [[package]] name = "itoa" -version = "0.3.0" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fd9dc2c587067de817fec4ad355e3818c3d893a78cab32a0a474c7a15bb8d5" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "kdf" @@ -398,46 +393,42 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "log" -version = "0.4.17" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "num-bigint" -version = "0.3.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" dependencies = [ "autocfg", "num-integer", - "num-traits 0.2.19", + "num-traits", ] [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", - "num-traits 0.2.19", + "num-traits", ] -[[package]] -name = "num-traits" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51eab148f171aefad295f8cece636fc488b9b392ef544da31ea4b8ef6b9e9c39" - [[package]] name = "num-traits" version = "0.2.19" @@ -449,9 +440,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.0" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde51589ab56b20a6f686b2c68f7a0bd6add753d697abf720d63f8db3ab7b1ad" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" dependencies = [ "critical-section", "portable-atomic", @@ -477,9 +468,9 @@ dependencies = [ [[package]] name = "phc" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c071858f76787264da1540c8fe6c73502767246b1a70d4ce31c94a38bdcac93" +checksum = "44dc769b75f93afdddd8c7fa12d685292ddeff1e66f7f0f3a234cf1818afe892" dependencies = [ "base64ct", "ctutils", @@ -499,43 +490,43 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.8.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "prettyplease" -version = "0.2.20" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.89", + "syn 2.0.117", ] [[package]] name = "proc-macro2" -version = "1.0.91" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307e3004becf10f5a6e0d59d20f3cd28231b0e0827a96cd3e0ce6d14bc1e4bb3" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.1.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a2af567ac9e1e7d2d11097ca14a1e463a5c06a2ee84c23c009b489b00afc1fc" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "radium" @@ -545,9 +536,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "rustcrypto-ff" @@ -570,10 +561,10 @@ dependencies = [ "addchain", "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", "proc-macro2", "quote", - "syn 1.0.0", + "syn 1.0.109", ] [[package]] @@ -588,11 +579,11 @@ dependencies = [ [[package]] name = "sec1" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46b9a5ab87780a3189a1d704766579517a04ad59de653b7aad7d38e8a15f7dc" +checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d" dependencies = [ - "base16ct 1.0.0", + "base16ct", "ctutils", "der", "hybrid-array", @@ -603,46 +594,59 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.0" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76b5842e81eb9bbea19276a9dbbda22ac042532f390a67ab08b895617978abf3" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" -version = "1.0.184" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c911f4b04d7385c9035407a4eff5903bf4fe270fa046fda448b69e797f4fff0" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] [[package]] name = "serde_derive" -version = "1.0.166" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.0" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9b1ec939469a124b27e208106550c38358ed4334d2b1b5b3825bc1ee37d946a" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "dtoa", "itoa", - "num-traits 0.1.32", + "memchr", "serde", + "serde_core", + "zmij", ] [[package]] name = "serdect" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3ef0e35b322ddfaecbc60f34ab448e157e48531288ee49fafbb053696b8ffe2" +checksum = "66cf8fedced2fcf12406bcb34223dffb92eaf34908ede12fed414c82b7f00b3e" dependencies = [ - "base16ct 0.3.0", + "base16ct", "serde", ] @@ -683,20 +687,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "1.0.0" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f8c8eab7d9f493cd89d4068085651d81ac7d39c56eb64f7158ea514b156e280" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] name = "syn" -version = "2.0.89" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -711,21 +715,21 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "typenum" -version = "1.17.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" @@ -737,11 +741,11 @@ dependencies = [ [[package]] name = "wasip2" -version = "1.0.0+wasi-0.2.4" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen 0.45.0", + "wit-bindgen 0.46.0", ] [[package]] @@ -782,16 +786,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags", - "hashbrown", + "hashbrown 0.15.5", "indexmap", "semver", ] [[package]] name = "wit-bindgen" -version = "0.45.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "wit-bindgen" @@ -823,7 +827,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn 2.0.89", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -839,7 +843,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -892,6 +896,12 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zmij" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" From e4d7d34011255763c1113f7de79e7674bf0ac291 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 12 May 2026 09:00:52 -0600 Subject: [PATCH 72/75] elliptic-curve: remove `bits` feature (#2417) I was not able to find any users of it searching GitHub. This feature is backed by `bitvec` which both has a high number of transitive dependencies which have been minorly problematic (#2414), but also my understanding based on Zulip discussions on #t-opsem is that `bitvec` is not sound under either stacked or tree borrows, which makes it a bit worrisome for use in cryptographic applications. We can always add the feature back if it turns out there are users, but if not it seems like it's not worth the maintenance burden. --- .github/workflows/elliptic-curve.yml | 3 +- Cargo.lock | 107 +-------------------------- elliptic-curve/Cargo.toml | 2 - elliptic-curve/src/dev/mock_curve.rs | 23 ------ elliptic-curve/src/scalar.rs | 4 - 5 files changed, 5 insertions(+), 134 deletions(-) diff --git a/.github/workflows/elliptic-curve.yml b/.github/workflows/elliptic-curve.yml index 61381f529..0c208f8fd 100644 --- a/.github/workflows/elliptic-curve.yml +++ b/.github/workflows/elliptic-curve.yml @@ -46,7 +46,6 @@ jobs: - run: cargo build --target ${{ matrix.target }} --release --no-default-features - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features arithmetic - - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features bits - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features critical-section - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features dev - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features digest @@ -104,6 +103,6 @@ jobs: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: - toolchain: nightly-2026-02-11 # pinned due to rust-lang/miri#4855 + toolchain: nightly-2026-05-01 # pinned due to ensure determinism - run: rustup component add miri && cargo miri setup - run: cargo miri test --all-features diff --git a/Cargo.lock b/Cargo.lock index b6c2c2aef..cadd3e899 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,17 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addchain" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e33f6a175ec6a9e0aca777567f9ff7c3deefc255660df887e7fa3585e9801d8" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "aead" version = "0.6.0-rc.10" @@ -60,18 +49,6 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "blobby" version = "0.4.0" @@ -247,7 +224,6 @@ dependencies = [ "sec1", "serdect", "subtle", - "tap", "zeroize", ] @@ -263,12 +239,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "getrandom" version = "0.4.2" @@ -409,26 +379,6 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" -[[package]] -name = "num-bigint" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -501,7 +451,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.117", + "syn", ] [[package]] @@ -528,12 +478,6 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "rand_core" version = "0.10.1" @@ -546,27 +490,10 @@ version = "0.14.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd2a8adb347447693cd2ba0d218c4b66c62da9b0a5672b17b981e4291ec65ff6" dependencies = [ - "bitvec", "rand_core", - "rustcrypto-ff_derive", "subtle", ] -[[package]] -name = "rustcrypto-ff_derive" -version = "0.14.0-rc.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cda22ea03582974ab5687fc131eba2dc78e258e7eef4d7e01bcd0522ed79f66" -dependencies = [ - "addchain", - "num-bigint", - "num-integer", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "rustcrypto-group" version = "0.14.0-rc.1" @@ -624,7 +551,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -685,17 +612,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.117" @@ -707,12 +623,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "typenum" version = "1.20.0" @@ -827,7 +737,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn 2.0.117", + "syn", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -843,7 +753,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.117", + "syn", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -885,15 +795,6 @@ dependencies = [ "wasmparser", ] -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - [[package]] name = "zeroize" version = "1.8.2" diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index b6eb62d31..8b5f7f3e6 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -36,7 +36,6 @@ pem-rfc7468 = { version = "1", optional = true, features = ["alloc"] } pkcs8 = { version = "0.11", optional = true, default-features = false } sec1 = { version = "0.8", optional = true, features = ["ctutils", "subtle", "zeroize"] } serdect = { version = "0.4", optional = true, default-features = false, features = ["alloc"] } -tap = { version = "1.0.1", optional = true, default-features = false } # make `bitvec`'s `wyz` work with `minimal-versions` [dev-dependencies] hex-literal = "1" @@ -62,7 +61,6 @@ std = [ arithmetic = ["group"] basepoint-table = ["arithmetic"] critical-section = ["basepoint-table", "once_cell/critical-section"] -bits = ["dep:tap", "arithmetic", "ff/bits"] dev = ["arithmetic", "dep:hex-literal", "pem", "pkcs8"] ecdh = ["arithmetic", "digest", "dep:hkdf"] getrandom = ["arithmetic", "bigint/getrandom", "common/getrandom"] diff --git a/elliptic-curve/src/dev/mock_curve.rs b/elliptic-curve/src/dev/mock_curve.rs index 33c83c044..5919bcbca 100644 --- a/elliptic-curve/src/dev/mock_curve.rs +++ b/elliptic-curve/src/dev/mock_curve.rs @@ -31,8 +31,6 @@ use pkcs8::AssociatedOid; #[cfg(feature = "alloc")] use alloc::vec::Vec; -#[cfg(feature = "bits")] -use ff::PrimeFieldBits; /// Pseudo-coordinate for fixed-based scalar mult output pub const PSEUDO_COORDINATE_FIXED_BASE_MUL: [u8; 32] = @@ -56,10 +54,6 @@ pub type SecretKey = crate::SecretKey; /// Scalar value type. pub type ScalarValue = crate::ScalarValue; -/// Scalar bits. -#[cfg(feature = "bits")] -pub type ScalarBits = crate::scalar::ScalarBits; - /// Mock elliptic curve type useful for writing tests which require a concrete /// curve type. /// @@ -161,23 +155,6 @@ impl PrimeField for Scalar { } } -#[cfg(feature = "bits")] -impl PrimeFieldBits for Scalar { - #[cfg(target_pointer_width = "32")] - type ReprBits = [u32; 8]; - - #[cfg(target_pointer_width = "64")] - type ReprBits = [u64; 4]; - - fn to_le_bits(&self) -> ScalarBits { - self.0.as_uint().to_words().into() - } - - fn char_le_bits() -> ScalarBits { - MockCurve::ORDER.to_words().into() - } -} - impl Generate for Scalar { fn try_generate_from_rng( rng: &mut R, diff --git a/elliptic-curve/src/scalar.rs b/elliptic-curve/src/scalar.rs index b98fba8e5..b4b44fa3f 100644 --- a/elliptic-curve/src/scalar.rs +++ b/elliptic-curve/src/scalar.rs @@ -21,10 +21,6 @@ use crate::CurveArithmetic; #[cfg(feature = "arithmetic")] pub type Scalar = ::Scalar; -/// Bit representation of a scalar field element of a given curve. -#[cfg(feature = "bits")] -pub type ScalarBits = ff::FieldBits< as ff::PrimeFieldBits>::ReprBits>; - /// Instantiate a scalar from an unsigned integer without checking for overflow. pub trait FromUintUnchecked { /// Unsigned integer type (i.e. `Curve::Uint`) From 94f108f78474093969480d64a0c7066e525bd31f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 18:24:42 +0300 Subject: [PATCH 73/75] ci: bump crate-ci/typos from 1.46.1 to 1.46.2 (#2419) --- .github/workflows/workspace.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index 2b31ab52f..b085601ce 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -56,7 +56,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - uses: crate-ci/typos@v1.46.1 + - uses: crate-ci/typos@v1.46.2 lock: name: Check Cargo.lock From f73c4bca676e9916976bd9bd429459f93670b2dd Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Tue, 19 May 2026 18:45:51 +0300 Subject: [PATCH 74/75] crypto-common: add `SetIvState` trait (#2420) --- crypto-common/CHANGELOG.md | 6 ++++++ crypto-common/src/lib.rs | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/crypto-common/CHANGELOG.md b/crypto-common/CHANGELOG.md index f40183052..351ad4537 100644 --- a/crypto-common/CHANGELOG.md +++ b/crypto-common/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.2.2 (UNRELEASED) +### Added +- `SetIvState` trait ([#2420]) + +[#2420]: https://github.com/RustCrypto/traits/pull/2420 + ## 0.2.1 (2026-02-25) ### Changed - `BlockSizeUser::BlockSize` is no longer bounded by `BlockSizes` ([#2309]) diff --git a/crypto-common/src/lib.rs b/crypto-common/src/lib.rs index faa39e3d2..4ebf38272 100644 --- a/crypto-common/src/lib.rs +++ b/crypto-common/src/lib.rs @@ -310,6 +310,22 @@ pub trait IvState: IvSizeUser { fn iv_state(&self) -> Iv; } +/// Trait for setting current IV state. +// TODO: merge with `IvState` in the next breaking release +pub trait SetIvState: IvState { + /// Set IV. + fn set_iv(&mut self, iv: &Iv); + + /// Execute the `f` closure with the current state and reset it back + /// to the original state before the method returns. + fn peek(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { + let iv = self.iv_state(); + let res = f(self); + self.set_iv(&iv); + res + } +} + impl KeySizeUser for T where T: InnerUser, From 93dee26c6bde3741a197f1c5f6b7baac277705f3 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Tue, 19 May 2026 18:51:30 +0300 Subject: [PATCH 75/75] Release crypto-common v0.2.2 (#2421) ### Added - `SetIvState` trait ([#2420]) [#2420]: https://github.com/RustCrypto/traits/pull/2420 --- Cargo.lock | 2 +- crypto-common/CHANGELOG.md | 2 +- crypto-common/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cadd3e899..c6ccbc15b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,7 +163,7 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.2.1" +version = "0.2.2" dependencies = [ "getrandom", "hybrid-array", diff --git a/crypto-common/CHANGELOG.md b/crypto-common/CHANGELOG.md index 351ad4537..ffc3453e5 100644 --- a/crypto-common/CHANGELOG.md +++ b/crypto-common/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 0.2.2 (UNRELEASED) +## 0.2.2 (2026-05-19) ### Added - `SetIvState` trait ([#2420]) diff --git a/crypto-common/Cargo.toml b/crypto-common/Cargo.toml index d9f324bef..1d55fb0a8 100644 --- a/crypto-common/Cargo.toml +++ b/crypto-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "crypto-common" -version = "0.2.1" +version = "0.2.2" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85"