3.5.2 Add more tests to ff-group-tests

The audit recommends checking failure cases for from_bytes,
from_bytes_unechecked, and from_repr. This isn't feasible.

from_bytes is allowed to have non-canonical values. [0xff; 32] may accordingly
be a valid point for non-SEC1-encoded curves.

from_bytes_unchecked doesn't have a defined failure mode, and by name,
unchecked, shouldn't necessarily fail. The audit acknowledges the tests should
test for whatever result is 'appropriate', yet any result which isn't a failure
on a valid element is appropriate.

from_repr must be canonical, yet for a binary field of 2^n where n % 8 == 0, a
[0xff; n / 8] repr would be valid.
This commit is contained in:
Luke Parker
2023-02-24 06:03:56 -05:00
parent 32c18cac84
commit 93f7afec8b
13 changed files with 95 additions and 25 deletions

View File

@@ -1,3 +1,4 @@
use rand_core::RngCore;
use group::ff::{PrimeField, PrimeFieldBits};
use crate::field::test_field;
@@ -29,6 +30,16 @@ pub fn test_is_odd<F: PrimeField>() {
assert_eq!(F::one().is_odd().unwrap_u8(), 1, "1 was even");
assert_eq!(F::one().is_even().unwrap_u8(), 0, "1 wasn't odd");
// Make sure an odd value added to an odd value is even
let two = F::one().double();
assert_eq!(two.is_odd().unwrap_u8(), 0, "2 was odd");
assert_eq!(two.is_even().unwrap_u8(), 1, "2 wasn't even");
// Make sure an even value added to an even value is even
let four = two.double();
assert_eq!(four.is_odd().unwrap_u8(), 0, "4 was odd");
assert_eq!(four.is_even().unwrap_u8(), 1, "4 wasn't even");
let neg_one = -F::one();
assert_eq!(neg_one.is_odd().unwrap_u8(), 0, "-1 was odd");
assert_eq!(neg_one.is_even().unwrap_u8(), 1, "-1 wasn't even");
@@ -49,6 +60,11 @@ pub fn test_encoding<F: PrimeField>() {
F::from_repr_vartime(repr).unwrap(),
"{msg} couldn't be encoded and decoded",
);
assert_eq!(
bytes.as_ref(),
F::from_repr(repr).unwrap().to_repr().as_ref(),
"canonical encoding decoded produced distinct encoding"
);
};
test(F::zero(), "0");
test(F::one(), "1");
@@ -57,8 +73,8 @@ pub fn test_encoding<F: PrimeField>() {
}
/// Run all tests on fields implementing PrimeField.
pub fn test_prime_field<F: PrimeField>() {
test_field::<F>();
pub fn test_prime_field<R: RngCore, F: PrimeField>(rng: &mut R) {
test_field::<R, F>(rng);
test_zero::<F>();
test_one::<F>();
@@ -265,6 +281,7 @@ pub fn test_root_of_unity<F: PrimeFieldBits>() {
}
bit = bit.double();
}
assert!(bool::from(t.is_odd()), "t wasn't odd");
assert_eq!(pow(F::multiplicative_generator(), t), F::root_of_unity(), "incorrect root of unity");
assert_eq!(
@@ -275,8 +292,8 @@ pub fn test_root_of_unity<F: PrimeFieldBits>() {
}
/// Run all tests on fields implementing PrimeFieldBits.
pub fn test_prime_field_bits<F: PrimeFieldBits>() {
test_prime_field::<F>();
pub fn test_prime_field_bits<R: RngCore, F: PrimeFieldBits>(rng: &mut R) {
test_prime_field::<R, F>(rng);
test_to_le_bits::<F>();
test_char_le_bits::<F>();