Skip to main content

protocol/
ecdh.rs

1//! Elliptic-curve Diffie–Hellman helpers.
2
3use ec::point_ops::PointOps;
4
5use crate::scalar::SecretScalar;
6
7/// Deterministic key pair built from a caller-supplied secret scalar.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct KeyPair<P, const LIMBS: usize> {
10    /// The secret key
11    pub secret: SecretScalar<LIMBS>,
12    /// The public key
13    pub public: P,
14}
15
16/// Stateless ECDH helper.
17pub struct Ecdh;
18
19impl Ecdh {
20    /// Derive a public key `[secret]G` from a fixed generator/base point.
21    pub fn derive_public_key<P, const LIMBS: usize>(
22        base_point: &P,
23        secret: &SecretScalar<LIMBS>,
24        curve: &P::Curve,
25    ) -> P
26    where
27        P: PointOps,
28    {
29        base_point.scalar_mul(secret.as_limbs(), curve)
30    }
31
32    /// Build a deterministic key pair from a secret scalar.
33    pub fn keypair_from_secret<P, const LIMBS: usize>(
34        base_point: &P,
35        secret: SecretScalar<LIMBS>,
36        curve: &P::Curve,
37    ) -> KeyPair<P, LIMBS>
38    where
39        P: PointOps,
40    {
41        let public = Self::derive_public_key(base_point, &secret, curve);
42        KeyPair { secret, public }
43    }
44
45    /// Compute a shared point `[my_secret] peer_public`.
46    ///
47    /// Returns `None` when the peer public key is the identity.
48    pub fn shared_secret<P, const LIMBS: usize>(
49        my_secret: &SecretScalar<LIMBS>,
50        peer_public: &P,
51        curve: &P::Curve,
52    ) -> Option<P>
53    where
54        P: PointOps,
55    {
56        if peer_public.is_identity() {
57            return None;
58        }
59        Some(peer_public.scalar_mul(my_secret.as_limbs(), curve))
60    }
61}