Skip to content

Commit c451e15

Browse files
authored
Add BoxedUint::{from_be_slice_vartime, from_le_slice_vartime} (#833)
Adds methods for decoding `BoxedUint` which infer the precision from the input size. This is useful for decoding public parameters, especially when the size of other parameters is inferred from some public parameter that needs to be decoded first, e.g. RSA modulus.
1 parent 3549014 commit c451e15

File tree

2 files changed

+60
-2
lines changed

2 files changed

+60
-2
lines changed

src/uint/boxed/encoding.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,20 @@ impl BoxedUint {
3939
Ok(ret)
4040
}
4141

42+
/// Create a new [`BoxedUint`] from the provided big endian bytes, automatically selecting its
43+
/// precision based on the size of the input.
44+
///
45+
/// This method is variable-time with respect to all subsequent operations since it chooses the
46+
/// limb count based on the input size, and is therefore only suitable for public inputs.
47+
///
48+
/// When working with secret values, use [`BoxedUint::from_be_slice`].
49+
pub fn from_be_slice_vartime(bytes: &[u8]) -> Self {
50+
let bits_precision = (bytes.len() as u32).saturating_mul(8);
51+
52+
// TODO(tarcieri): avoid panic
53+
Self::from_be_slice(bytes, bits_precision).expect("precision should be large enough")
54+
}
55+
4256
/// Create a new [`BoxedUint`] from the provided little endian bytes.
4357
///
4458
/// The `bits_precision` argument represents the precision of the resulting integer, which is
@@ -72,6 +86,20 @@ impl BoxedUint {
7286
Ok(ret)
7387
}
7488

89+
/// Create a new [`BoxedUint`] from the provided little endian bytes, automatically selecting
90+
/// its precision based on the size of the input.
91+
///
92+
/// This method is variable-time with respect to all subsequent operations since it chooses the
93+
/// limb count based on the input size, and is therefore only suitable for public inputs.
94+
///
95+
/// When working with secret values, use [`BoxedUint::from_le_slice`].
96+
pub fn from_le_slice_vartime(bytes: &[u8]) -> Self {
97+
let bits_precision = (bytes.len() as u32).saturating_mul(8);
98+
99+
// TODO(tarcieri): avoid panic
100+
Self::from_le_slice(bytes, bits_precision).expect("precision should be large enough")
101+
}
102+
75103
/// Serialize this [`BoxedUint`] as big-endian.
76104
#[inline]
77105
pub fn to_be_bytes(&self) -> Box<[u8]> {
@@ -343,6 +371,15 @@ mod tests {
343371
);
344372
}
345373

374+
#[test]
375+
fn from_be_slice_vartime() {
376+
let bytes = hex!(
377+
"111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111F"
378+
);
379+
let uint = BoxedUint::from_be_slice_vartime(&bytes);
380+
assert_eq!(&*uint.to_be_bytes_trimmed_vartime(), bytes.as_slice());
381+
}
382+
346383
#[test]
347384
#[cfg(target_pointer_width = "32")]
348385
fn from_le_slice_eq() {
@@ -436,6 +473,15 @@ mod tests {
436473
);
437474
}
438475

476+
#[test]
477+
fn from_le_slice_vartime() {
478+
let bytes = hex!(
479+
"111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111F"
480+
);
481+
let uint = BoxedUint::from_le_slice_vartime(&bytes);
482+
assert_eq!(&*uint.to_le_bytes_trimmed_vartime(), bytes.as_slice());
483+
}
484+
439485
#[test]
440486
fn to_be_bytes() {
441487
let bytes = hex!("00112233445566778899aabbccddeeff");

tests/boxed_uint.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,6 @@ proptest! {
283283
}
284284
}
285285

286-
287286
#[test]
288287
fn shr_vartime(a in uint(), shift in any::<u16>()) {
289288
let a_bi = to_biguint(&a);
@@ -302,7 +301,6 @@ proptest! {
302301
}
303302
}
304303

305-
306304
#[test]
307305
fn radix_encode_vartime(a in uint(), radix in 2u32..=36) {
308306
let a_bi = to_biguint(&a);
@@ -316,4 +314,18 @@ proptest! {
316314
prop_assert_eq!(dec_bi, a_bi);
317315

318316
}
317+
318+
#[test]
319+
fn from_be_slice_vartime(a in uint()) {
320+
let a_bytes = a.to_be_bytes_trimmed_vartime();
321+
let b = BoxedUint::from_be_slice_vartime(&a_bytes);
322+
prop_assert_eq!(a, b);
323+
}
324+
325+
#[test]
326+
fn from_le_slice_vartime(a in uint()) {
327+
let a_bytes = a.to_le_bytes_trimmed_vartime();
328+
let b = BoxedUint::from_le_slice_vartime(&a_bytes);
329+
prop_assert_eq!(a, b);
330+
}
319331
}

0 commit comments

Comments
 (0)