Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

elliptic-curve: ecdh::SharedSecret::extract HKDF helper #1007

Merged
merged 1 commit into from
May 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion elliptic-curve/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ base64ct = { version = "1", optional = true, default-features = false }
digest = { version = "0.10", optional = true }
ff = { version = "0.12", optional = true, default-features = false }
group = { version = "0.12", optional = true, default-features = false }
hkdf = { version = "0.12", optional = true, default-features = false }
hex-literal = { version = "0.3", optional = true }
pem-rfc7468 = { version = "0.5", optional = true }
pkcs8 = { version = "0.9", optional = true, default-features = false }
Expand All @@ -48,7 +49,7 @@ arithmetic = ["ff", "group"]
bits = ["arithmetic", "ff/bits"]
dev = ["arithmetic", "hex-literal", "pem", "pkcs8"]
hash2curve = ["arithmetic", "digest"]
ecdh = ["arithmetic"]
ecdh = ["arithmetic", "digest", "hkdf"]
hazmat = []
jwk = ["alloc", "base64ct/alloc", "serde", "serde_json", "zeroize/alloc"]
pem = ["alloc", "arithmetic", "pem-rfc7468/alloc", "pkcs8", "sec1/pem"]
Expand Down
63 changes: 43 additions & 20 deletions elliptic-curve/src/ecdh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ use crate::{
ProjectiveArithmetic, ProjectivePoint, PublicKey,
};
use core::borrow::Borrow;
use digest::{crypto_common::BlockSizeUser, Digest};
use group::Curve as _;
use hkdf::{hmac::SimpleHmac, Hkdf};
use rand_core::{CryptoRng, RngCore};
use zeroize::{Zeroize, ZeroizeOnDrop};

Expand Down Expand Up @@ -150,20 +152,6 @@ where
}

/// Shared secret value computed via ECDH key agreement.
///
/// This value contains the raw serialized x-coordinate of the elliptic curve
/// point computed from a Diffie-Hellman exchange.
///
/// # ⚠️ WARNING: NOT UNIFORMLY RANDOM! ⚠️
///
/// This value is not uniformly random and should not be used directly
/// as a cryptographic key for anything which requires that property
/// (e.g. symmetric ciphers).
///
/// Instead, the resulting value should be used as input to a Key Derivation
/// Function (KDF) or cryptographic hash function to produce a symmetric key.
// TODO(tarcieri): KDF traits and support for deriving uniform keys
// See: https://github.com/RustCrypto/traits/issues/5
pub struct SharedSecret<C: Curve> {
/// Computed secret value
secret_bytes: FieldBytes<C>,
Expand All @@ -181,13 +169,48 @@ impl<C: Curve> SharedSecret<C> {
}
}

/// Shared secret value, serialized as bytes.
/// Use [HKDF] (HMAC-based Extract-and-Expand Key Derivation Function) to
/// extract entropy from this shared secret.
///
/// This method can be used to transform the shared secret into uniformly
/// random values which are suitable as key material.
///
/// The `D` type parameter is a cryptographic digest function.
/// `sha2::Sha256` is a common choice for use with HKDF.
///
/// The `salt` parameter can be used to supply additional randomness.
/// Some examples include:
///
/// - randomly generated (but authenticated) string
/// - fixed application-specific value
/// - previous shared secret used for rekeying (as in TLS 1.3 and Noise)
///
/// After initializing HKDF, use [`Hkdf::expand`] to obtain output key
/// material.
///
/// [HKDF]: https://en.wikipedia.org/wiki/HKDF
pub fn extract<D>(&self, salt: Option<&[u8]>) -> Hkdf<D, SimpleHmac<D>>
where
D: BlockSizeUser + Clone + Digest,
{
Hkdf::new(salt, &self.secret_bytes)
}

/// This value contains the raw serialized x-coordinate of the elliptic curve
/// point computed from a Diffie-Hellman exchange, serialized as bytes.
///
/// When in doubt, use [`SharedSecret::extract`] instead.
///
/// # ⚠️ WARNING: NOT UNIFORMLY RANDOM! ⚠️
///
/// This value is not uniformly random and should not be used directly
/// as a cryptographic key for anything which requires that property
/// (e.g. symmetric ciphers).
///
/// As noted in the comments for this struct, this value is non-uniform and
/// should not be used directly as a symmetric encryption key, but instead
/// as input to a KDF (or failing that, a hash function) used to produce
/// a symmetric key.
pub fn as_bytes(&self) -> &FieldBytes<C> {
/// Instead, the resulting value should be used as input to a Key Derivation
/// Function (KDF) or cryptographic hash function to produce a symmetric key.
/// The [`SharedSecret::extract`] function will do this for you.
pub fn raw_secret_bytes(&self) -> &FieldBytes<C> {
&self.secret_bytes
}
}
Expand Down
4 changes: 1 addition & 3 deletions elliptic-curve/src/secret_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ pub(crate) const SEC1_PEM_TYPE_LABEL: &str = "EC PRIVATE KEY";
///
/// To decode an elliptic curve private key from PKCS#8, enable the `pkcs8`
/// feature of this crate (or the `pkcs8` feature of a specific RustCrypto
/// elliptic curve crate) and use the
/// [`DecodePrivateKey`][`elliptic_curve::pkcs8::DecodePrivateKey`]
/// trait to parse it.
/// elliptic curve crate) and use the [`DecodePrivateKey`] trait to parse it.
///
/// When the `pem` feature of this crate (or a specific RustCrypto elliptic
/// curve crate) is enabled, a [`FromStr`] impl is also available.
Expand Down