Add conversion between affine and projective models.
This commit is contained in:
parent
9e671eed0c
commit
0ccb2fbff0
|
@ -29,6 +29,9 @@ fn criterion_benchmark(c: &mut Criterion) {
|
|||
c.bench_function(&format!("{} check equality", name), move |b| {
|
||||
b.iter(|| black_box(a) == black_box(a))
|
||||
});
|
||||
c.bench_function(&format!("{} to affine", name), move |b| {
|
||||
b.iter(|| G1Affine::from(black_box(a)))
|
||||
});
|
||||
}
|
||||
|
||||
// G2Affine
|
||||
|
@ -53,6 +56,9 @@ fn criterion_benchmark(c: &mut Criterion) {
|
|||
c.bench_function(&format!("{} check equality", name), move |b| {
|
||||
b.iter(|| black_box(a) == black_box(a))
|
||||
});
|
||||
c.bench_function(&format!("{} to affine", name), move |b| {
|
||||
b.iter(|| G2Affine::from(black_box(a)))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
91
src/g1.rs
91
src/g1.rs
|
@ -16,6 +16,30 @@ pub struct G1Affine {
|
|||
infinity: Choice,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a G1Projective> for G1Affine {
|
||||
fn from(p: &'a G1Projective) -> G1Affine {
|
||||
let zinv = p.z.invert().unwrap_or(Fp::zero());
|
||||
let zinv2 = zinv.square();
|
||||
let x = p.x * zinv2;
|
||||
let zinv3 = zinv2 * zinv;
|
||||
let y = p.y * zinv3;
|
||||
|
||||
let tmp = G1Affine {
|
||||
x,
|
||||
y,
|
||||
infinity: Choice::from(0u8),
|
||||
};
|
||||
|
||||
G1Affine::conditional_select(&tmp, &G1Affine::identity(), zinv.is_zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<G1Projective> for G1Affine {
|
||||
fn from(p: G1Projective) -> G1Affine {
|
||||
G1Affine::from(&p)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstantTimeEq for G1Affine {
|
||||
fn ct_eq(&self, other: &Self) -> Choice {
|
||||
// The only cases in which two points are equal are
|
||||
|
@ -91,6 +115,12 @@ impl G1Affine {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if this element is the identity (the point at infinity).
|
||||
#[inline]
|
||||
pub fn is_identity(&self) -> Choice {
|
||||
self.infinity
|
||||
}
|
||||
|
||||
/// Returns true if this point is on the curve. This should always return
|
||||
/// true unless an "unchecked" API was used.
|
||||
pub fn is_on_curve(&self) -> Choice {
|
||||
|
@ -107,6 +137,22 @@ pub struct G1Projective {
|
|||
z: Fp,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a G1Affine> for G1Projective {
|
||||
fn from(p: &'a G1Affine) -> G1Projective {
|
||||
G1Projective {
|
||||
x: p.x,
|
||||
y: p.y,
|
||||
z: Fp::conditional_select(&Fp::one(), &Fp::zero(), p.infinity),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<G1Affine> for G1Projective {
|
||||
fn from(p: G1Affine) -> G1Projective {
|
||||
G1Projective::from(&p)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstantTimeEq for G1Projective {
|
||||
fn ct_eq(&self, other: &Self) -> Choice {
|
||||
// Is (xz^2, yz^3, z) equal to (x'z'^2, yz'^3, z') when converted to affine?
|
||||
|
@ -180,6 +226,12 @@ impl G1Projective {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if this element is the identity (the point at infinity).
|
||||
#[inline]
|
||||
pub fn is_identity(&self) -> Choice {
|
||||
self.z.is_zero()
|
||||
}
|
||||
|
||||
/// Returns true if this point is on the curve. This should always return
|
||||
/// true unless an "unchecked" API was used.
|
||||
pub fn is_on_curve(&self) -> Choice {
|
||||
|
@ -301,3 +353,42 @@ fn test_conditionally_select_projective() {
|
|||
b
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_projective_to_affine() {
|
||||
let a = G1Projective::generator();
|
||||
let b = G1Projective::identity();
|
||||
|
||||
assert!(bool::from(G1Affine::from(a).is_on_curve()));
|
||||
assert!(!bool::from(G1Affine::from(a).is_identity()));
|
||||
assert!(bool::from(G1Affine::from(b).is_on_curve()));
|
||||
assert!(bool::from(G1Affine::from(b).is_identity()));
|
||||
|
||||
let z = Fp::from_raw_unchecked([
|
||||
0xba7afa1f9a6fe250,
|
||||
0xfa0f5b595eafe731,
|
||||
0x3bdc477694c306e7,
|
||||
0x2149be4b3949fa24,
|
||||
0x64aa6e0649b2078c,
|
||||
0x12b108ac33643c3e,
|
||||
]);
|
||||
|
||||
let c = G1Projective {
|
||||
x: a.x * (z.square()),
|
||||
y: a.y * (z.square() * z),
|
||||
z,
|
||||
};
|
||||
|
||||
assert_eq!(G1Affine::from(c), G1Affine::generator());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_affine_to_projective() {
|
||||
let a = G1Affine::generator();
|
||||
let b = G1Affine::identity();
|
||||
|
||||
assert!(bool::from(G1Projective::from(a).is_on_curve()));
|
||||
assert!(!bool::from(G1Projective::from(a).is_identity()));
|
||||
assert!(bool::from(G1Projective::from(b).is_on_curve()));
|
||||
assert!(bool::from(G1Projective::from(b).is_identity()));
|
||||
}
|
||||
|
|
101
src/g2.rs
101
src/g2.rs
|
@ -17,6 +17,30 @@ pub struct G2Affine {
|
|||
infinity: Choice,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a G2Projective> for G2Affine {
|
||||
fn from(p: &'a G2Projective) -> G2Affine {
|
||||
let zinv = p.z.invert().unwrap_or(Fp2::zero());
|
||||
let zinv2 = zinv.square();
|
||||
let x = p.x * zinv2;
|
||||
let zinv3 = zinv2 * zinv;
|
||||
let y = p.y * zinv3;
|
||||
|
||||
let tmp = G2Affine {
|
||||
x,
|
||||
y,
|
||||
infinity: Choice::from(0u8),
|
||||
};
|
||||
|
||||
G2Affine::conditional_select(&tmp, &G2Affine::identity(), zinv.is_zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<G2Projective> for G2Affine {
|
||||
fn from(p: G2Projective) -> G2Affine {
|
||||
G2Affine::from(&p)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstantTimeEq for G2Affine {
|
||||
fn ct_eq(&self, other: &Self) -> Choice {
|
||||
// The only cases in which two points are equal are
|
||||
|
@ -122,6 +146,12 @@ impl G2Affine {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if this element is the identity (the point at infinity).
|
||||
#[inline]
|
||||
pub fn is_identity(&self) -> Choice {
|
||||
self.infinity
|
||||
}
|
||||
|
||||
/// Returns true if this point is on the curve. This should always return
|
||||
/// true unless an "unchecked" API was used.
|
||||
pub fn is_on_curve(&self) -> Choice {
|
||||
|
@ -138,6 +168,22 @@ pub struct G2Projective {
|
|||
z: Fp2,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a G2Affine> for G2Projective {
|
||||
fn from(p: &'a G2Affine) -> G2Projective {
|
||||
G2Projective {
|
||||
x: p.x,
|
||||
y: p.y,
|
||||
z: Fp2::conditional_select(&Fp2::one(), &Fp2::zero(), p.infinity),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<G2Affine> for G2Projective {
|
||||
fn from(p: G2Affine) -> G2Projective {
|
||||
G2Projective::from(&p)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstantTimeEq for G2Projective {
|
||||
fn ct_eq(&self, other: &Self) -> Choice {
|
||||
// Is (xz^2, yz^3, z) equal to (x'z'^2, yz'^3, z') when converted to affine?
|
||||
|
@ -231,6 +277,12 @@ impl G2Projective {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if this element is the identity (the point at infinity).
|
||||
#[inline]
|
||||
pub fn is_identity(&self) -> Choice {
|
||||
self.z.is_zero()
|
||||
}
|
||||
|
||||
/// Returns true if this point is on the curve. This should always return
|
||||
/// true unless an "unchecked" API was used.
|
||||
pub fn is_on_curve(&self) -> Choice {
|
||||
|
@ -372,3 +424,52 @@ fn test_conditionally_select_projective() {
|
|||
b
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_projective_to_affine() {
|
||||
let a = G2Projective::generator();
|
||||
let b = G2Projective::identity();
|
||||
|
||||
assert!(bool::from(G2Affine::from(a).is_on_curve()));
|
||||
assert!(!bool::from(G2Affine::from(a).is_identity()));
|
||||
assert!(bool::from(G2Affine::from(b).is_on_curve()));
|
||||
assert!(bool::from(G2Affine::from(b).is_identity()));
|
||||
|
||||
let z = Fp2 {
|
||||
c0: Fp::from_raw_unchecked([
|
||||
0xba7afa1f9a6fe250,
|
||||
0xfa0f5b595eafe731,
|
||||
0x3bdc477694c306e7,
|
||||
0x2149be4b3949fa24,
|
||||
0x64aa6e0649b2078c,
|
||||
0x12b108ac33643c3e,
|
||||
]),
|
||||
c1: Fp::from_raw_unchecked([
|
||||
0x125325df3d35b5a8,
|
||||
0xdc469ef5555d7fe3,
|
||||
0x2d716d2443106a9,
|
||||
0x5a1db59a6ff37d0,
|
||||
0x7cf7784e5300bb8f,
|
||||
0x16a88922c7a5e844,
|
||||
]),
|
||||
};
|
||||
|
||||
let c = G2Projective {
|
||||
x: a.x * (z.square()),
|
||||
y: a.y * (z.square() * z),
|
||||
z,
|
||||
};
|
||||
|
||||
assert_eq!(G2Affine::from(c), G2Affine::generator());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_affine_to_projective() {
|
||||
let a = G2Affine::generator();
|
||||
let b = G2Affine::identity();
|
||||
|
||||
assert!(bool::from(G2Projective::from(a).is_on_curve()));
|
||||
assert!(!bool::from(G2Projective::from(a).is_identity()));
|
||||
assert!(bool::from(G2Projective::from(b).is_on_curve()));
|
||||
assert!(bool::from(G2Projective::from(b).is_identity()));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue