dcrypt_algorithms/ec/p192/
mod.rs

1//! NIST P-192 Elliptic Curve Primitives
2//!
3//! This module implements NIST P-192 elliptic curve operations in constant time.
4//! Curve equation: y² = x³ - 3x + b over 𝔽ₚ, where
5//! - p = 2¹⁹² − 2⁶⁴ − 1,
6//! - Curve order n = 0xFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF.  (NIST P-192 order).
7//!
8//! Implements:
9//! - Mersenne reduction for 𝔽ₚ (2¹⁹² ≡ 2⁶⁴ + 1),
10//! - Jacobian projective coordinates for point operations,
11//! - Constant‐time scalar multiplication, addition, etc.
12
13mod constants;
14mod field;
15mod point;
16mod scalar;
17
18pub use constants::{
19    P192_FIELD_ELEMENT_SIZE, P192_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE, P192_POINT_COMPRESSED_SIZE,
20    P192_POINT_UNCOMPRESSED_SIZE, P192_SCALAR_SIZE,
21};
22pub use field::FieldElement;
23pub use point::{Point, PointFormat};
24pub use scalar::Scalar;
25
26use crate::error::{Error, Result};
27use crate::hash::sha2::Sha256;
28use crate::kdf::hkdf::Hkdf;
29use crate::kdf::KeyDerivationFunction as KdfTrait;
30use dcrypt_params::traditional::ecdsa::NIST_P192;
31use rand::{CryptoRng, RngCore};
32
33/// Get the standard base point G of the P-192 curve
34pub fn base_point_g() -> Point {
35    Point::new_uncompressed(&NIST_P192.g_x, &NIST_P192.g_y)
36        .expect("Standard base point must be valid")
37}
38
39/// Scalar multiplication with the base point: scalar * G
40pub fn scalar_mult_base_g(scalar: &Scalar) -> Result<Point> {
41    let g = base_point_g();
42    g.mul(scalar)
43}
44
45/// Generate a cryptographically secure ECDH keypair
46pub fn generate_keypair<R: CryptoRng + RngCore>(rng: &mut R) -> Result<(Scalar, Point)> {
47    let mut scalar_bytes = [0u8; P192_SCALAR_SIZE];
48    loop {
49        rng.fill_bytes(&mut scalar_bytes);
50        match Scalar::new(scalar_bytes) {
51            Ok(privk) => {
52                let pubk = scalar_mult_base_g(&privk)?;
53                return Ok((privk, pubk));
54            }
55            Err(_) => continue,
56        }
57    }
58}
59
60/// General scalar multiplication: compute scalar * arbitrary point
61pub fn scalar_mult(scalar: &Scalar, point: &Point) -> Result<Point> {
62    if point.is_identity() {
63        Ok(Point::identity())
64    } else {
65        point.mul(scalar)
66    }
67}
68
69/// Key derivation for ECDH shared secret using HKDF-SHA256
70pub fn kdf_hkdf_sha256_for_ecdh_kem(
71    ikm: &[u8],
72    info: Option<&[u8]>,
73) -> Result<[u8; P192_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE]> {
74    let hkdf = <Hkdf<Sha256, 16> as KdfTrait>::new();
75    let derived = hkdf.derive_key(ikm, None, info, P192_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE)?;
76    let mut out = [0u8; P192_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE];
77    if derived.len() == P192_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE {
78        out.copy_from_slice(&derived);
79        Ok(out)
80    } else {
81        Err(Error::Length {
82            context: "KDF output for ECDH P-192",
83            expected: P192_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE,
84            actual: derived.len(),
85        })
86    }
87}
88
89#[cfg(test)]
90mod tests;