group: Remove EncodedPoint::{into_affine, into_affine_unchecked}

Replaced by explicit APIs on the CurveAffine trait.

GroupDecodingError has been moved into pairing::bls12_381::ec, as it is
no longer used by the group traits.
This commit is contained in:
Jack Grigg 2020-05-19 18:10:10 +12:00
parent b0a3713d7e
commit b77f8dddda
6 changed files with 377 additions and 299 deletions

View File

@ -46,14 +46,18 @@ impl<E: Engine> Proof<E> {
}
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
let mut g1_repr = <E::G1Affine as CurveAffine>::Compressed::empty();
let mut g2_repr = <E::G2Affine as CurveAffine>::Compressed::empty();
let read_g1 = |reader: &mut R| -> io::Result<E::G1Affine> {
let mut g1_repr = <E::G1Affine as CurveAffine>::Compressed::empty();
reader.read_exact(g1_repr.as_mut())?;
reader.read_exact(g1_repr.as_mut())?;
let a = g1_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| {
let affine = E::G1Affine::from_compressed(&g1_repr);
let affine = if affine.is_some().into() {
Ok(affine.unwrap())
} else {
Err(io::Error::new(io::ErrorKind::InvalidData, "invalid G1"))
};
affine.and_then(|e| {
if e.is_identity().into() {
Err(io::Error::new(
io::ErrorKind::InvalidData,
@ -62,13 +66,21 @@ impl<E: Engine> Proof<E> {
} else {
Ok(e)
}
})?;
})
};
reader.read_exact(g2_repr.as_mut())?;
let b = g2_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| {
let read_g2 = |reader: &mut R| -> io::Result<E::G2Affine> {
let mut g2_repr = <E::G2Affine as CurveAffine>::Compressed::empty();
reader.read_exact(g2_repr.as_mut())?;
let affine = E::G2Affine::from_compressed(&g2_repr);
let affine = if affine.is_some().into() {
Ok(affine.unwrap())
} else {
Err(io::Error::new(io::ErrorKind::InvalidData, "invalid G2"))
};
affine.and_then(|e| {
if e.is_identity().into() {
Err(io::Error::new(
io::ErrorKind::InvalidData,
@ -77,22 +89,12 @@ impl<E: Engine> Proof<E> {
} else {
Ok(e)
}
})?;
})
};
reader.read_exact(g1_repr.as_mut())?;
let c = g1_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| {
if e.is_identity().into() {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"point at infinity",
))
} else {
Ok(e)
}
})?;
let a = read_g1(&mut reader)?;
let b = read_g2(&mut reader)?;
let c = read_g1(&mut reader)?;
Ok(Proof { a, b, c })
}
@ -155,58 +157,52 @@ impl<E: Engine> VerifyingKey<E> {
}
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
let mut g1_repr = <E::G1Affine as CurveAffine>::Uncompressed::empty();
let mut g2_repr = <E::G2Affine as CurveAffine>::Uncompressed::empty();
let read_g1 = |reader: &mut R| -> io::Result<E::G1Affine> {
let mut g1_repr = <E::G1Affine as CurveAffine>::Uncompressed::empty();
reader.read_exact(g1_repr.as_mut())?;
reader.read_exact(g1_repr.as_mut())?;
let alpha_g1 = g1_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
let affine = E::G1Affine::from_uncompressed(&g1_repr);
if affine.is_some().into() {
Ok(affine.unwrap())
} else {
Err(io::Error::new(io::ErrorKind::InvalidData, "invalid G1"))
}
};
reader.read_exact(g1_repr.as_mut())?;
let beta_g1 = g1_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
let read_g2 = |reader: &mut R| -> io::Result<E::G2Affine> {
let mut g2_repr = <E::G2Affine as CurveAffine>::Uncompressed::empty();
reader.read_exact(g2_repr.as_mut())?;
reader.read_exact(g2_repr.as_mut())?;
let beta_g2 = g2_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
let affine = E::G2Affine::from_uncompressed(&g2_repr);
if affine.is_some().into() {
Ok(affine.unwrap())
} else {
Err(io::Error::new(io::ErrorKind::InvalidData, "invalid G2"))
}
};
reader.read_exact(g2_repr.as_mut())?;
let gamma_g2 = g2_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
reader.read_exact(g1_repr.as_mut())?;
let delta_g1 = g1_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
reader.read_exact(g2_repr.as_mut())?;
let delta_g2 = g2_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
let alpha_g1 = read_g1(&mut reader)?;
let beta_g1 = read_g1(&mut reader)?;
let beta_g2 = read_g2(&mut reader)?;
let gamma_g2 = read_g2(&mut reader)?;
let delta_g1 = read_g1(&mut reader)?;
let delta_g2 = read_g2(&mut reader)?;
let ic_len = reader.read_u32::<BigEndian>()? as usize;
let mut ic = vec![];
for _ in 0..ic_len {
reader.read_exact(g1_repr.as_mut())?;
let g1 = g1_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| {
if e.is_identity().into() {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"point at infinity",
))
} else {
Ok(e)
}
})?;
let g1 = read_g1(&mut reader).and_then(|e| {
if e.is_identity().into() {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"point at infinity",
))
} else {
Ok(e)
}
})?;
ic.push(g1);
}
@ -296,13 +292,19 @@ impl<E: Engine> Parameters<E> {
let mut repr = <E::G1Affine as CurveAffine>::Uncompressed::empty();
reader.read_exact(repr.as_mut())?;
if checked {
repr.into_affine()
let affine = if checked {
E::G1Affine::from_uncompressed(&repr)
} else {
repr.into_affine_unchecked()
}
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| {
E::G1Affine::from_uncompressed_unchecked(&repr)
};
let affine = if affine.is_some().into() {
Ok(affine.unwrap())
} else {
Err(io::Error::new(io::ErrorKind::InvalidData, "invalid G1"))
};
affine.and_then(|e| {
if e.is_identity().into() {
Err(io::Error::new(
io::ErrorKind::InvalidData,
@ -318,13 +320,19 @@ impl<E: Engine> Parameters<E> {
let mut repr = <E::G2Affine as CurveAffine>::Uncompressed::empty();
reader.read_exact(repr.as_mut())?;
if checked {
repr.into_affine()
let affine = if checked {
E::G2Affine::from_uncompressed(&repr)
} else {
repr.into_affine_unchecked()
}
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| {
E::G2Affine::from_uncompressed_unchecked(&repr)
};
let affine = if affine.is_some().into() {
Ok(affine.unwrap())
} else {
Err(io::Error::new(io::ErrorKind::InvalidData, "invalid G2"))
};
affine.and_then(|e| {
if e.is_identity().into() {
Err(io::Error::new(
io::ErrorKind::InvalidData,

View File

@ -1,5 +1,5 @@
use ff::{Field, PrimeField, ScalarEngine};
use group::{CurveAffine, CurveProjective, EncodedPoint, Group, GroupDecodingError, PrimeGroup};
use group::{CurveAffine, CurveProjective, EncodedPoint, Group, PrimeGroup};
use pairing::{Engine, PairingCurveAffine};
use rand_core::RngCore;
@ -443,14 +443,6 @@ impl EncodedPoint for FakePoint {
unimplemented!()
}
fn into_affine(&self) -> Result<Self::Affine, GroupDecodingError> {
unimplemented!()
}
fn into_affine_unchecked(&self) -> Result<Self::Affine, GroupDecodingError> {
unimplemented!()
}
fn from_affine(_: Self::Affine) -> Self {
unimplemented!()
}
@ -478,6 +470,22 @@ impl CurveAffine for Fr {
fn into_projective(&self) -> Self::Projective {
*self
}
fn from_compressed(_bytes: &Self::Compressed) -> CtOption<Self> {
unimplemented!()
}
fn from_compressed_unchecked(_bytes: &Self::Compressed) -> CtOption<Self> {
unimplemented!()
}
fn from_uncompressed(_bytes: &Self::Uncompressed) -> CtOption<Self> {
unimplemented!()
}
fn from_uncompressed_unchecked(_bytes: &Self::Uncompressed) -> CtOption<Self> {
unimplemented!()
}
}
impl PairingCurveAffine for Fr {

View File

@ -3,11 +3,10 @@
use ff::{Field, PrimeField};
use rand::RngCore;
use std::error::Error;
use std::fmt;
use std::iter::Sum;
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use subtle::Choice;
use subtle::{Choice, CtOption};
pub mod tests;
@ -155,12 +154,34 @@ pub trait CurveAffine:
/// Converts this element into its affine representation.
fn into_projective(&self) -> Self::Projective;
/// Attempts to deserialize an element from its compressed encoding.
fn from_compressed(bytes: &Self::Compressed) -> CtOption<Self>;
/// Attempts to deserialize a compressed element, not checking if the element is in
/// the correct subgroup.
///
/// **This is dangerous to call unless you trust the bytes you are reading; otherwise,
/// API invariants may be broken.** Please consider using
/// [`CurveAffine::from_compressed`] instead.
fn from_compressed_unchecked(bytes: &Self::Compressed) -> CtOption<Self>;
/// Converts this element into its compressed encoding, so long as it's not
/// the point at infinity.
fn into_compressed(&self) -> Self::Compressed {
<Self::Compressed as EncodedPoint>::from_affine(*self)
}
/// Attempts to deserialize an element from its uncompressed encoding.
fn from_uncompressed(bytes: &Self::Uncompressed) -> CtOption<Self>;
/// Attempts to deserialize an uncompressed element, not checking if the element is in
/// the correct subgroup.
///
/// **This is dangerous to call unless you trust the bytes you are reading; otherwise,
/// API invariants may be broken.** Please consider using
/// [`CurveAffine::from_uncompressed`] instead.
fn from_uncompressed_unchecked(bytes: &Self::Uncompressed) -> CtOption<Self>;
/// Converts this element into its uncompressed encoding, so long as it's not
/// the point at infinity.
fn into_uncompressed(&self) -> Self::Uncompressed {
@ -180,60 +201,7 @@ pub trait EncodedPoint:
/// Returns the number of bytes consumed by this representation.
fn size() -> usize;
/// Converts an `EncodedPoint` into a `CurveAffine` element,
/// if the encoding represents a valid element.
fn into_affine(&self) -> Result<Self::Affine, GroupDecodingError>;
/// Converts an `EncodedPoint` into a `CurveAffine` element,
/// without guaranteeing that the encoding represents a valid
/// element. This is useful when the caller knows the encoding is
/// valid already.
///
/// If the encoding is invalid, this can break API invariants,
/// so caution is strongly encouraged.
fn into_affine_unchecked(&self) -> Result<Self::Affine, GroupDecodingError>;
/// Creates an `EncodedPoint` from an affine point, as long as the
/// point is not the point at infinity.
fn from_affine(affine: Self::Affine) -> Self;
}
/// An error that may occur when trying to decode an `EncodedPoint`.
#[derive(Debug)]
pub enum GroupDecodingError {
/// The coordinate(s) do not lie on the curve.
NotOnCurve,
/// The element is not part of the r-order subgroup.
NotInSubgroup,
/// One of the coordinates could not be decoded
CoordinateDecodingError(&'static str),
/// The compression mode of the encoded element was not as expected
UnexpectedCompressionMode,
/// The encoding contained bits that should not have been set
UnexpectedInformation,
}
impl Error for GroupDecodingError {
fn description(&self) -> &str {
match *self {
GroupDecodingError::NotOnCurve => "coordinate(s) do not lie on the curve",
GroupDecodingError::NotInSubgroup => "the element is not part of an r-order subgroup",
GroupDecodingError::CoordinateDecodingError(..) => "coordinate(s) could not be decoded",
GroupDecodingError::UnexpectedCompressionMode => {
"encoding has unexpected compression mode"
}
GroupDecodingError::UnexpectedInformation => "encoding has unexpected information",
}
}
}
impl fmt::Display for GroupDecodingError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match *self {
GroupDecodingError::CoordinateDecodingError(description) => {
write!(f, "{} decoding error", description)
}
_ => write!(f, "{}", self.description()),
}
}
}

View File

@ -3,7 +3,7 @@ use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{Mul, Neg};
use crate::{CurveAffine, CurveProjective, EncodedPoint};
use crate::{CurveAffine, CurveProjective};
pub fn curve_tests<G: CurveProjective>() {
let mut rng = XorShiftRng::from_seed([
@ -405,18 +405,12 @@ fn random_encoding_tests<G: CurveProjective>() {
]);
assert_eq!(
G::Affine::identity()
.into_uncompressed()
.into_affine()
.unwrap(),
G::Affine::from_uncompressed(&G::Affine::identity().into_uncompressed()).unwrap(),
G::Affine::identity()
);
assert_eq!(
G::Affine::identity()
.into_compressed()
.into_affine()
.unwrap(),
G::Affine::from_compressed(&G::Affine::identity().into_compressed()).unwrap(),
G::Affine::identity()
);
@ -424,17 +418,17 @@ fn random_encoding_tests<G: CurveProjective>() {
let mut r = G::random(&mut rng).into_affine();
let uncompressed = r.into_uncompressed();
let de_uncompressed = uncompressed.into_affine().unwrap();
let de_uncompressed = G::Affine::from_uncompressed(&uncompressed).unwrap();
assert_eq!(de_uncompressed, r);
let compressed = r.into_compressed();
let de_compressed = compressed.into_affine().unwrap();
let de_compressed = G::Affine::from_compressed(&compressed).unwrap();
assert_eq!(de_compressed, r);
r = r.neg();
let compressed = r.into_compressed();
let de_compressed = compressed.into_affine().unwrap();
let de_compressed = G::Affine::from_compressed(&compressed).unwrap();
assert_eq!(de_compressed, r);
}
}

View File

@ -17,6 +17,12 @@ macro_rules! curve_impl {
pub(crate) infinity: bool,
}
impl Default for $affine {
fn default() -> Self {
Self::identity()
}
}
impl ::std::fmt::Display for $affine {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
if self.infinity {
@ -27,6 +33,21 @@ macro_rules! curve_impl {
}
}
impl ::subtle::ConditionallySelectable for $affine {
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
$affine {
x: $basefield::conditional_select(&a.x, &b.x, choice),
y: $basefield::conditional_select(&a.y, &b.y, choice),
// Obviously not constant-time, but this code will be replaced.
infinity: if choice.into() {
b.infinity
} else {
a.infinity
},
}
}
}
#[derive(Copy, Clone, Debug, Eq)]
pub struct $projective {
pub(crate) x: $basefield,
@ -203,6 +224,53 @@ macro_rules! curve_impl {
fn into_projective(&self) -> $projective {
(*self).into()
}
fn from_compressed(bytes: &Self::Compressed) -> CtOption<Self> {
Self::from_compressed_unchecked(bytes).and_then(|affine| {
// NB: Decompression guarantees that it is on the curve already.
CtOption::new(
affine,
Choice::from(if affine.is_in_correct_subgroup_assuming_on_curve() {
1
} else {
0
}),
)
})
}
fn from_compressed_unchecked(bytes: &Self::Compressed) -> CtOption<Self> {
if let Ok(p) = bytes.into_affine_unchecked() {
CtOption::new(p, Choice::from(1))
} else {
CtOption::new(Self::identity(), Choice::from(0))
}
}
fn from_uncompressed(bytes: &Self::Uncompressed) -> CtOption<Self> {
Self::from_uncompressed_unchecked(bytes).and_then(|affine| {
CtOption::new(
affine,
Choice::from(
if affine.is_on_curve()
&& affine.is_in_correct_subgroup_assuming_on_curve()
{
1
} else {
0
},
),
)
})
}
fn from_uncompressed_unchecked(bytes: &Self::Uncompressed) -> CtOption<Self> {
if let Ok(p) = bytes.into_affine_unchecked() {
CtOption::new(p, Choice::from(1))
} else {
CtOption::new(Self::identity(), Choice::from(0))
}
}
}
impl PairingCurveAffine for $affine {
@ -788,14 +856,52 @@ macro_rules! curve_impl {
};
}
use std::error::Error;
use std::fmt;
/// An error that may occur when trying to decode an `EncodedPoint`.
#[derive(Debug)]
enum GroupDecodingError {
/// The coordinate(s) do not lie on the curve.
NotOnCurve,
/// One of the coordinates could not be decoded
CoordinateDecodingError(&'static str),
/// The compression mode of the encoded element was not as expected
UnexpectedCompressionMode,
/// The encoding contained bits that should not have been set
UnexpectedInformation,
}
impl Error for GroupDecodingError {
fn description(&self) -> &str {
match *self {
GroupDecodingError::NotOnCurve => "coordinate(s) do not lie on the curve",
GroupDecodingError::CoordinateDecodingError(..) => "coordinate(s) could not be decoded",
GroupDecodingError::UnexpectedCompressionMode => {
"encoding has unexpected compression mode"
}
GroupDecodingError::UnexpectedInformation => "encoding has unexpected information",
}
}
}
impl fmt::Display for GroupDecodingError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match *self {
GroupDecodingError::CoordinateDecodingError(description) => {
write!(f, "{} decoding error", description)
}
_ => write!(f, "{}", self.description()),
}
}
}
pub mod g1 {
use super::super::{Fq, Fq12, FqRepr, Fr};
use super::g2::G2Affine;
use super::{g2::G2Affine, GroupDecodingError};
use crate::{Engine, PairingCurveAffine};
use ff::{BitIterator, Field, PrimeField};
use group::{
CurveAffine, CurveProjective, EncodedPoint, Group, GroupDecodingError, PrimeGroup,
};
use group::{CurveAffine, CurveProjective, EncodedPoint, Group, PrimeGroup};
use rand_core::RngCore;
use std::fmt;
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
@ -834,26 +940,7 @@ pub mod g1 {
}
}
impl EncodedPoint for G1Uncompressed {
type Affine = G1Affine;
fn empty() -> Self {
G1Uncompressed([0; 96])
}
fn size() -> usize {
96
}
fn into_affine(&self) -> Result<G1Affine, GroupDecodingError> {
let affine = self.into_affine_unchecked()?;
if !affine.is_on_curve() {
Err(GroupDecodingError::NotOnCurve)
} else if !affine.is_in_correct_subgroup_assuming_on_curve() {
Err(GroupDecodingError::NotInSubgroup)
} else {
Ok(affine)
}
}
impl G1Uncompressed {
fn into_affine_unchecked(&self) -> Result<G1Affine, GroupDecodingError> {
// Create a copy of this representation.
let mut copy = self.0;
@ -904,6 +991,17 @@ pub mod g1 {
})
}
}
}
impl EncodedPoint for G1Uncompressed {
type Affine = G1Affine;
fn empty() -> Self {
G1Uncompressed([0; 96])
}
fn size() -> usize {
96
}
fn from_affine(affine: G1Affine) -> Self {
let mut res = Self::empty();
@ -941,26 +1039,7 @@ pub mod g1 {
}
}
impl EncodedPoint for G1Compressed {
type Affine = G1Affine;
fn empty() -> Self {
G1Compressed([0; 48])
}
fn size() -> usize {
48
}
fn into_affine(&self) -> Result<G1Affine, GroupDecodingError> {
let affine = self.into_affine_unchecked()?;
// NB: Decompression guarantees that it is on the curve already.
if !affine.is_in_correct_subgroup_assuming_on_curve() {
Err(GroupDecodingError::NotInSubgroup)
} else {
Ok(affine)
}
}
impl G1Compressed {
fn into_affine_unchecked(&self) -> Result<G1Affine, GroupDecodingError> {
// Create a copy of this representation.
let mut copy = self.0;
@ -1001,6 +1080,17 @@ pub mod g1 {
}
}
}
}
impl EncodedPoint for G1Compressed {
type Affine = G1Affine;
fn empty() -> Self {
G1Compressed([0; 48])
}
fn size() -> usize {
48
}
fn from_affine(affine: G1Affine) -> Self {
let mut res = Self::empty();
@ -1400,12 +1490,10 @@ pub mod g1 {
pub mod g2 {
use super::super::{Fq, Fq12, Fq2, FqRepr, Fr};
use super::g1::G1Affine;
use super::{g1::G1Affine, GroupDecodingError};
use crate::{Engine, PairingCurveAffine};
use ff::{BitIterator, Field, PrimeField};
use group::{
CurveAffine, CurveProjective, EncodedPoint, Group, GroupDecodingError, PrimeGroup,
};
use group::{CurveAffine, CurveProjective, EncodedPoint, Group, PrimeGroup};
use rand_core::RngCore;
use std::fmt;
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
@ -1444,26 +1532,7 @@ pub mod g2 {
}
}
impl EncodedPoint for G2Uncompressed {
type Affine = G2Affine;
fn empty() -> Self {
G2Uncompressed([0; 192])
}
fn size() -> usize {
192
}
fn into_affine(&self) -> Result<G2Affine, GroupDecodingError> {
let affine = self.into_affine_unchecked()?;
if !affine.is_on_curve() {
Err(GroupDecodingError::NotOnCurve)
} else if !affine.is_in_correct_subgroup_assuming_on_curve() {
Err(GroupDecodingError::NotInSubgroup)
} else {
Ok(affine)
}
}
impl G2Uncompressed {
fn into_affine_unchecked(&self) -> Result<G2Affine, GroupDecodingError> {
// Create a copy of this representation.
let mut copy = self.0;
@ -1526,6 +1595,17 @@ pub mod g2 {
})
}
}
}
impl EncodedPoint for G2Uncompressed {
type Affine = G2Affine;
fn empty() -> Self {
G2Uncompressed([0; 192])
}
fn size() -> usize {
192
}
fn from_affine(affine: G2Affine) -> Self {
let mut res = Self::empty();
@ -1565,26 +1645,7 @@ pub mod g2 {
}
}
impl EncodedPoint for G2Compressed {
type Affine = G2Affine;
fn empty() -> Self {
G2Compressed([0; 96])
}
fn size() -> usize {
96
}
fn into_affine(&self) -> Result<G2Affine, GroupDecodingError> {
let affine = self.into_affine_unchecked()?;
// NB: Decompression guarantees that it is on the curve already.
if !affine.is_in_correct_subgroup_assuming_on_curve() {
Err(GroupDecodingError::NotInSubgroup)
} else {
Ok(affine)
}
}
impl G2Compressed {
fn into_affine_unchecked(&self) -> Result<G2Affine, GroupDecodingError> {
// Create a copy of this representation.
let mut copy = self.0;
@ -1640,6 +1701,17 @@ pub mod g2 {
}
}
}
}
impl EncodedPoint for G2Compressed {
type Affine = G2Affine;
fn empty() -> Self {
G2Compressed([0; 96])
}
fn size() -> usize {
96
}
fn from_affine(affine: G2Affine) -> Self {
let mut res = Self::empty();

View File

@ -1,5 +1,5 @@
use ff::PrimeField;
use group::{CurveAffine, CurveProjective, EncodedPoint, Group, GroupDecodingError};
use group::{CurveAffine, CurveProjective, EncodedPoint, Group};
use super::*;
use crate::*;
@ -55,7 +55,7 @@ fn test_pairing_result_against_relic() {
});
}
fn test_vectors<G: CurveProjective, E: EncodedPoint<Affine = G::Affine>>(expected: &[u8]) {
fn uncompressed_test_vectors<G: CurveProjective>(expected: &[u8]) {
let mut e = G::identity();
let mut v = vec![];
@ -63,13 +63,41 @@ fn test_vectors<G: CurveProjective, E: EncodedPoint<Affine = G::Affine>>(expecte
let mut expected = expected;
for _ in 0..1000 {
let e_affine = e.into_affine();
let encoded = E::from_affine(e_affine);
let encoded = <G::Affine as CurveAffine>::Uncompressed::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();
let mut decoded = <G::Affine as CurveAffine>::Uncompressed::empty();
decoded
.as_mut()
.copy_from_slice(&expected[0..<G::Affine as CurveAffine>::Uncompressed::size()]);
expected = &expected[<G::Affine as CurveAffine>::Uncompressed::size()..];
let decoded = G::Affine::from_uncompressed(&decoded).unwrap();
assert_eq!(e_affine, decoded);
e.add_assign(&G::generator());
}
}
assert_eq!(&v[..], expected);
}
fn compressed_test_vectors<G: CurveProjective>(expected: &[u8]) {
let mut e = G::identity();
let mut v = vec![];
{
let mut expected = expected;
for _ in 0..1000 {
let e_affine = e.into_affine();
let encoded = <G::Affine as CurveAffine>::Compressed::from_affine(e_affine);
v.extend_from_slice(encoded.as_ref());
let mut decoded = <G::Affine as CurveAffine>::Compressed::empty();
decoded
.as_mut()
.copy_from_slice(&expected[0..<G::Affine as CurveAffine>::Compressed::size()]);
expected = &expected[<G::Affine as CurveAffine>::Compressed::size()..];
let decoded = G::Affine::from_compressed(&decoded).unwrap();
assert_eq!(e_affine, decoded);
e.add_assign(&G::generator());
@ -81,22 +109,22 @@ fn test_vectors<G: CurveProjective, E: EncodedPoint<Affine = G::Affine>>(expecte
#[test]
fn test_g1_uncompressed_valid_vectors() {
test_vectors::<G1, G1Uncompressed>(include_bytes!("g1_uncompressed_valid_test_vectors.dat"));
uncompressed_test_vectors::<G1>(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"));
compressed_test_vectors::<G1>(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"));
uncompressed_test_vectors::<G2>(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"));
compressed_test_vectors::<G2>(include_bytes!("g2_compressed_valid_test_vectors.dat"));
}
#[test]
@ -107,7 +135,7 @@ fn test_g1_uncompressed_invalid_vectors() {
{
let mut z = z;
z.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = z.into_affine() {
if G1Affine::from_uncompressed(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because we expected an uncompressed point");
@ -117,7 +145,7 @@ fn test_g1_uncompressed_invalid_vectors() {
{
let mut z = z;
z.as_mut()[0] |= 0b0010_0000;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
if G1Affine::from_uncompressed(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because the parity bit should not be set if the point is at infinity");
@ -127,7 +155,7 @@ fn test_g1_uncompressed_invalid_vectors() {
for i in 0..G1Uncompressed::size() {
let mut z = z;
z.as_mut()[i] |= 0b0000_0001;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
if G1Affine::from_uncompressed(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
@ -140,7 +168,7 @@ fn test_g1_uncompressed_invalid_vectors() {
{
let mut o = o;
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = o.into_affine() {
if G1Affine::from_uncompressed(&o).is_none().into() {
// :)
} else {
panic!("should have rejected the point because we expected an uncompressed point");
@ -153,8 +181,8 @@ fn test_g1_uncompressed_invalid_vectors() {
let mut o = o;
o.as_mut()[..48].copy_from_slice(m.as_ref());
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate");
if G1Affine::from_uncompressed(&o).is_none().into() {
// x coordinate
} else {
panic!("should have rejected the point")
}
@ -164,8 +192,8 @@ fn test_g1_uncompressed_invalid_vectors() {
let mut o = o;
o.as_mut()[48..].copy_from_slice(m.as_ref());
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "y coordinate");
if G1Affine::from_uncompressed(&o).is_none().into() {
// y coordinate
} else {
panic!("should have rejected the point")
}
@ -177,7 +205,7 @@ fn test_g1_uncompressed_invalid_vectors() {
let mut o = o;
o.as_mut()[..48].copy_from_slice(m.as_ref());
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
if G1Affine::from_uncompressed(&o).is_none().into() {
// :)
} else {
panic!("should have rejected the point because it isn't on the curve")
@ -201,7 +229,7 @@ fn test_g1_uncompressed_invalid_vectors() {
o.as_mut()[..48].copy_from_slice(x.to_repr().as_ref());
o.as_mut()[48..].copy_from_slice(y.to_repr().as_ref());
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
if G1Affine::from_uncompressed(&o).is_none().into() {
break;
} else {
panic!(
@ -223,7 +251,7 @@ fn test_g2_uncompressed_invalid_vectors() {
{
let mut z = z;
z.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = z.into_affine() {
if G2Affine::from_uncompressed(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because we expected an uncompressed point");
@ -233,7 +261,7 @@ fn test_g2_uncompressed_invalid_vectors() {
{
let mut z = z;
z.as_mut()[0] |= 0b0010_0000;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
if G2Affine::from_uncompressed(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because the parity bit should not be set if the point is at infinity");
@ -243,7 +271,7 @@ fn test_g2_uncompressed_invalid_vectors() {
for i in 0..G2Uncompressed::size() {
let mut z = z;
z.as_mut()[i] |= 0b0000_0001;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
if G2Affine::from_uncompressed(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
@ -256,7 +284,7 @@ fn test_g2_uncompressed_invalid_vectors() {
{
let mut o = o;
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = o.into_affine() {
if G2Affine::from_uncompressed(&o).is_none().into() {
// :)
} else {
panic!("should have rejected the point because we expected an uncompressed point");
@ -269,8 +297,8 @@ fn test_g2_uncompressed_invalid_vectors() {
let mut o = o;
o.as_mut()[..48].copy_from_slice(m.as_ref());
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate (c1)");
if G2Affine::from_uncompressed(&o).is_none().into() {
// x coordinate (c1)
} else {
panic!("should have rejected the point")
}
@ -280,8 +308,8 @@ fn test_g2_uncompressed_invalid_vectors() {
let mut o = o;
o.as_mut()[48..96].copy_from_slice(m.as_ref());
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate (c0)");
if G2Affine::from_uncompressed(&o).is_none().into() {
// x coordinate (c0)
} else {
panic!("should have rejected the point")
}
@ -291,8 +319,8 @@ fn test_g2_uncompressed_invalid_vectors() {
let mut o = o;
o.as_mut()[96..144].copy_from_slice(m.as_ref());
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "y coordinate (c1)");
if G2Affine::from_uncompressed(&o).is_none().into() {
// y coordinate (c1)
} else {
panic!("should have rejected the point")
}
@ -302,8 +330,8 @@ fn test_g2_uncompressed_invalid_vectors() {
let mut o = o;
o.as_mut()[144..].copy_from_slice(m.as_ref());
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "y coordinate (c0)");
if G2Affine::from_uncompressed(&o).is_none().into() {
// y coordinate (c0)
} else {
panic!("should have rejected the point")
}
@ -316,7 +344,7 @@ fn test_g2_uncompressed_invalid_vectors() {
o.as_mut()[..48].copy_from_slice(m.as_ref());
o.as_mut()[48..96].copy_from_slice(m.as_ref());
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
if G2Affine::from_uncompressed(&o).is_none().into() {
// :)
} else {
panic!("should have rejected the point because it isn't on the curve")
@ -345,7 +373,7 @@ fn test_g2_uncompressed_invalid_vectors() {
o.as_mut()[96..144].copy_from_slice(y.c1.to_repr().as_ref());
o.as_mut()[144..].copy_from_slice(y.c0.to_repr().as_ref());
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
if G2Affine::from_uncompressed(&o).is_none().into() {
break;
} else {
panic!(
@ -367,7 +395,7 @@ fn test_g1_compressed_invalid_vectors() {
{
let mut z = z;
z.as_mut()[0] &= 0b0111_1111;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = z.into_affine() {
if G1Affine::from_compressed(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because we expected a compressed point");
@ -377,7 +405,7 @@ fn test_g1_compressed_invalid_vectors() {
{
let mut z = z;
z.as_mut()[0] |= 0b0010_0000;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
if G1Affine::from_compressed(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because the parity bit should not be set if the point is at infinity");
@ -387,7 +415,7 @@ fn test_g1_compressed_invalid_vectors() {
for i in 0..G1Compressed::size() {
let mut z = z;
z.as_mut()[i] |= 0b0000_0001;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
if G1Affine::from_compressed(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
@ -400,7 +428,7 @@ fn test_g1_compressed_invalid_vectors() {
{
let mut o = o;
o.as_mut()[0] &= 0b0111_1111;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = o.into_affine() {
if G1Affine::from_compressed(&o).is_none().into() {
// :)
} else {
panic!("should have rejected the point because we expected a compressed point");
@ -414,8 +442,8 @@ fn test_g1_compressed_invalid_vectors() {
o.as_mut()[..48].copy_from_slice(m.as_ref());
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate");
if G1Affine::from_compressed(&o).is_none().into() {
// x coordinate
} else {
panic!("should have rejected the point")
}
@ -436,7 +464,7 @@ fn test_g1_compressed_invalid_vectors() {
o.as_mut().copy_from_slice(x.to_repr().as_ref());
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
if G1Affine::from_compressed(&o).is_none().into() {
break;
} else {
panic!("should have rejected the point because it isn't on the curve")
@ -459,7 +487,7 @@ fn test_g1_compressed_invalid_vectors() {
o.as_mut().copy_from_slice(x.to_repr().as_ref());
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
if G1Affine::from_compressed(&o).is_none().into() {
break;
} else {
panic!(
@ -481,7 +509,7 @@ fn test_g2_compressed_invalid_vectors() {
{
let mut z = z;
z.as_mut()[0] &= 0b0111_1111;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = z.into_affine() {
if G2Affine::from_compressed(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because we expected a compressed point");
@ -491,7 +519,7 @@ fn test_g2_compressed_invalid_vectors() {
{
let mut z = z;
z.as_mut()[0] |= 0b0010_0000;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
if G2Affine::from_compressed(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because the parity bit should not be set if the point is at infinity");
@ -501,7 +529,7 @@ fn test_g2_compressed_invalid_vectors() {
for i in 0..G2Compressed::size() {
let mut z = z;
z.as_mut()[i] |= 0b0000_0001;
if let Err(GroupDecodingError::UnexpectedInformation) = z.into_affine() {
if G2Affine::from_compressed(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
@ -514,7 +542,7 @@ fn test_g2_compressed_invalid_vectors() {
{
let mut o = o;
o.as_mut()[0] &= 0b0111_1111;
if let Err(GroupDecodingError::UnexpectedCompressionMode) = o.into_affine() {
if G2Affine::from_compressed(&o).is_none().into() {
// :)
} else {
panic!("should have rejected the point because we expected a compressed point");
@ -528,8 +556,8 @@ fn test_g2_compressed_invalid_vectors() {
o.as_mut()[..48].copy_from_slice(m.as_ref());
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate (c1)");
if G2Affine::from_compressed(&o).is_none().into() {
// x coordinate (c1)
} else {
panic!("should have rejected the point")
}
@ -540,8 +568,8 @@ fn test_g2_compressed_invalid_vectors() {
o.as_mut()[48..96].copy_from_slice(m.as_ref());
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate (c0)");
if G2Affine::from_compressed(&o).is_none().into() {
// x coordinate (c0)
} else {
panic!("should have rejected the point")
}
@ -569,7 +597,7 @@ fn test_g2_compressed_invalid_vectors() {
o.as_mut()[48..].copy_from_slice(x.c0.to_repr().as_ref());
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
if G2Affine::from_compressed(&o).is_none().into() {
break;
} else {
panic!("should have rejected the point because it isn't on the curve")
@ -599,7 +627,7 @@ fn test_g2_compressed_invalid_vectors() {
o.as_mut()[48..].copy_from_slice(x.c0.to_repr().as_ref());
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
if G2Affine::from_compressed(&o).is_none().into() {
break;
} else {
panic!(