1个不稳定版本
0.4.2 | 2024年5月26日 |
---|
#1199 in 加密学
在 18 crates 中使用
345KB
7.5K SLoC
ark-ff
此crate定义了有限域特性和遵循这些特性的有用抽象模型。一些流行椭圆曲线的具体系列有限域实现可以在 arkworks-rs/curves
下的 arkworks-rs/curves/<你最喜欢的曲线>/src/fields/
中找到。
此crate包含两种类型的特性
Field
特性:这些定义了操作域元素的接口,如加法、乘法、逆元、平方根等。- 域
Config
:指定定义域所需参数。对于扩展域,它还提供了用于构造域所需的一些附加功能,例如涉及用于构造域的(立方或二次)非剩余数(NONRESIDUE
)的操作。
可用的域特性包括
AdditiveGroup
- 与关联的Scalar
类型具有“标量乘法”操作的加法群的接口。这适用于素数域、域扩展和用于密码学的椭圆曲线群。Field
- 泛型有限域的接口。FftField
- 提供允许在域元素上执行高效FFT的方法。PrimeField
- 具有素数p
个元素的域,也称为Fp
。
实现的是以下模型
二次扩展
QuadExtField
- 表示二次扩展域的结构体,在本例中包含两个基域元素QuadExtConfig
- 定义实例化二次扩展域所需必要参数的特质
三次扩展
CubicExtField
- 表示三次扩展域的结构体,包含三个基域元素CubicExtConfig
- 定义创建三次扩展域所需必要参数的特质
上述两个模型作为直接构建扩展域 Fp^m
(即 m
等于 2 或 3)或创建扩展塔以达到更高的 m
的抽象。后者是通过迭代应用扩展来实现的,例如在二次扩展域上的三次扩展。
Fp2
- 在素数域上直接进行二次扩展,即BaseField == BasePrimeField
Fp3
- 在素数域上直接进行三次扩展,即BaseField == BasePrimeField
Fp6_2over3
- 扩展塔:在三次扩展域上进行二次扩展,即BaseField = Fp3
,但BasePrimeField = Fp
。Fp6_3over2
- 扩展塔,与上述类似,但塔的顺序相反:它是在二次扩展域上的三次扩展,即BaseField = Fp2
,但BasePrimeField = Fp
。默认情况下只导出后一个作为Fp6
。Fp12_2over3over2
- 扩展塔:在Fp6_3over2
上的二次扩展,即BaseField = Fp6
。
使用方法
当使用有限域时,有两个重要的特质:Field
和 PrimeField
。让我们通过示例来探讨这些特质。
加法群
AdditiveGroup
特质提供了一个具有相关标量乘法操作的加法群的泛型接口。实现此特质的数据类型支持如加法、减法、取反以及通过 Scalar
关联类型进行的标量乘法等常见群操作。
use ark_ff::AdditiveGroup;
// We'll use a field associated with the BLS12-381 pairing-friendly
// group for this example.
use ark_test_curves::bls12_381::Fq2 as F;
// `ark-std` is a utility crate that enables `arkworks` libraries
// to easily support `std` and `no_std` workloads, and also re-exports
// useful crates that should be common across the entire ecosystem, such as `rand`.
use ark_std::{One, UniformRand};
let mut rng = ark_std::test_rng();
// Let's sample uniformly random field elements:
let a = F::rand(&mut rng);
let b = F::rand(&mut rng);
let c = <F as AdditiveGroup>::Scalar::rand(&mut rng);
// We can add...
let c = a + b;
// ... subtract ...
let d = a - b;
// ... double elements ...
assert_eq!(c + d, a.double());
// ... negate them ...
assert_ne!(d, -d);
// ... and multiply them by scalars:
let e = d * c;
域
Field
特质为任何有限域提供了一个泛型接口。实现 Field
的数据类型支持如加法、减法、乘法和逆等常见域操作,并且也必须是 AdditiveGroup
。
use ark_ff::{AdditiveGroup, Field};
// We'll use a field associated with the BLS12-381 pairing-friendly
// group for this example.
use ark_test_curves::bls12_381::Fq2 as F;
// `ark-std` is a utility crate that enables `arkworks` libraries
// to easily support `std` and `no_std` workloads, and also re-exports
// useful crates that should be common across the entire ecosystem, such as `rand`.
use ark_std::{One, UniformRand};
let mut rng = ark_std::test_rng();
// Let's sample uniformly random field elements:
let a = F::rand(&mut rng);
let b = F::rand(&mut rng);
// We can perform all the operations from the `AdditiveGroup` trait:
// We can add...
let c = a + b;
// ... subtract ...
let d = a - b;
// ... double elements ...
assert_eq!(c + d, a.double());
// ... multiply ...
let e = c * d;
// ... square elements ...
assert_eq!(e, a.square() - b.square());
// ... and compute inverses ...
assert_eq!(a.inverse().unwrap() * a, F::one()); // have to unwrap, as `a` could be zero.
在某些情况下,能够计算域元素的平方根很有用(例如,用于椭圆曲线元素的点压缩)。为此,用户可以为他们的域类型实现与 sqrt
相关的方法。此方法已为素数域(见下文)以及二次扩展域实现。
可以使用以下方式使用与 sqrt
相关的方法
use ark_ff::Field;
// As before, we'll use a field associated with the BLS12-381 pairing-friendly
// group for this example.
use ark_test_curves::bls12_381::Fq2 as F;
use ark_std::{One, UniformRand};
let mut rng = ark_std::test_rng();
let a = F::rand(&mut rng);
// We can check if a field element is a square by computing its Legendre symbol...
if a.legendre().is_qr() {
// ... and if it is, we can compute its square root.
let b = a.sqrt().unwrap();
assert_eq!(b.square(), a);
} else {
// Otherwise, we can check that the square root is `None`.
assert_eq!(a.sqrt(), None);
}
素数域
如果字段是素数阶,则用户可以选择为它实现 PrimeField
特性。这提供了以下额外的API访问
use ark_ff::{Field, PrimeField, FpConfig, BigInteger, Zero};
// Now we'll use the prime field underlying the BLS12-381 G1 curve.
use ark_test_curves::bls12_381::Fq as F;
use ark_std::{One, UniformRand};
let mut rng = ark_std::test_rng();
let a = F::rand(&mut rng);
// We can access the prime modulus associated with `F`:
let modulus = <F as PrimeField>::MODULUS;
assert_eq!(a.pow(&modulus), a);
// We can convert field elements to integers in the range [0, MODULUS - 1]:
let one: num_bigint::BigUint = F::one().into();
assert_eq!(one, num_bigint::BigUint::one());
// We can construct field elements from an arbitrary sequence of bytes:
let n = F::from_le_bytes_mod_order(&modulus.to_bytes_le());
assert_eq!(n, F::zero());
依赖关系
~2.5–3.5MB
~70K SLoC