Skip to main content

ed448_goldilocks/curve/scalar_mul/
variable_base.rs

1#![allow(non_snake_case)]
2
3use super::window::wnaf::LookupTable;
4use crate::EdwardsScalar;
5use crate::curve::twedwards::{extended::ExtendedPoint, extensible::ExtensiblePoint};
6use subtle::{Choice, ConditionallyNegatable};
7
8pub fn variable_base(point: &ExtendedPoint, s: &EdwardsScalar) -> ExtensiblePoint {
9    let mut result = ExtensiblePoint::IDENTITY;
10
11    // Recode Scalar
12    let scalar = s.to_radix_16();
13
14    let lookup = LookupTable::from(point);
15
16    for i in (0..113).rev() {
17        result = result.double().double().double().double();
18
19        // The mask is the top bit, will be 1 for negative numbers, 0 for positive numbers
20        let mask = scalar[i] >> 7;
21        let sign = mask & 0x1;
22        // Use the mask to get the absolute value of scalar
23        let abs_value = ((scalar[i] + mask) ^ mask) as u32;
24
25        let mut neg_P = lookup.select(abs_value);
26        neg_P.conditional_negate(Choice::from((sign) as u8));
27
28        result = result.to_extended().add_projective_niels(&neg_P);
29    }
30
31    result
32}
33
34#[cfg(test)]
35mod test {
36    use super::*;
37    use crate::TWISTED_EDWARDS_BASE_POINT;
38    use crate::curve::scalar_mul::double_and_add;
39    use elliptic_curve::bigint::U448;
40
41    #[test]
42    fn test_scalar_mul() {
43        // XXX: In the future use known multiples from Sage in bytes form?
44        let twisted_point = TWISTED_EDWARDS_BASE_POINT;
45        let scalar = EdwardsScalar::new(U448::from_be_hex(
46            "05ca185aee2e1b73def437f63c003777083f83043fe5bf1aab454c66b64629d1de8026c1307f665ead0b70151533427ce128ae786ee372b7",
47        ));
48
49        let got = variable_base(&twisted_point, &scalar);
50
51        let got2 = double_and_add(&twisted_point, scalar.bits());
52        assert_eq!(got, got2);
53
54        // Lets see if this is conserved over the isogenies
55        let edwards_point = twisted_point.to_untwisted();
56        let got_untwisted_point = edwards_point.scalar_mul(&scalar);
57        let expected_untwisted_point = got.to_extended().to_untwisted();
58        assert_eq!(got_untwisted_point, expected_untwisted_point);
59    }
60
61    #[test]
62    fn test_simple_scalar_mul_identities() {
63        let x = TWISTED_EDWARDS_BASE_POINT;
64
65        // Test that 1 * P = P
66        let exp = variable_base(&x, &EdwardsScalar::from(1u8));
67        assert!(x == exp);
68        // Test that 2 * (P + P) = 4 * P
69        let expected_two_x = x.add_extended(&x).double();
70        let got = variable_base(&x, &EdwardsScalar::from(4u8));
71        assert!(expected_two_x == got);
72    }
73}