dcrypt_algorithms/ec/b283k/
mod.rs1mod constants;
11mod field;
12mod point;
13mod scalar;
14
15pub use constants::{
16 B283K_FIELD_ELEMENT_SIZE, B283K_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE, B283K_POINT_COMPRESSED_SIZE,
17 B283K_POINT_UNCOMPRESSED_SIZE, B283K_SCALAR_SIZE,
18};
19pub use field::FieldElement;
20pub use point::{Point, PointFormat};
21pub use scalar::Scalar;
22
23use crate::error::{Error, Result};
24use crate::hash::sha2::Sha384;
25use crate::kdf::hkdf::Hkdf;
26use crate::kdf::KeyDerivationFunction as KdfTrait;
27use rand::{CryptoRng, RngCore};
28
29struct Sect283k1Params {
31 g_x: [u8; 36],
32 g_y: [u8; 36],
33}
34
35const SECT283K1: Sect283k1Params = Sect283k1Params {
36 g_x: [
38 0x05, 0x03, 0x21, 0x3F, 0x78, 0xCA, 0x44, 0x88, 0x3F, 0x1A, 0x3B, 0x81, 0x62, 0xF1, 0x88,
39 0xE5, 0x53, 0xCD, 0x26, 0x5F, 0x23, 0xC1, 0x56, 0x7A, 0x16, 0x87, 0x69, 0x13, 0xB0, 0xC2,
40 0xAC, 0x24, 0x58, 0x49, 0x28, 0x36,
41 ],
42 g_y: [
44 0x01, 0xCC, 0xDA, 0x38, 0x0F, 0x1C, 0x9E, 0x31, 0x8D, 0x90, 0xF9, 0x5D, 0x07, 0xE5, 0x42,
45 0x6F, 0xE8, 0x7E, 0x45, 0xC0, 0xE8, 0x18, 0x46, 0x98, 0xE4, 0x59, 0x62, 0x36, 0x4E, 0x34,
46 0x11, 0x61, 0x77, 0xDD, 0x22, 0x59,
47 ],
48};
49
50pub fn base_point_g() -> Point {
52 Point::new_uncompressed(&SECT283K1.g_x, &SECT283K1.g_y)
53 .expect("Standard base point must be valid")
54}
55
56pub fn scalar_mult_base_g(scalar: &Scalar) -> Result<Point> {
58 let g = base_point_g();
59 g.mul(scalar)
60}
61
62pub fn generate_keypair<R: CryptoRng + RngCore>(rng: &mut R) -> Result<(Scalar, Point)> {
64 let mut scalar_bytes = [0u8; B283K_SCALAR_SIZE];
65 loop {
66 rng.fill_bytes(&mut scalar_bytes);
67 match Scalar::new(scalar_bytes) {
68 Ok(private_key) => {
69 let public_key = scalar_mult_base_g(&private_key)?;
70 return Ok((private_key, public_key));
71 }
72 Err(_) => continue,
73 }
74 }
75}
76
77pub fn scalar_mult(scalar: &Scalar, point: &Point) -> Result<Point> {
79 if point.is_identity() {
80 return Ok(Point::identity());
81 }
82 point.mul(scalar)
83}
84
85pub fn kdf_hkdf_sha384_for_ecdh_kem(
87 ikm: &[u8],
88 info: Option<&[u8]>,
89) -> Result<[u8; B283K_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE]> {
90 let hkdf_instance = <Hkdf<Sha384, 16> as KdfTrait>::new();
91
92 let derived_key_vec =
93 hkdf_instance.derive_key(ikm, None, info, B283K_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE)?;
94
95 let mut output_array = [0u8; B283K_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE];
96 if derived_key_vec.len() == B283K_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE {
97 output_array.copy_from_slice(&derived_key_vec);
98 Ok(output_array)
99 } else {
100 Err(Error::Length {
101 context: "KDF output for ECDH B283k",
102 expected: B283K_KEM_SHARED_SECRET_KDF_OUTPUT_SIZE,
103 actual: derived_key_vec.len(),
104 })
105 }
106}
107
108#[cfg(test)]
109mod tests;