use super::*;
use rand_core::SeedableRng;
use *;
#[test]
fn test_pairing_product() {
let mut rng = rand_xorshift::XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
for _ in 0..100 {
let p1 = G1::random(&mut rng);
let p2 = G1::random(&mut rng);
let q1 = G2::random(&mut rng);
let q2 = G2::random(&mut rng);
let mut t1 = Bls12::pairing(p1, q1);
let t2 = Bls12::pairing(p2, q2);
t1.mul_assign(&t2);
let t = Bls12::pairing_product(p1, q1, p2, q2);
assert_eq!(t1, t, "pairing product incorrect");
}
}
#[test]
fn test_pairing_multi_product() {
let mut rng = rand_xorshift::XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let size = 10;
let p: Vec<G1Affine> = (0..size)
.map(|_| G1::random(&mut rng).into_affine())
.collect();
let q: Vec<G2Affine> = (0..size)
.map(|_| G2::random(&mut rng).into_affine())
.collect();
for n in 0..size {
let mut t = Fq12::one();
for i in 0..n {
let p1 = G1Affine::into_projective(&p[i]);
let q1 = G2Affine::into_projective(&q[i]);
t.mul_assign(&Bls12::pairing(p1, q1));
}
assert_eq!(
t,
Bls12::pairing_multi_product(&p[0..n], &q[0..n]),
"pairing multi product incorrect"
);
}
}
#[test]
fn test_pairing_result_against_relic() {
assert_eq!(Bls12::pairing(G1::one(), G2::one()), Fq12 {
c0: Fq6 {
c0: Fq2 {
c0: Fq::from_str("2819105605953691245277803056322684086884703000473961065716485506033588504203831029066448642358042597501014294104502").unwrap(),
c1: Fq::from_str("1323968232986996742571315206151405965104242542339680722164220900812303524334628370163366153839984196298685227734799").unwrap()
},
c1: Fq2 {
c0: Fq::from_str("2987335049721312504428602988447616328830341722376962214011674875969052835043875658579425548512925634040144704192135").unwrap(),
c1: Fq::from_str("3879723582452552452538684314479081967502111497413076598816163759028842927668327542875108457755966417881797966271311").unwrap()
},
c2: Fq2 {
c0: Fq::from_str("261508182517997003171385743374653339186059518494239543139839025878870012614975302676296704930880982238308326681253").unwrap(),
c1: Fq::from_str("231488992246460459663813598342448669854473942105054381511346786719005883340876032043606739070883099647773793170614").unwrap()
}
},
c1: Fq6 {
c0: Fq2 {
c0: Fq::from_str("3993582095516422658773669068931361134188738159766715576187490305611759126554796569868053818105850661142222948198557").unwrap(),
c1: Fq::from_str("1074773511698422344502264006159859710502164045911412750831641680783012525555872467108249271286757399121183508900634").unwrap()
},
c1: Fq2 {
c0: Fq::from_str("2727588299083545686739024317998512740561167011046940249988557419323068809019137624943703910267790601287073339193943").unwrap(),
c1: Fq::from_str("493643299814437640914745677854369670041080344349607504656543355799077485536288866009245028091988146107059514546594").unwrap()
},
c2: Fq2 {
c0: Fq::from_str("734401332196641441839439105942623141234148957972407782257355060229193854324927417865401895596108124443575283868655").unwrap(),
c1: Fq::from_str("2348330098288556420918672502923664952620152483128593484301759394583320358354186482723629999370241674973832318248497").unwrap()
}
}
});
}
fn test_vectors<G: CurveProjective, E: EncodedPoint<Affine = G::Affine>>(expected: &[u8]) {
let mut e = G::zero();
let mut v = vec![];
{
let mut expected = expected;
for _ in 0..1000 {
let e_affine = e.into_affine();
let encoded = E::from_affine(e_affine);
v.extend_from_slice(encoded.as_ref());
let mut decoded = E::empty();
decoded.as_mut().copy_from_slice(&expected[0..E::size()]);
expected = &expected[E::size()..];
let decoded = decoded.into_affine().unwrap();
assert_eq!(e_affine, decoded);
e.add_assign(&G::one());
}
}
assert_eq!(&v[..], expected);
}
#[test]
fn test_g1_uncompressed_valid_vectors() {
test_vectors::<G1, G1Uncompressed>(include_bytes!("g1_uncompressed_valid_test_vectors.dat"));
}
#[test]
fn test_g1_compressed_valid_vectors() {
test_vectors::<G1, G1Compressed>(include_bytes!("g1_compressed_valid_test_vectors.dat"));
}
#[test]
fn test_g2_uncompressed_valid_vectors() {
test_vectors::<G2, G2Uncompressed>(include_bytes!("g2_uncompressed_valid_test_vectors.dat"));
}
#[test]
fn test_g2_compressed_valid_vectors() {
test_vectors::<G2, G2Compressed>(include_bytes!("g2_compressed_valid_test_vectors.dat"));
}
#[test]
fn test_g1_uncompressed_invalid_vectors() {
{
let z = G1Affine::zero().into_uncompressed();
{
let mut z = z;
z.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = z.into_affine() {
} else {
panic!("should have rejected the point because we expected an uncompressed point");
}
}
{
let mut z = z;
z.as_mut()[0] |= 0b0010_0000;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
} else {
panic!("should have rejected the point because the parity bit should not be set if the point is at infinity");
}
}
for i in 0..G1Uncompressed::size() {
let mut z = z;
z.as_mut()[i] |= 0b0000_0001;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
} else {
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
}
}
}
let o = G1Affine::one().into_uncompressed();
{
let mut o = o;
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = o.into_affine() {
} else {
panic!("should have rejected the point because we expected an uncompressed point");
}
}
let m = Fq::char();
{
let mut o = o;
m.write_be(&mut o.as_mut()[0..]).unwrap();
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate");
} else {
panic!("should have rejected the point")
}
}
{
let mut o = o;
m.write_be(&mut o.as_mut()[48..]).unwrap();
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
assert_eq!(coordinate, "y coordinate");
} else {
panic!("should have rejected the point")
}
}
{
let m = Fq::zero().into_repr();
let mut o = o;
m.write_be(&mut o.as_mut()[0..]).unwrap();
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
} else {
panic!("should have rejected the point because it isn't on the curve")
}
}
{
let mut o = o;
let mut x = Fq::one();
loop {
let mut x3b = x;
x3b.square();
x3b.mul_assign(&x);
x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap());
if let Some(y) = x3b.sqrt() {
x.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
y.into_repr().write_be(&mut o.as_mut()[48..]).unwrap();
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
break;
} else {
panic!(
"should have rejected the point because it isn't in the correct subgroup"
)
}
} else {
x.add_assign(&Fq::one());
}
}
}
}
#[test]
fn test_g2_uncompressed_invalid_vectors() {
{
let z = G2Affine::zero().into_uncompressed();
{
let mut z = z;
z.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = z.into_affine() {
} else {
panic!("should have rejected the point because we expected an uncompressed point");
}
}
{
let mut z = z;
z.as_mut()[0] |= 0b0010_0000;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
} else {
panic!("should have rejected the point because the parity bit should not be set if the point is at infinity");
}
}
for i in 0..G2Uncompressed::size() {
let mut z = z;
z.as_mut()[i] |= 0b0000_0001;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
} else {
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
}
}
}
let o = G2Affine::one().into_uncompressed();
{
let mut o = o;
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = o.into_affine() {
} else {
panic!("should have rejected the point because we expected an uncompressed point");
}
}
let m = Fq::char();
{
let mut o = o;
m.write_be(&mut o.as_mut()[0..]).unwrap();
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate (c1)");
} else {
panic!("should have rejected the point")
}
}
{
let mut o = o;
m.write_be(&mut o.as_mut()[48..]).unwrap();
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate (c0)");
} else {
panic!("should have rejected the point")
}
}
{
let mut o = o;
m.write_be(&mut o.as_mut()[96..]).unwrap();
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
assert_eq!(coordinate, "y coordinate (c1)");
} else {
panic!("should have rejected the point")
}
}
{
let mut o = o;
m.write_be(&mut o.as_mut()[144..]).unwrap();
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
assert_eq!(coordinate, "y coordinate (c0)");
} else {
panic!("should have rejected the point")
}
}
{
let m = Fq::zero().into_repr();
let mut o = o;
m.write_be(&mut o.as_mut()[0..]).unwrap();
m.write_be(&mut o.as_mut()[48..]).unwrap();
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
} else {
panic!("should have rejected the point because it isn't on the curve")
}
}
{
let mut o = o;
let mut x = Fq2::one();
loop {
let mut x3b = x;
x3b.square();
x3b.mul_assign(&x);
x3b.add_assign(&Fq2 {
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
c1: Fq::from_repr(FqRepr::from(4)).unwrap(),
});
if let Some(y) = x3b.sqrt() {
x.c1.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
x.c0.into_repr().write_be(&mut o.as_mut()[48..]).unwrap();
y.c1.into_repr().write_be(&mut o.as_mut()[96..]).unwrap();
y.c0.into_repr().write_be(&mut o.as_mut()[144..]).unwrap();
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
break;
} else {
panic!(
"should have rejected the point because it isn't in the correct subgroup"
)
}
} else {
x.add_assign(&Fq2::one());
}
}
}
}
#[test]
fn test_g1_compressed_invalid_vectors() {
{
let z = G1Affine::zero().into_compressed();
{
let mut z = z;
z.as_mut()[0] &= 0b0111_1111;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = z.into_affine() {
} else {
panic!("should have rejected the point because we expected a compressed point");
}
}
{
let mut z = z;
z.as_mut()[0] |= 0b0010_0000;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
} else {
panic!("should have rejected the point because the parity bit should not be set if the point is at infinity");
}
}
for i in 0..G1Compressed::size() {
let mut z = z;
z.as_mut()[i] |= 0b0000_0001;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
} else {
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
}
}
}
let o = G1Affine::one().into_compressed();
{
let mut o = o;
o.as_mut()[0] &= 0b0111_1111;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = o.into_affine() {
} else {
panic!("should have rejected the point because we expected a compressed point");
}
}
let m = Fq::char();
{
let mut o = o;
m.write_be(&mut o.as_mut()[0..]).unwrap();
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate");
} else {
panic!("should have rejected the point")
}
}
{
let mut o = o;
let mut x = Fq::one();
loop {
let mut x3b = x;
x3b.square();
x3b.mul_assign(&x);
x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap());
if x3b.sqrt().is_some() {
x.add_assign(&Fq::one());
} else {
x.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
break;
} else {
panic!("should have rejected the point because it isn't on the curve")
}
}
}
}
{
let mut o = o;
let mut x = Fq::one();
loop {
let mut x3b = x;
x3b.square();
x3b.mul_assign(&x);
x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap());
if x3b.sqrt().is_some() {
x.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
break;
} else {
panic!(
"should have rejected the point because it isn't in the correct subgroup"
)
}
} else {
x.add_assign(&Fq::one());
}
}
}
}
#[test]
fn test_g2_compressed_invalid_vectors() {
{
let z = G2Affine::zero().into_compressed();
{
let mut z = z;
z.as_mut()[0] &= 0b0111_1111;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = z.into_affine() {
} else {
panic!("should have rejected the point because we expected a compressed point");
}
}
{
let mut z = z;
z.as_mut()[0] |= 0b0010_0000;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
} else {
panic!("should have rejected the point because the parity bit should not be set if the point is at infinity");
}
}
for i in 0..G2Compressed::size() {
let mut z = z;
z.as_mut()[i] |= 0b0000_0001;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
} else {
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
}
}
}
let o = G2Affine::one().into_compressed();
{
let mut o = o;
o.as_mut()[0] &= 0b0111_1111;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = o.into_affine() {
} else {
panic!("should have rejected the point because we expected a compressed point");
}
}
let m = Fq::char();
{
let mut o = o;
m.write_be(&mut o.as_mut()[0..]).unwrap();
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate (c1)");
} else {
panic!("should have rejected the point")
}
}
{
let mut o = o;
m.write_be(&mut o.as_mut()[48..]).unwrap();
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate (c0)");
} else {
panic!("should have rejected the point")
}
}
{
let mut o = o;
let mut x = Fq2 {
c0: Fq::one(),
c1: Fq::one(),
};
loop {
let mut x3b = x;
x3b.square();
x3b.mul_assign(&x);
x3b.add_assign(&Fq2 {
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
c1: Fq::from_repr(FqRepr::from(4)).unwrap(),
});
if x3b.sqrt().is_some() {
x.add_assign(&Fq2::one());
} else {
x.c1.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
x.c0.into_repr().write_be(&mut o.as_mut()[48..]).unwrap();
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
break;
} else {
panic!("should have rejected the point because it isn't on the curve")
}
}
}
}
{
let mut o = o;
let mut x = Fq2 {
c0: Fq::one(),
c1: Fq::one(),
};
loop {
let mut x3b = x;
x3b.square();
x3b.mul_assign(&x);
x3b.add_assign(&Fq2 {
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
c1: Fq::from_repr(FqRepr::from(4)).unwrap(),
});
if x3b.sqrt().is_some() {
x.c1.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
x.c0.into_repr().write_be(&mut o.as_mut()[48..]).unwrap();
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
break;
} else {
panic!(
"should have rejected the point because it isn't in the correct subgroup"
)
}
} else {
x.add_assign(&Fq2::one());
}
}
}
}