#elliptic-curve #serialization #traits #arkworks #object #polynomial

no-std ark-serialize

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

13个版本

0.5.0-alpha.02024年6月20日
0.4.2 2023年3月18日
0.4.1 2023年2月21日
0.4.0-alpha.72022年12月29日
0.2.0 2021年3月24日

#418 in 加密学

Download history 151037/week @ 2024-04-27 156617/week @ 2024-05-04 167856/week @ 2024-05-11 145249/week @ 2024-05-18 165826/week @ 2024-05-25 165768/week @ 2024-06-01 155689/week @ 2024-06-08 168547/week @ 2024-06-15 185189/week @ 2024-06-22 157145/week @ 2024-06-29 163209/week @ 2024-07-06 187504/week @ 2024-07-13 200458/week @ 2024-07-20 184452/week @ 2024-07-27 218371/week @ 2024-08-03 199008/week @ 2024-08-10

835,189 每月下载量
用于 2,079 个crate (152 个直接使用)

MIT/Apache

53KB
1.5K SLoC

ark-serialize

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

用法

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

ark-serialize = "0.4"

如果您还想为您的类型推导 CanonicalSerializeCanonicalDeserialize trait的实现,您可以使用 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);

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

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

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

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

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–3MB
~62K SLoC