Skip to main content

dcrypt_algorithms/ec/p192/
mod.rs

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