minimal_ed448/
scalar.rs

1use zeroize::{DefaultIsZeroes, Zeroize};
2
3use crypto_bigint::{
4  U448, U896, U1024,
5  modular::constant_mod::{ResidueParams, Residue},
6};
7
8const MODULUS_STR: &str = concat!(
9  "3fffffffffffffffffffffffffffffffffffffffffffffffffffffff",
10  "7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3",
11);
12
13impl_modulus!(ScalarModulus, U448, MODULUS_STR);
14type ResidueType = Residue<ScalarModulus, { ScalarModulus::LIMBS }>;
15
16/// Ed448 Scalar field element.
17#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
18pub struct Scalar(pub(crate) ResidueType);
19
20impl DefaultIsZeroes for Scalar {}
21
22// 2**446 - 13818066809895115352007386748515426880336692474882178609894547503885
23pub(crate) const MODULUS: U448 = U448::from_be_hex(MODULUS_STR);
24
25const WIDE_MODULUS: U896 = U896::from_be_hex(concat!(
26  "00000000000000000000000000000000000000000000000000000000",
27  "00000000000000000000000000000000000000000000000000000000",
28  "3fffffffffffffffffffffffffffffffffffffffffffffffffffffff",
29  "7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3",
30));
31
32const WIDE_REDUCTION_MODULUS: NonZero<U1024> = NonZero::from_uint(U1024::from_be_hex(concat!(
33  "00000000000000000000000000000000",
34  "00000000000000000000000000000000000000000000000000000000",
35  "00000000000000000000000000000000000000000000000000000000",
36  "3fffffffffffffffffffffffffffffffffffffffffffffffffffffff",
37  "7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3",
38)));
39
40field!(
41  Scalar,
42  ResidueType,
43  MODULUS_STR,
44  MODULUS,
45  WIDE_MODULUS,
46  446,
47  2,
48  concat!(
49    "04000000000000000000000000000000000000000000000000000000",
50    "00000000000000000000000000000000000000000000000000000000",
51  ),
52);
53
54impl Scalar {
55  /// Perform a wide reduction to obtain a non-biased Scalar.
56  pub fn wide_reduce(bytes: [u8; 114]) -> Scalar {
57    let mut bytes_128 = [0; 128];
58    bytes_128[.. 114].copy_from_slice(&bytes);
59    let wide = U1024::from_le_slice(&bytes_128);
60    Scalar(Residue::new(&U448::from_le_slice(
61      &wide.rem(&WIDE_REDUCTION_MODULUS).to_le_bytes()[.. 56],
62    )))
63  }
64}
65
66#[test]
67fn test_scalar() {
68  ff_group_tests::prime_field::test_prime_field_bits::<_, Scalar>(&mut rand_core::OsRng);
69}