Conditional negate (#90)

* Reorder tests in dalek-ff-group

* Add required method for ConditionallyNegatable

Adds lifetime bound implementation `Neg`
for borrowed FieldElements in dalek-ff-group.
This commit is contained in:
J. Burfeind 2022-08-18 22:02:31 +02:00 committed by GitHub
parent 45912d6837
commit a2aa182cc4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -2,7 +2,7 @@ use core::ops::{Add, AddAssign, Sub, SubAssign, Neg, Mul, MulAssign};
use rand_core::RngCore; use rand_core::RngCore;
use subtle::{Choice, CtOption, ConstantTimeEq, ConditionallySelectable}; use subtle::{Choice, CtOption, ConstantTimeEq, ConditionallyNegatable, ConditionallySelectable};
use crypto_bigint::{Encoding, U256, U512}; use crypto_bigint::{Encoding, U256, U512};
@ -50,6 +50,13 @@ impl Neg for FieldElement {
} }
} }
impl<'a> Neg for &'a FieldElement {
type Output = FieldElement;
fn neg(self) -> Self::Output {
(*self).neg()
}
}
impl Field for FieldElement { impl Field for FieldElement {
fn random(mut rng: impl RngCore) -> Self { fn random(mut rng: impl RngCore) -> Self {
let mut bytes = [0; 64]; let mut bytes = [0; 64];
@ -174,7 +181,7 @@ impl FieldElement {
r.conditional_assign(&r_prime, flipped_sign | flipped_sign_i); r.conditional_assign(&r_prime, flipped_sign | flipped_sign_i);
let r_is_negative = r.is_odd(); let r_is_negative = r.is_odd();
r.conditional_assign(&(-r), r_is_negative); r.conditional_negate(r_is_negative);
let was_non_zero_square = correct_sign | flipped_sign; let was_non_zero_square = correct_sign | flipped_sign;
@ -182,6 +189,32 @@ impl FieldElement {
} }
} }
#[test]
fn test_conditional_negate() {
let one = FieldElement::one();
let true_choice = choice(true);
let false_choice = choice(false);
let mut var = one;
var.conditional_negate(false_choice);
assert_eq!(var, FieldElement::one());
var.conditional_negate(true_choice);
assert_eq!(var, -FieldElement::one());
var.conditional_negate(false_choice);
assert_eq!(var, -FieldElement::one());
}
#[test]
fn test_edwards_d() {
let a = -FieldElement(U256::from_u32(121665));
let b = FieldElement(U256::from_u32(121666));
assert_eq!(EDWARDS_D, a * b.invert().unwrap());
}
#[test] #[test]
fn test_is_odd() { fn test_is_odd() {
assert_eq!(0, FieldElement::zero().is_odd().unwrap_u8()); assert_eq!(0, FieldElement::zero().is_odd().unwrap_u8());
@ -194,14 +227,6 @@ fn test_is_odd() {
assert_eq!(1, (-FieldElement::one().double()).is_odd().unwrap_u8()); assert_eq!(1, (-FieldElement::one().double()).is_odd().unwrap_u8());
} }
#[test]
fn test_edwards_d() {
let a = -FieldElement(U256::from_u32(121665));
let b = FieldElement(U256::from_u32(121666));
assert_eq!(EDWARDS_D, a * b.invert().unwrap());
}
#[test] #[test]
fn test_mul() { fn test_mul() {
assert_eq!(FieldElement(FIELD_MODULUS) * FieldElement::one(), FieldElement::zero()); assert_eq!(FieldElement(FIELD_MODULUS) * FieldElement::one(), FieldElement::zero());