Skip to main content

dcrypt_algorithms/ec/b283k/
mod.rs

1//! Koblitz sect283k1 Elliptic Curve Primitives
2//!
3//! This module implements the sect283k1 binary elliptic curve operations.
4//! The curve equation is y² + xy = x³ + 1 over the binary field GF(2^283).
5//! - Field polynomial: x^283 + x^12 + x^7 + x^5 + 1
6//! - The curve order n = 0x01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE96E404282DD3232283E52623152F256011
7//!
8//! Operations use timing-aware source structure, but no blanket compiler- or
9//! target-level constant-time guarantee is made.
10
11mod constants;
12mod field;
13mod point;
14mod scalar;
15
16pub use constants::{
17    B283K_FIELD_ELEMENT_SIZE, B283K_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE, B283K_POINT_COMPRESSED_SIZE,
18    B283K_POINT_UNCOMPRESSED_SIZE, B283K_SCALAR_SIZE,
19};
20pub use field::FieldElement;
21pub use point::{Point, PointFormat};
22pub use scalar::Scalar;
23
24use crate::error::{Error, Result};
25use crate::hash::sha2::Sha384;
26use crate::kdf::hkdf::Hkdf;
27use crate::kdf::KeyDerivationFunction as KdfTrait;
28use rand::{CryptoRng, RngCore};
29
30/// SECT283K1 curve parameters (base point G)
31struct Sect283k1Params {
32    g_x: [u8; 36],
33    g_y: [u8; 36],
34}
35
36const SECT283K1: Sect283k1Params = Sect283k1Params {
37    // Correct g_x from SEC 2: 0503213F 78CA4488 3F1A3B81 62F188E5 53CD265F 23C1567A 16876913 B0C2AC24 58492836
38    g_x: [
39        0x05, 0x03, 0x21, 0x3F, 0x78, 0xCA, 0x44, 0x88, 0x3F, 0x1A, 0x3B, 0x81, 0x62, 0xF1, 0x88,
40        0xE5, 0x53, 0xCD, 0x26, 0x5F, 0x23, 0xC1, 0x56, 0x7A, 0x16, 0x87, 0x69, 0x13, 0xB0, 0xC2,
41        0xAC, 0x24, 0x58, 0x49, 0x28, 0x36,
42    ],
43    // Correct g_y from SEC 2: 01CCDA38 0F1C9E31 8D90F95D 07E5426F E87E45C0 E8184698 E4596236 4E341161 77DD2259
44    g_y: [
45        0x01, 0xCC, 0xDA, 0x38, 0x0F, 0x1C, 0x9E, 0x31, 0x8D, 0x90, 0xF9, 0x5D, 0x07, 0xE5, 0x42,
46        0x6F, 0xE8, 0x7E, 0x45, 0xC0, 0xE8, 0x18, 0x46, 0x98, 0xE4, 0x59, 0x62, 0x36, 0x4E, 0x34,
47        0x11, 0x61, 0x77, 0xDD, 0x22, 0x59,
48    ],
49};
50
51/// Get the standard base point G of the sect283k1 curve
52pub fn base_point_g() -> Point {
53    Point::new_uncompressed(&SECT283K1.g_x, &SECT283K1.g_y)
54        .expect("Standard base point must be valid")
55}
56
57/// Scalar multiplication with the base point: scalar * G
58pub fn scalar_mult_base_g(scalar: &Scalar) -> Result<Point> {
59    let g = base_point_g();
60    g.mul(scalar)
61}
62
63/// Generate a cryptographically secure ECDH keypair
64pub fn generate_keypair<R: CryptoRng + RngCore>(rng: &mut R) -> Result<(Scalar, Point)> {
65    let mut scalar_bytes = [0u8; B283K_SCALAR_SIZE];
66    loop {
67        rng.fill_bytes(&mut scalar_bytes);
68        match Scalar::new(scalar_bytes) {
69            Ok(private_key) => {
70                let public_key = scalar_mult_base_g(&private_key)?;
71                return Ok((private_key, public_key));
72            }
73            Err(_) => continue,
74        }
75    }
76}
77
78/// General scalar multiplication: compute scalar * point
79pub fn scalar_mult(scalar: &Scalar, point: &Point) -> Result<Point> {
80    if point.is_identity() {
81        return Ok(Point::identity());
82    }
83    point.mul(scalar)
84}
85
86/// Key derivation function for ECDH shared secret using HKDF-SHA384
87pub fn kdf_hkdf_sha384_for_ecdh_kem(
88    ikm: &[u8],
89    info: Option<&[u8]>,
90) -> Result<[u8; B283K_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE]> {
91    let hkdf_instance = <Hkdf<Sha384, 16> as KdfTrait>::new();
92
93    let derived_key_vec =
94        hkdf_instance.derive_key(ikm, None, info, B283K_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE)?;
95
96    let mut output_array = [0u8; B283K_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE];
97    if derived_key_vec.len() == B283K_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE {
98        output_array.copy_from_slice(&derived_key_vec);
99        Ok(output_array)
100    } else {
101        Err(Error::Length {
102            context: "KDF output for ECDH B283k",
103            expected: B283K_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE,
104            actual: derived_key_vec.len(),
105        })
106    }
107}
108
109#[cfg(test)]
110mod tests;