From c000957bae0cda532c82385683376e1ec237c27b Mon Sep 17 00:00:00 2001 From: Hugo Tunius Date: Sat, 22 Oct 2022 09:42:23 +0200 Subject: [PATCH] Remove byteorder (#418) Instead of having a dependency on `byteorder`, use methods from the standard library(`{to,from}_le_bytes`). --- Cargo.toml | 1 - src/scalar.rs | 116 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 97 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 35b2e72..9b58da3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,6 @@ harness = false [dependencies] rand_core = { version = "0.6", default-features = false } -byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] } digest = { version = "0.10", default-features = false } subtle = { version = "^2.2.1", default-features = false } serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] } diff --git a/src/scalar.rs b/src/scalar.rs index 3adf046..ac3d9cf 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -138,6 +138,7 @@ use core::borrow::Borrow; use core::cmp::{Eq, PartialEq}; +use core::convert::TryInto; use core::fmt::Debug; use core::iter::{Product, Sum}; use core::ops::Index; @@ -476,19 +477,19 @@ impl From for Scalar { impl From for Scalar { fn from(x: u16) -> Scalar { - use byteorder::{ByteOrder, LittleEndian}; let mut s_bytes = [0u8; 32]; - LittleEndian::write_u16(&mut s_bytes, x); - Scalar{ bytes: s_bytes } + let x_bytes = x.to_le_bytes(); + s_bytes[0..x_bytes.len()].copy_from_slice(&x_bytes); + Scalar { bytes: s_bytes } } } impl From for Scalar { fn from(x: u32) -> Scalar { - use byteorder::{ByteOrder, LittleEndian}; let mut s_bytes = [0u8; 32]; - LittleEndian::write_u32(&mut s_bytes, x); - Scalar{ bytes: s_bytes } + let x_bytes = x.to_le_bytes(); + s_bytes[0..x_bytes.len()].copy_from_slice(&x_bytes); + Scalar { bytes: s_bytes } } } @@ -515,19 +516,19 @@ impl From for Scalar { /// assert!(fourtytwo == six * seven); /// ``` fn from(x: u64) -> Scalar { - use byteorder::{ByteOrder, LittleEndian}; let mut s_bytes = [0u8; 32]; - LittleEndian::write_u64(&mut s_bytes, x); - Scalar{ bytes: s_bytes } + let x_bytes = x.to_le_bytes(); + s_bytes[0..x_bytes.len()].copy_from_slice(&x_bytes); + Scalar { bytes: s_bytes } } } impl From for Scalar { fn from(x: u128) -> Scalar { - use byteorder::{ByteOrder, LittleEndian}; let mut s_bytes = [0u8; 32]; - LittleEndian::write_u128(&mut s_bytes, x); - Scalar{ bytes: s_bytes } + let x_bytes = x.to_le_bytes(); + s_bytes[0..x_bytes.len()].copy_from_slice(&x_bytes); + Scalar { bytes: s_bytes } } } @@ -897,14 +898,12 @@ impl Scalar { // required by the NAF definition debug_assert!( w >= 2 ); // required so that the NAF digits fit in i8 - debug_assert!( w <= 8 ); - - use byteorder::{ByteOrder, LittleEndian}; + debug_assert!(w <= 8); let mut naf = [0i8; 256]; let mut x_u64 = [0u64; 5]; - LittleEndian::read_u64_into(&self.bytes, &mut x_u64[0..4]); + read_le_u64_into(&self.bytes, &mut x_u64[0..4]); let width = 1 << w; let window_mask = width - 1; @@ -1030,11 +1029,9 @@ impl Scalar { return self.to_radix_16(); } - use byteorder::{ByteOrder, LittleEndian}; - // Scalar formatted as four `u64`s with carry bit packed into the highest bit. let mut scalar64x4 = [0u64; 4]; - LittleEndian::read_u64_into(&self.bytes, &mut scalar64x4[0..4]); + read_le_u64_into(&self.bytes, &mut scalar64x4[0..4]); let radix: u64 = 1 << w; let window_mask: u64 = radix - 1; @@ -1186,6 +1183,26 @@ impl UnpackedScalar { } } +/// Read one or more u64s stored as little endian bytes. +/// +/// ## Panics +/// Panics if `src.len() != 8 * dst.len()`. +fn read_le_u64_into(src: &[u8], dst: &mut [u64]) { + assert!( + src.len() == 8 * dst.len(), + "src.len() = {}, dst.len() = {}", + src.len(), + dst.len() + ); + for (bytes, val) in src.chunks(8).zip(dst.iter_mut()) { + *val = u64::from_le_bytes( + bytes + .try_into() + .expect("Incorrect src length, should be 8 * dst.len()"), + ); + } +} + #[cfg(test)] mod test { use super::*; @@ -1738,4 +1755,65 @@ mod test { test_pippenger_radix_iter(scalar, 8); } } + + #[test] + fn test_read_le_u64_into() { + let cases: &[(&[u8], &[u64])] = &[ + ( + &[0xFE, 0xEF, 0x10, 0x01, 0x1F, 0xF1, 0x0F, 0xF0], + &[0xF00F_F11F_0110_EFFE], + ), + ( + &[ + 0xFE, 0xEF, 0x10, 0x01, 0x1F, 0xF1, 0x0F, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, + 0xBC, 0xDE, 0xF0, + ], + &[0xF00F_F11F_0110_EFFE, 0xF0DE_BC9A_7856_3412], + ), + ]; + + for (src, expected) in cases { + let mut dst = vec![0; expected.len()]; + read_le_u64_into(src, &mut dst); + + assert_eq!(&dst, expected, "Expected {:x?} got {:x?}", expected, dst); + } + } + + // Tests consistency of From<{integer}> impls for Scalar + #[test] + fn test_scalar_from_int() { + let s1 = Scalar::one(); + + // For `x` in `u8`, `u16`, `u32`, `u64`, and `u128`, check that + // `Scalar::from(x + 1) == Scalar::from(x) + Scalar::from(1)` + + let x = 0x23u8; + let sx = Scalar::from(x); + assert_eq!(sx + s1, Scalar::from(x + 1)); + + let x = 0x2323u16; + let sx = Scalar::from(x); + assert_eq!(sx + s1, Scalar::from(x + 1)); + + let x = 0x2323_2323u32; + let sx = Scalar::from(x); + assert_eq!(sx + s1, Scalar::from(x + 1)); + + let x = 0x2323_2323_2323_2323u64; + let sx = Scalar::from(x); + assert_eq!(sx + s1, Scalar::from(x + 1)); + + let x = 0x2323_2323_2323_2323_2323_2323_2323_2323u128; + let sx = Scalar::from(x); + assert_eq!(sx + s1, Scalar::from(x + 1)); + } + + #[test] + #[should_panic] + fn test_read_le_u64_into_should_panic_on_bad_input() { + let mut dst = [0_u64; 1]; + // One byte short + read_le_u64_into(&[0xFE, 0xEF, 0x10, 0x01, 0x1F, 0xF1, 0x0F], &mut dst); + } }