Implement constant time comparison and selection of Fp elements.
This commit is contained in:
parent
419c62536c
commit
f9b3f177f2
75
src/fp.rs
75
src/fp.rs
|
@ -1,5 +1,78 @@
|
||||||
//! This module provides an implementation of the BLS12-381 base field `GF(p)`
|
//! This module provides an implementation of the BLS12-381 base field `GF(p)`
|
||||||
//! where `p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab`
|
//! where `p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab`
|
||||||
|
|
||||||
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
|
||||||
|
|
||||||
|
// The internal representation of this type is six 64-bit unsigned
|
||||||
|
// integers in little-endian order. `Fp` values are always in
|
||||||
|
// Montgomery form; i.e., Scalar(a) = aR mod p, with R = 2^384.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct Fp;
|
pub struct Fp([u64; 6]);
|
||||||
|
|
||||||
|
impl ConstantTimeEq for Fp {
|
||||||
|
fn ct_eq(&self, other: &Self) -> Choice {
|
||||||
|
self.0[0].ct_eq(&other.0[0])
|
||||||
|
& self.0[1].ct_eq(&other.0[1])
|
||||||
|
& self.0[2].ct_eq(&other.0[2])
|
||||||
|
& self.0[3].ct_eq(&other.0[3])
|
||||||
|
& self.0[4].ct_eq(&other.0[4])
|
||||||
|
& self.0[5].ct_eq(&other.0[5])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Fp {}
|
||||||
|
impl PartialEq for Fp {
|
||||||
|
#[inline]
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.ct_eq(other).unwrap_u8() == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConditionallySelectable for Fp {
|
||||||
|
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||||
|
Fp([
|
||||||
|
u64::conditional_select(&a.0[0], &b.0[0], choice),
|
||||||
|
u64::conditional_select(&a.0[1], &b.0[1], choice),
|
||||||
|
u64::conditional_select(&a.0[2], &b.0[2], choice),
|
||||||
|
u64::conditional_select(&a.0[3], &b.0[3], choice),
|
||||||
|
u64::conditional_select(&a.0[4], &b.0[4], choice),
|
||||||
|
u64::conditional_select(&a.0[5], &b.0[5], choice),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_conditional_selection() {
|
||||||
|
let a = Fp([1, 2, 3, 4, 5, 6]);
|
||||||
|
let b = Fp([7, 8, 9, 10, 11, 12]);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
ConditionallySelectable::conditional_select(&a, &b, Choice::from(0u8)),
|
||||||
|
a
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
ConditionallySelectable::conditional_select(&a, &b, Choice::from(1u8)),
|
||||||
|
b
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_equality() {
|
||||||
|
fn is_equal(a: &Fp, b: &Fp) -> bool {
|
||||||
|
let eq = a == b;
|
||||||
|
let ct_eq = a.ct_eq(&b);
|
||||||
|
|
||||||
|
assert_eq!(eq, ct_eq.unwrap_u8() == 1);
|
||||||
|
|
||||||
|
eq
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(is_equal(&Fp([1, 2, 3, 4, 5, 6]), &Fp([1, 2, 3, 4, 5, 6])));
|
||||||
|
|
||||||
|
assert!(!is_equal(&Fp([7, 2, 3, 4, 5, 6]), &Fp([1, 2, 3, 4, 5, 6])));
|
||||||
|
assert!(!is_equal(&Fp([1, 7, 3, 4, 5, 6]), &Fp([1, 2, 3, 4, 5, 6])));
|
||||||
|
assert!(!is_equal(&Fp([1, 2, 7, 4, 5, 6]), &Fp([1, 2, 3, 4, 5, 6])));
|
||||||
|
assert!(!is_equal(&Fp([1, 2, 3, 7, 5, 6]), &Fp([1, 2, 3, 4, 5, 6])));
|
||||||
|
assert!(!is_equal(&Fp([1, 2, 3, 4, 7, 6]), &Fp([1, 2, 3, 4, 5, 6])));
|
||||||
|
assert!(!is_equal(&Fp([1, 2, 3, 4, 5, 7]), &Fp([1, 2, 3, 4, 5, 6])));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue