From 01d9e904e1b5a0874550b36c395b2c16bf412ee9 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 5 Aug 2019 15:53:00 -0700 Subject: [PATCH] Add a missing wrapping_sub in NAF computation. Found by @3for; this only affected width-7 NAF computations, which were never used in the source tree (only width 5, optimal for dynamic cases, and 8, better for static cases). Closes #272 --- src/scalar.rs | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/scalar.rs b/src/scalar.rs index 575fefe..fe794db 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -917,7 +917,7 @@ impl Scalar { naf[pos] = window as i8; } else { carry = 1; - naf[pos] = (window as i8) - (width as i8); + naf[pos] = (window as i8).wrapping_sub(width as i8); } pos += w; @@ -1264,13 +1264,42 @@ mod test { } #[test] - fn non_adjacent_form() { + fn non_adjacent_form_test_vector() { let naf = A_SCALAR.non_adjacent_form(5); for i in 0..256 { assert_eq!(naf[i], A_NAF[i]); } } + fn non_adjacent_form_iter(w: usize, x: &Scalar) { + let naf = x.non_adjacent_form(w); + + // Reconstruct the scalar from the computed NAF + let mut y = Scalar::zero(); + for i in (0..256).rev() { + y += y; + let digit = if naf[i] < 0 { + -Scalar::from((-naf[i]) as u64) + } else { + Scalar::from(naf[i] as u64) + }; + y += digit; + } + + assert_eq!(*x, y); + } + + #[test] + fn non_adjacent_form_random() { + let mut rng = rand::thread_rng(); + for _ in 0..1_000 { + let x = Scalar::random(&mut rng); + for w in &[5, 6, 7, 8] { + non_adjacent_form_iter(*w, &x); + } + } + } + #[test] fn from_u64() { let val: u64 = 0xdeadbeefdeadbeef;