group: Remove "compressed" notion from GroupEncoding

A generic group has a single encoding; for elliptic curves, this
happens to be the compressed encoding.
This commit is contained in:
Jack Grigg 2020-05-29 20:58:54 +12:00
parent 71586914d4
commit df13cd7480
6 changed files with 54 additions and 56 deletions

View File

@ -38,19 +38,19 @@ impl<E: Engine> PartialEq for Proof<E> {
impl<E: Engine> Proof<E> {
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
writer.write_all(self.a.to_compressed().as_ref())?;
writer.write_all(self.b.to_compressed().as_ref())?;
writer.write_all(self.c.to_compressed().as_ref())?;
writer.write_all(self.a.to_bytes().as_ref())?;
writer.write_all(self.b.to_bytes().as_ref())?;
writer.write_all(self.c.to_bytes().as_ref())?;
Ok(())
}
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
let read_g1 = |reader: &mut R| -> io::Result<E::G1Affine> {
let mut g1_repr = <E::G1Affine as GroupEncoding>::Compressed::default();
let mut g1_repr = <E::G1Affine as GroupEncoding>::Repr::default();
reader.read_exact(g1_repr.as_mut())?;
let affine = E::G1Affine::from_compressed(&g1_repr);
let affine = E::G1Affine::from_bytes(&g1_repr);
let affine = if affine.is_some().into() {
Ok(affine.unwrap())
} else {
@ -70,10 +70,10 @@ impl<E: Engine> Proof<E> {
};
let read_g2 = |reader: &mut R| -> io::Result<E::G2Affine> {
let mut g2_repr = <E::G2Affine as GroupEncoding>::Compressed::default();
let mut g2_repr = <E::G2Affine as GroupEncoding>::Repr::default();
reader.read_exact(g2_repr.as_mut())?;
let affine = E::G2Affine::from_compressed(&g2_repr);
let affine = E::G2Affine::from_bytes(&g2_repr);
let affine = if affine.is_some().into() {
Ok(affine.unwrap())
} else {

View File

@ -446,17 +446,17 @@ impl CurveAffine for Fr {
}
impl GroupEncoding for Fr {
type Compressed = FakePoint;
type Repr = FakePoint;
fn from_compressed(_bytes: &Self::Compressed) -> CtOption<Self> {
fn from_bytes(_bytes: &Self::Repr) -> CtOption<Self> {
unimplemented!()
}
fn from_compressed_unchecked(_bytes: &Self::Compressed) -> CtOption<Self> {
fn from_bytes_unchecked(_bytes: &Self::Repr) -> CtOption<Self> {
unimplemented!()
}
fn to_compressed(&self) -> Self::Compressed {
fn to_bytes(&self) -> Self::Repr {
unimplemented!()
}
}

View File

@ -156,22 +156,22 @@ pub trait CurveAffine:
pub trait GroupEncoding: Sized {
/// The encoding of group elements.
type Compressed: Default + AsRef<[u8]> + AsMut<[u8]>;
type Repr: Default + AsRef<[u8]> + AsMut<[u8]>;
/// Attempts to deserialize an element from its compressed encoding.
fn from_compressed(bytes: &Self::Compressed) -> CtOption<Self>;
/// Attempts to deserialize a group element from its encoding.
fn from_bytes(bytes: &Self::Repr) -> CtOption<Self>;
/// Attempts to deserialize a compressed element, not checking if the element is in
/// the correct subgroup.
/// Attempts to deserialize a group element, not checking if the element is valid.
///
/// **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>;
/// [`GroupEncoding::from_bytes`] instead.
fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self>;
/// Converts this element into its compressed encoding, so long as it's not
/// the point at infinity.
fn to_compressed(&self) -> Self::Compressed;
/// Converts this element into its byte encoding. This may or may not support
/// encoding the identity.
// TODO: Figure out how to handle identity encoding generically.
fn to_bytes(&self) -> Self::Repr;
}
/// Affine representation of a point on an elliptic curve that has a defined uncompressed

View File

@ -401,21 +401,21 @@ fn random_compressed_encoding_tests<G: CurveProjective>() {
]);
assert_eq!(
G::Affine::from_compressed(&G::Affine::identity().to_compressed()).unwrap(),
G::Affine::from_bytes(&G::Affine::identity().to_bytes()).unwrap(),
G::Affine::identity()
);
for _ in 0..1000 {
let mut r = G::random(&mut rng).to_affine();
let compressed = r.to_compressed();
let de_compressed = G::Affine::from_compressed(&compressed).unwrap();
let compressed = r.to_bytes();
let de_compressed = G::Affine::from_bytes(&compressed).unwrap();
assert_eq!(de_compressed, r);
r = r.neg();
let compressed = r.to_compressed();
let de_compressed = G::Affine::from_compressed(&compressed).unwrap();
let compressed = r.to_bytes();
let de_compressed = G::Affine::from_bytes(&compressed).unwrap();
assert_eq!(de_compressed, r);
}
}

View File

@ -223,10 +223,10 @@ macro_rules! curve_impl {
}
impl GroupEncoding for $affine {
type Compressed = $compressed;
type Repr = $compressed;
fn from_compressed(bytes: &Self::Compressed) -> CtOption<Self> {
Self::from_compressed_unchecked(bytes).and_then(|affine| {
fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
Self::from_bytes_unchecked(bytes).and_then(|affine| {
// NB: Decompression guarantees that it is on the curve already.
CtOption::new(
affine,
@ -239,7 +239,7 @@ macro_rules! curve_impl {
})
}
fn from_compressed_unchecked(bytes: &Self::Compressed) -> CtOption<Self> {
fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
if let Ok(p) = bytes.into_affine_unchecked() {
CtOption::new(p, Choice::from(1))
} else {
@ -247,7 +247,7 @@ macro_rules! curve_impl {
}
}
fn to_compressed(&self) -> Self::Compressed {
fn to_bytes(&self) -> Self::Repr {
$compressed::from_affine(*self)
}
}

View File

@ -87,22 +87,20 @@ where
fn compressed_test_vectors<G: CurveProjective>(expected: &[u8]) {
let mut e = G::identity();
let encoded_len = <G::Affine as GroupEncoding>::Compressed::default()
.as_ref()
.len();
let encoded_len = <G::Affine as GroupEncoding>::Repr::default().as_ref().len();
let mut v = vec![];
{
let mut expected = expected;
for _ in 0..1000 {
let e_affine = e.to_affine();
let encoded = e_affine.to_compressed();
let encoded = e_affine.to_bytes();
v.extend_from_slice(encoded.as_ref());
let mut decoded = <G::Affine as GroupEncoding>::Compressed::default();
let mut decoded = <G::Affine as GroupEncoding>::Repr::default();
decoded.as_mut().copy_from_slice(&expected[0..encoded_len]);
expected = &expected[encoded_len..];
let decoded = G::Affine::from_compressed(&decoded).unwrap();
let decoded = G::Affine::from_bytes(&decoded).unwrap();
assert_eq!(e_affine, decoded);
e.add_assign(&G::generator());
@ -395,12 +393,12 @@ fn test_g2_uncompressed_invalid_vectors() {
#[test]
fn test_g1_compressed_invalid_vectors() {
{
let z = G1Affine::identity().to_compressed();
let z = G1Affine::identity().to_bytes();
{
let mut z = z;
z.as_mut()[0] &= 0b0111_1111;
if G1Affine::from_compressed(&z).is_none().into() {
if G1Affine::from_bytes(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because we expected a compressed point");
@ -410,7 +408,7 @@ fn test_g1_compressed_invalid_vectors() {
{
let mut z = z;
z.as_mut()[0] |= 0b0010_0000;
if G1Affine::from_compressed(&z).is_none().into() {
if G1Affine::from_bytes(&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");
@ -420,7 +418,7 @@ fn test_g1_compressed_invalid_vectors() {
for i in 0..G1Compressed::size() {
let mut z = z;
z.as_mut()[i] |= 0b0000_0001;
if G1Affine::from_compressed(&z).is_none().into() {
if G1Affine::from_bytes(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
@ -428,12 +426,12 @@ fn test_g1_compressed_invalid_vectors() {
}
}
let o = G1Affine::generator().to_compressed();
let o = G1Affine::generator().to_bytes();
{
let mut o = o;
o.as_mut()[0] &= 0b0111_1111;
if G1Affine::from_compressed(&o).is_none().into() {
if G1Affine::from_bytes(&o).is_none().into() {
// :)
} else {
panic!("should have rejected the point because we expected a compressed point");
@ -447,7 +445,7 @@ fn test_g1_compressed_invalid_vectors() {
o.as_mut()[..48].copy_from_slice(m.as_ref());
o.as_mut()[0] |= 0b1000_0000;
if G1Affine::from_compressed(&o).is_none().into() {
if G1Affine::from_bytes(&o).is_none().into() {
// x coordinate
} else {
panic!("should have rejected the point")
@ -469,7 +467,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 G1Affine::from_compressed(&o).is_none().into() {
if G1Affine::from_bytes(&o).is_none().into() {
break;
} else {
panic!("should have rejected the point because it isn't on the curve")
@ -492,7 +490,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 G1Affine::from_compressed(&o).is_none().into() {
if G1Affine::from_bytes(&o).is_none().into() {
break;
} else {
panic!(
@ -509,12 +507,12 @@ fn test_g1_compressed_invalid_vectors() {
#[test]
fn test_g2_compressed_invalid_vectors() {
{
let z = G2Affine::identity().to_compressed();
let z = G2Affine::identity().to_bytes();
{
let mut z = z;
z.as_mut()[0] &= 0b0111_1111;
if G2Affine::from_compressed(&z).is_none().into() {
if G2Affine::from_bytes(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because we expected a compressed point");
@ -524,7 +522,7 @@ fn test_g2_compressed_invalid_vectors() {
{
let mut z = z;
z.as_mut()[0] |= 0b0010_0000;
if G2Affine::from_compressed(&z).is_none().into() {
if G2Affine::from_bytes(&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");
@ -534,7 +532,7 @@ fn test_g2_compressed_invalid_vectors() {
for i in 0..G2Compressed::size() {
let mut z = z;
z.as_mut()[i] |= 0b0000_0001;
if G2Affine::from_compressed(&z).is_none().into() {
if G2Affine::from_bytes(&z).is_none().into() {
// :)
} else {
panic!("should have rejected the point because the coordinates should be zeroes at the point at infinity");
@ -542,12 +540,12 @@ fn test_g2_compressed_invalid_vectors() {
}
}
let o = G2Affine::generator().to_compressed();
let o = G2Affine::generator().to_bytes();
{
let mut o = o;
o.as_mut()[0] &= 0b0111_1111;
if G2Affine::from_compressed(&o).is_none().into() {
if G2Affine::from_bytes(&o).is_none().into() {
// :)
} else {
panic!("should have rejected the point because we expected a compressed point");
@ -561,7 +559,7 @@ fn test_g2_compressed_invalid_vectors() {
o.as_mut()[..48].copy_from_slice(m.as_ref());
o.as_mut()[0] |= 0b1000_0000;
if G2Affine::from_compressed(&o).is_none().into() {
if G2Affine::from_bytes(&o).is_none().into() {
// x coordinate (c1)
} else {
panic!("should have rejected the point")
@ -573,7 +571,7 @@ fn test_g2_compressed_invalid_vectors() {
o.as_mut()[48..96].copy_from_slice(m.as_ref());
o.as_mut()[0] |= 0b1000_0000;
if G2Affine::from_compressed(&o).is_none().into() {
if G2Affine::from_bytes(&o).is_none().into() {
// x coordinate (c0)
} else {
panic!("should have rejected the point")
@ -602,7 +600,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 G2Affine::from_compressed(&o).is_none().into() {
if G2Affine::from_bytes(&o).is_none().into() {
break;
} else {
panic!("should have rejected the point because it isn't on the curve")
@ -632,7 +630,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 G2Affine::from_compressed(&o).is_none().into() {
if G2Affine::from_bytes(&o).is_none().into() {
break;
} else {
panic!(