From 84158337afa5bca7edb676c4b3d80d0fe4b64bf1 Mon Sep 17 00:00:00 2001 From: "pinkforest(she/her)" <36498018+pinkforest@users.noreply.github.com> Date: Sat, 1 Apr 2023 04:34:03 +1100 Subject: [PATCH] Make `static_secrets` optional (#122) * Make `static_secrets` optional * Added more feature combinations to CI --- .github/workflows/rust.yml | 6 +++++- Cargo.toml | 1 + src/x25519.rs | 15 ++++++++++----- tests/x25519_tests.rs | 2 ++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d5c47c5..c367173 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -13,7 +13,7 @@ env: jobs: test: - name: Test all features + name: Test with multiple feature combinations runs-on: ubuntu-latest strategy: matrix: @@ -29,6 +29,10 @@ jobs: with: target: ${{ matrix.target }} - run: ${{ matrix.deps }} + - run: cargo test --target ${{ matrix.target }} --no-default-features + - run: cargo test --target ${{ matrix.target }} --no-default-features --features reusable_secrets + - run: cargo test --target ${{ matrix.target }} --no-default-features --features static_secrets + - run: cargo test --target ${{ matrix.target }} - run: cargo test --target ${{ matrix.target }} --all-features build-simd: diff --git a/Cargo.toml b/Cargo.toml index 46e048c..f6c48d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,3 +60,4 @@ serde = ["dep:serde", "curve25519-dalek/serde"] alloc = ["curve25519-dalek/alloc", "serde?/alloc", "zeroize?/alloc"] precomputed-tables = ["curve25519-dalek/precomputed-tables"] reusable_secrets = [] +static_secrets = [] diff --git a/src/x25519.rs b/src/x25519.rs index f161243..c8008ac 100644 --- a/src/x25519.rs +++ b/src/x25519.rs @@ -24,8 +24,7 @@ use rand_core::RngCore; #[cfg(feature = "zeroize")] use zeroize::Zeroize; -/// A Diffie-Hellman public key, corresponding to an [`EphemeralSecret`] or -/// [`StaticSecret`] key. +/// A Diffie-Hellman public key /// /// We implement `Zeroize` so that downstream consumers may derive it for `Drop` /// should they wish to erase public keys from memory. Note that this erasure @@ -68,7 +67,7 @@ impl AsRef<[u8]> for PublicKey { /// A short-lived Diffie-Hellman secret key that can only be used to compute a single /// [`SharedSecret`]. /// -/// This type is identical to the [`StaticSecret`] type, except that the +/// This type is identical to the `StaticSecret` type, except that the /// [`EphemeralSecret::diffie_hellman`] method consumes and then wipes the secret key, and there /// are no serialization methods defined. This means that [`EphemeralSecret`]s can only be /// generated from fresh randomness where the compiler statically checks that the resulting @@ -125,7 +124,7 @@ impl<'a> From<&'a EphemeralSecret> for PublicKey { /// /// Similarly to [`EphemeralSecret`], this type does _not_ have serialisation /// methods, in order to discourage long-term usage of secret key material. (For -/// long-term secret keys, see [`StaticSecret`].) +/// long-term secret keys, see `StaticSecret`.) /// /// # Warning /// @@ -195,6 +194,7 @@ impl<'a> From<&'a ReusableSecret> for PublicKey { /// [`EphemeralSecret`] at all times, as that type enforces at compile-time that /// secret keys are never reused, which can have very serious security /// implications for many protocols. +#[cfg(feature = "static_secrets")] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "zeroize", derive(Zeroize))] #[cfg_attr(feature = "zeroize", zeroize(drop))] @@ -203,6 +203,7 @@ pub struct StaticSecret( #[cfg_attr(feature = "serde", serde(with = "AllowUnreducedScalarBytes"))] pub(crate) Scalar, ); +#[cfg(feature = "static_secrets")] impl StaticSecret { /// Perform a Diffie-Hellman key agreement between `self` and /// `their_public` key to produce a `SharedSecret`. @@ -247,6 +248,7 @@ impl StaticSecret { } } +#[cfg(feature = "static_secrets")] impl From<[u8; 32]> for StaticSecret { /// Load a secret key from a byte array. fn from(bytes: [u8; 32]) -> StaticSecret { @@ -254,6 +256,7 @@ impl From<[u8; 32]> for StaticSecret { } } +#[cfg(feature = "static_secrets")] impl<'a> From<&'a StaticSecret> for PublicKey { /// Given an x25519 [`StaticSecret`] key, compute its corresponding [`PublicKey`]. fn from(secret: &'a StaticSecret) -> PublicKey { @@ -261,6 +264,7 @@ impl<'a> From<&'a StaticSecret> for PublicKey { } } +#[cfg(feature = "static_secrets")] impl AsRef<[u8]> for StaticSecret { /// View this key as a byte array. #[inline] @@ -343,7 +347,8 @@ impl AsRef<[u8]> for SharedSecret { /// cannot use the better, safer, and faster ephemeral DH API. /// /// # Example -/// ```rust +#[cfg_attr(feature = "static_secrets", doc = "```")] +#[cfg_attr(not(feature = "static_secrets"), doc = "```ignore")] /// use rand_core::OsRng; /// use rand_core::RngCore; /// diff --git a/tests/x25519_tests.rs b/tests/x25519_tests.rs index 280978d..d883915 100644 --- a/tests/x25519_tests.rs +++ b/tests/x25519_tests.rs @@ -202,6 +202,7 @@ mod rand_core { } #[test] + #[cfg(feature = "static_secrets")] fn static_from_rng() { #[allow(deprecated)] StaticSecret::new(OsRng); @@ -226,6 +227,7 @@ mod getrandom { } #[test] + #[cfg(feature = "static_secrets")] fn static_random() { StaticSecret::random(); }