#elliptic-curve #serialization #element #object #data #traits

无 std ark-serialize-zypher

用于序列化 arkworks 生态系统中的类型库

1 个不稳定版本

0.4.2 2024 年 5 月 26 日

#887 in 加密学


19 个crate中(直接使用17个)使用

MIT/Apache

54KB
1.5K SLoC

ark-serialize

ark-serialize 定义了用于将 Rust 数据结构序列化和反序列化为字节的 CanonicalSerializeCanonicalDeserialize 特性。这些特性提供的接口专门针对加密对象进行序列化。特别是,它们为椭圆曲线元素的压缩表示提供特殊支持。大多数 arkworks-rs 中的类型都实现了这些特性。

用法

要使用 ark-serialize,请将以下内容添加到您的 Cargo.toml

ark-serialize = "0.4"

如果您还希望为您的类型推导 CanonicalSerializeCanonicalDeserialize 特性的实现,可以启用 derive 功能

ark-serialize = { version = "0.4", features = ["derive"] }

示例

让我们首先看看如何使用 ark-serialize 对现有类型进行操作

// We'll use the BLS12-381 pairing-friendly group for this example.
use ark_test_curves::bls12_381::{G1Projective as G1, G2Projective as G2, G1Affine, G2Affine};
use ark_serialize::{CanonicalSerialize, CanonicalDeserialize};
use ark_std::UniformRand;

let mut rng = ark_std::test_rng();
// Let's sample uniformly random group elements:
let a: G1Affine = G1::rand(&mut rng).into();
let b: G2Affine = G2::rand(&mut rng).into();

// We can serialize with compression...
let mut compressed_bytes = Vec::new();
a.serialize_compressed(&mut compressed_bytes).unwrap();
// ...and without:
let mut uncompressed_bytes = Vec::new();
a.serialize_uncompressed(&mut uncompressed_bytes).unwrap();

// We can reconstruct our points from the compressed serialization...
let a_compressed = G1Affine::deserialize_compressed(&*compressed_bytes).unwrap();

// ... and from the uncompressed one:
let a_uncompressed = G1Affine::deserialize_uncompressed(&*uncompressed_bytes).unwrap();

assert_eq!(a_compressed, a);
assert_eq!(a_uncompressed, a);

// If we trust the origin of the serialization
// (eg: if the serialization was stored on authenticated storage),
// then we can skip some validation checks, which can greatly reduce deserialization time.
let a_uncompressed_unchecked = G1Affine::deserialize_uncompressed_unchecked(&*uncompressed_bytes).unwrap();
let a_compressed_unchecked = G1Affine::deserialize_compressed_unchecked(&*compressed_bytes).unwrap();
assert_eq!(a_uncompressed_unchecked, a);
assert_eq!(a_compressed_unchecked, a);

如果我们想序列化自己的结构体,如果所有字段都实现了这些特性,我们可以为 CanonicalSerializeCanonicalDeserialize 特性推导实现。例如

use ark_test_curves::bls12_381::{G1Affine, G2Affine};
use ark_serialize::{CanonicalSerialize, CanonicalDeserialize};

#[derive(CanonicalSerialize, CanonicalDeserialize)]
pub struct MyStruct {
    a: G1Affine,
    b: G2Affine,
}

我们也可以手动实现这些特性。例如

use ark_test_curves::bls12_381::{G1Affine, G2Affine};
use ark_serialize::{CanonicalSerialize, CanonicalDeserialize, Compress, SerializationError, Valid, Validate};
use ark_std::io::{Read, Write};

pub struct MyStruct {
    a: G1Affine,
    b: G2Affine,
}

impl CanonicalSerialize for MyStruct {
    // We only have to implement the `serialize_with_mode` method; the other methods 
    // have default implementations that call the latter.
    //
    // Notice that `serialize_with_mode` takes `mode: Compress` as an argument. This 
    // is used to indicate whether we want to serialize with or without compression.
    fn serialize_with_mode<W: Write>(&self, mut writer: W, mode: Compress) -> Result<(), SerializationError> {
        self.a.serialize_with_mode(&mut writer, mode)?;
        self.b.serialize_with_mode(&mut writer, mode)?;
        Ok(())
    }

    fn serialized_size(&self, mode: Compress) -> usize {
        self.a.serialized_size(mode) + self.b.serialized_size(mode)
    }
}

impl CanonicalDeserialize for MyStruct {
    // We only have to implement the `deserialize_with_mode` method; the other methods 
    // have default implementations that call the latter.
    fn deserialize_with_mode<R: Read>(mut reader: R, compress: Compress, validate: Validate) -> Result<Self, SerializationError> {
        let a = G1Affine::deserialize_with_mode(&mut reader, compress, validate)?;
        let b = G2Affine::deserialize_with_mode(&mut reader, compress, validate)?;
        Ok(Self { a, b })
    }
}

// We additionally have to implement the `Valid` trait for our struct.
// This trait specifies how to perform certain validation checks on deserialized types.
// For example, we can check that the deserialized group elements are in the prime-order subgroup.
impl Valid for MyStruct {
    fn check(&self) -> Result<(), SerializationError> {
        self.a.check()?;
        self.b.check()?;
        Ok(())
    }
}

依赖关系

~2–2.8MB
~54K SLoC