//! Elliptic Curve Diffie-Hellman Support.
//!
//! This module contains a generic ECDH implementation which is usable with
//! any elliptic curve which implements the [`CurveArithmetic`] trait (presently
//! the `k256` and `p256` crates)
//!
//! # ECDH Ephemeral (ECDHE) Usage
//!
//! Ephemeral Diffie-Hellman provides a one-time key exchange between two peers
//! using a randomly generated set of keys for each exchange.
//!
//! In practice ECDHE is used as part of an [Authenticated Key Exchange (AKE)][AKE]
//! protocol (e.g. [SIGMA]), where an existing cryptographic trust relationship
//! can be used to determine the authenticity of the ephemeral keys, such as
//! a digital signature. Without such an additional step, ECDHE is insecure!
//! (see security warning below)
//!
//! See the documentation for the [`EphemeralSecret`] type for more information
//! on performing ECDH ephemeral key exchanges.
//!
//! # Static ECDH Usage
//!
//! Static ECDH key exchanges are supported via the low-level
//! [`diffie_hellman`] function.
//!
//! [AKE]: https://en.wikipedia.org/wiki/Authenticated_Key_Exchange
//! [SIGMA]: https://webee.technion.ac.il/~hugo/sigma-pdf.pdf

use crate::{
    point::AffineCoordinates, AffinePoint, Curve, CurveArithmetic, FieldBytes, NonZeroScalar,
    ProjectivePoint, PublicKey,
};
use core::borrow::Borrow;
use digest::{crypto_common::BlockSizeUser, Digest};
use group::Curve as _;
use hkdf::{hmac::SimpleHmac, Hkdf};
use rand_core::CryptoRngCore;
use zeroize::{Zeroize, ZeroizeOnDrop};

/// Low-level Elliptic Curve Diffie-Hellman (ECDH) function.
///
/// Whenever possible, we recommend using the high-level ECDH ephemeral API
/// provided by [`EphemeralSecret`].
///
/// However, if you are implementing a protocol which requires a static scalar
/// value as part of an ECDH exchange, this API can be used to compute a
/// [`SharedSecret`] from that value.
///
/// Note that this API operates on the low-level [`NonZeroScalar`] and
/// [`AffinePoint`] types. If you are attempting to use the higher-level
/// [`SecretKey`][`crate::SecretKey`] and [`PublicKey`] types, you will
/// need to use the following conversions:
///
/// ```ignore
/// let shared_secret = elliptic_curve::ecdh::diffie_hellman(
///     secret_key.to_nonzero_scalar(),
///     public_key.as_affine()
/// );
/// ```
pub fn diffie_hellman<C>(
    secret_key: impl Borrow<NonZeroScalar<C>>,
    public_key: impl Borrow<AffinePoint<C>>,
) -> SharedSecret<C>
where
    C: CurveArithmetic,
{
    let public_point = ProjectivePoint::<C>::from(*public_key.borrow());
    let secret_point = (public_point * secret_key.borrow().as_ref()).to_affine();
    SharedSecret::new(secret_point)
}

/// Ephemeral Diffie-Hellman Secret.
///
/// These are ephemeral "secret key" values which are deliberately designed
/// to avoid being persisted.
///
/// To perform an ephemeral Diffie-Hellman exchange, do the following:
///
/// - Have each participant generate an [`EphemeralSecret`] value
/// - Compute the [`PublicKey`] for that value
/// - Have each peer provide their [`PublicKey`] to their counterpart
/// - Use [`EphemeralSecret`] and the other participant's [`PublicKey`]
///   to compute a [`SharedSecret`] value.
///
/// # ⚠️ SECURITY WARNING ⚠️
///
/// Ephemeral Diffie-Hellman exchanges are unauthenticated and without a
/// further authentication step are trivially vulnerable to man-in-the-middle
/// attacks!
///
/// These exchanges should be performed in the context of a protocol which
/// takes further steps to authenticate the peers in a key exchange.
pub struct EphemeralSecret<C>
where
    C: CurveArithmetic,
{
    scalar: NonZeroScalar<C>,
}

impl<C> EphemeralSecret<C>
where
    C: CurveArithmetic,
{
    /// Generate a cryptographically random [`EphemeralSecret`].
    pub fn random(rng: &mut impl CryptoRngCore) -> Self {
        Self {
            scalar: NonZeroScalar::random(rng),
        }
    }

    /// Get the public key associated with this ephemeral secret.
    ///
    /// The `compress` flag enables point compression.
    pub fn public_key(&self) -> PublicKey<C> {
        PublicKey::from_secret_scalar(&self.scalar)
    }

    /// Compute a Diffie-Hellman shared secret from an ephemeral secret and the
    /// public key of the other participant in the exchange.
    pub fn diffie_hellman(&self, public_key: &PublicKey<C>) -> SharedSecret<C> {
        diffie_hellman(self.scalar, public_key.as_affine())
    }
}

impl<C> From<&EphemeralSecret<C>> for PublicKey<C>
where
    C: CurveArithmetic,
{
    fn from(ephemeral_secret: &EphemeralSecret<C>) -> Self {
        ephemeral_secret.public_key()
    }
}

impl<C> Zeroize for EphemeralSecret<C>
where
    C: CurveArithmetic,
{
    fn zeroize(&mut self) {
        self.scalar.zeroize()
    }
}

impl<C> ZeroizeOnDrop for EphemeralSecret<C> where C: CurveArithmetic {}

impl<C> Drop for EphemeralSecret<C>
where
    C: CurveArithmetic,
{
    fn drop(&mut self) {
        self.zeroize();
    }
}

/// Shared secret value computed via ECDH key agreement.
pub struct SharedSecret<C: Curve> {
    /// Computed secret value
    secret_bytes: FieldBytes<C>,
}

impl<C: Curve> SharedSecret<C> {
    /// Create a new [`SharedSecret`] from an [`AffinePoint`] for this curve.
    #[inline]
    fn new(point: AffinePoint<C>) -> Self
    where
        C: CurveArithmetic,
    {
        Self {
            secret_bytes: point.x(),
        }
    }

    /// 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).
    ///
    /// 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
    }
}

impl<C: Curve> From<FieldBytes<C>> for SharedSecret<C> {
    /// NOTE: this impl is intended to be used by curve implementations to
    /// instantiate a [`SharedSecret`] value from their respective
    /// [`AffinePoint`] type.
    ///
    /// Curve implementations should provide the field element representing
    /// the affine x-coordinate as `secret_bytes`.
    fn from(secret_bytes: FieldBytes<C>) -> Self {
        Self { secret_bytes }
    }
}

impl<C: Curve> ZeroizeOnDrop for SharedSecret<C> {}

impl<C: Curve> Drop for SharedSecret<C> {
    fn drop(&mut self) {
        self.secret_bytes.zeroize()
    }
}
