8 个重大版本发布
0.9.0 | 2024 年 6 月 3 日 |
---|---|
0.8.0 | 2023 年 11 月 1 日 |
0.7.0 | 2023 年 8 月 28 日 |
0.5.0 | 2023 年 7 月 23 日 |
0.3.0 | 2022 年 9 月 9 日 |
#96 在 加密学 中
每月 781 次下载
在 4 个 crate 中使用 (2 直接)
3MB
55K SLoC
crrl
该库实现了某些用于加密研究的基本功能。其目标是提供高效、优化且为常量时间的实现,这些实现应代表生产级代码,以便进行现实性能基准测试。因此,尽管主要用于研究,这里的代码 应该 适合生产使用(尽管当然我不提供此类保证;风险自负)。
目前,仅实现了与椭圆曲线密码学相关的一些基本功能
-
一个通用的类型
GF255<MQ>
用于模素数 2^255-MQ 的整数有限域(其中 MQ 的值为 1 到 32767)。MQ 值作为类型参数提供,即确切的域在编译时已知。此类型涵盖了通常的模 2^255-19(用于 Curve25519)以及 2^255-18651 和 2^255-3957(用于 双奇数曲线 do255e 和 do255s)。 -
一个通用的类型
ModInt256<M0, M1, M2, M3>
用于 2^192 到 2^256 之间的任意有限整数域。内部使用 Montgomery 表示法。模数作为类型参数提供,允许编译器在模数的某些部分允许时应用优化(特别是用于 NIST 曲线 P-256 的模数)。 -
类型
GFsecp256k1
实现了曲线 secp256k1 的特定基域(模 2^256-4294968273 的整数)。64 位后端有专门的实现,而该类型的 32 位版本使用ModInt256
。 -
宏
define_gfgen
允许定义模素数的任意有限整数域,具有广泛的模数大小范围。它内部使用 Montgomery 表示法。 -
类型
GF448
实现了 Curve448 的特定基域。64 位后端有专门的实现,而 32 位后端使用define_gfgen
。 -
类型
ed25519::Point
提供了在 twisted Edwards 曲线 Curve25519 中的通用群操作。Ed25519 签名(根据 RFC 8032)已实现。类型ed25519::Scalar
实现了在曲线子群阶数模下的整数运算。 -
类型
ristretto255::Point
提供了在 ristretto255 群 中的通用群操作,其素数阶恰好等于 Curve25519 有趣子群的大小。 -
类型
ed448::Point
提供了在 Edwards 曲线 edwards448 中的通用群操作。Ed448 签名(根据 RFC 8032)已实现。类型ed448::Scalar
实现了在曲线子群阶数模下的整数运算。 -
类型
decaf448::Point
提供了在 decaf448 群 中的通用群操作,其素数阶恰好等于 Curve448 有趣子群的大小。 -
类型
p256::Point
提供了在 NIST P-256 曲线(即“secp256r1”或“prime256v1”)中的通用群操作。支持 ECDSA 签名。类型p256::Scalar
实现了对应的标量(曲线阶数模下的整数)。 -
类型
secp256k1::Point
提供了在 secp256k1 曲线(即“比特币曲线”)中的通用群操作。支持 ECDSA 签名。类型secp256k1::Scalar
实现了对应的标量(曲线阶数模下的整数)。利用 GLV 内自同构来加速点乘法(密钥交换)和签名验证。 -
类型
jq255e::Point
和jq255s::Point
实现了 双奇数曲线 jq255e 和 jq255s(以及相应的标量类型jq255e::Scalar
和jq255s::Scalar
)。实现了密钥交换和 Schnorr 签名。这些曲线提供了一个素数阶群抽象,类似于 ristretto255,但在相同的安全级别上具有更好的性能。此外,相关签名更短(48字节而不是64字节),且比常规 Ed25519 签名更快。 -
函数
x25519::x25519()
实现了 X25519 函数。当 X25519 应用到传统基点时,提供了一个优化的x25519::x2559_base()
函数。类似地,x448::x448()
和x448::x448_base()
提供了 X448 函数的相同功能。 -
类型
gls254::Point
实现了 GLS254 曲线(或者更准确地说,与该曲线的子群同构的素数阶群同态),该曲线是在二进制域上定义的。gls254::Scalar
是模曲线阶数的整数类型。gls254::PrivateKey
和gls254:PublicKey
使用该群实现高级操作,如密钥交换和签名。 -
模块
blake2s
包含一些 BLAKE2s 实现,具有可选的 SSE2 和 AVX2 优化。
类型 GF255
和 ModInt256
每个都有 32 位和 64 位的实现(实际上有两个 64 位的实现,请参阅后面的关于 gf255_m51
功能的讨论)。代码是可移植的(已在 32 位和 64 位的 x86、64 位的 aarch64 和 64 位的 riscv64 上进行了测试)。性能相当不错;例如,在 Intel "Coffee Lake" CPU 上,Ed25519 签名计算大约需要 51500 个周期,验证大约需要 114000 个周期;这并不比最佳汇编优化实现差太多。同时,使用运算符重载可以以与它们的数学描述几乎相同的语法表达点上的公式和标量。例如,X25519 实现的核心如下
let A = x2 + z2;
let B = x2 - z2;
let AA = A.square();
let BB = B.square();
let C = x3 + z3;
let D = x3 - z3;
let E = AA - BB;
let DA = D * A;
let CB = C * B;
x3 = (DA + CB).square();
z3 = x1 * (DA - CB).square();
x2 = AA * BB;
z2 = E * (AA + E.mul_small(121665));
这非常接近 RFC 7748 中的对应描述
A = x_2 + z_2
AA = A^2
B = x_2 - z_2
BB = B^2
E = AA - BB
C = x_3 + z_3
D = x_3 - z_3
DA = D * A
CB = C * B
x_3 = (DA + CB)^2
z_3 = x_1 * (DA - CB)^2
x_2 = AA * BB
z_2 = E * (AA + a24 * E)
可选功能
默认情况下,crrl 中的所有内容都会进行编译,这不幸地导致编译时间相对较长,尤其是在不太快的系统上。要仅编译某些原语的支持,请使用 --no-default-features
,然后使用 -F
选择性地添加您感兴趣的功能;例如,使用 cargo build --no-default-features -F ed25519
仅编译 Ed25519 支持(以及它需要的原语,例如其基域)。定义的原语控制功能如下
-
omnes
:启用以下所有功能。 -
decaf448
:基于 edwards448 的 decaf448 素数阶群 -
ed25519
:edwards25519 曲线和签名(RFC 8032:Ed25519) -
ed448
:edwards448 曲线和签名(RFC 8032:Ed448) -
frost
:FROST 阈值签名(支持宏和标准密码套件,但仅限于在此构建中启用的曲线) -
jq255e
:jq255e 素数阶群和签名 -
jq255s
:jq255s 素数阶群和签名 -
lms
:LMS 支持(基于散列的签名) -
p256
:NIST P-256 曲线和签名(ECDSA) -
ristretto255
:基于 edwards25519 的 ristretto255 素数阶群 -
secp256k1
:secp256k1 曲线和签名(ECDSA) -
x25519
:X25519 密钥交换原语(RFC 7748) -
x448
:X448 密钥交换原语(RFC 7748) -
modint256
:通用有限域实现(素数阶数最多 256 位) -
gf255
:通用有限域实现(对于素数阶数q = 2^255 - MQ
且MQ < 2^15
) -
gfgen
:通用有限域实现(生成宏;任意长度的素数模数) -
gls254
:GLS254素数阶群和签名 -
gls254bench
:为GLS254提供的额外基准测试代码 -
blake2s
:BLAKE2s哈希函数
某些操作有多个后端。在编译时选择适当的后端,但可以通过启用某些功能来覆盖它。
-
w32_backend
:即使在64位系统上,也强制使用32位代码。 -
w64_backend
:即使在32位系统上,也强制使用64位代码。 -
gf255_m64
:强制为GF255<MQ>
使用64位肢体;这是64位机器上的默认设置,除了RISC-V(riscv64)默认使用51位肢体。如果使用32位代码,则此功能没有作用。 -
gf255_m51
:为GF255<MQ>
编码使用51位肢体;这是64位RISC-V目标(riscv64)的默认设置,但不是在其他64位架构中,在这些架构中通常首选64位肢体。如果使用32位代码,则此功能没有作用。 -
gfb254_m64
:强制使用二进制域GF(2^254)的通用实现。如果使用32位代码,则此功能没有作用。 -
gfb254_x86clmul
:强制使用AVX2+pclmulqdq实现的二进制域GF(2^254)。如果编译目标是具有相关硬件支持的x86,则自动使用此代码;此功能绕过了自动检测。如果使用32位代码,则此功能没有作用。 -
gfb254_arm64pmull
:强制使用NEON+pmull实现的二进制域GF(2^254)。如果编译目标是aarch64系统,则自动使用此代码;此功能绕过了自动检测。如果使用32位代码,则此功能没有作用。
安全和合规性
所有代码都严格遵循,无论是基于时间的侧信道(所有内容都是恒时,除非明确指出否则,例如在包含vartime
的函数中)还是遵守相关标准。例如,Ed25519签名支持适用并强制执行点标量和标量的规范编码。
代码中没有任何尝试进行“零化内存”。一般来说,这种内存清理是徒劳的。请注意,由于大多数库使用no_std
规则,动态分配仅在堆栈上发生,从而限制了在RAM中留下秘密信息风险。只有使用堆分配的函数才存储在那里。
警告:我重申上述内容:尽管所有代码都旨在代表经过优化的生产就绪代码,但它仍然相当新,而且可能仍然存在一些错误,无论我在编写代码时多么小心。任何关于适用性的声明都明确否认。主要目的是通过提供性能足够接近实际应用性能的易于使用的API,帮助进行密码学研究中的“尝试”。
截断签名
Ed25519 和 ECDSA/P-256 实现了对截断签名的支持。标准签名可以缩短 8 到 32 位(即大小可能从 64 字节缩小到 60 字节),验证者在验证过程中重新构建原始签名(这会产生一定的计算成本)。这不是一个突破性的功能,但在带宽紧张且需要使用标准签名格式的情况下,它可能非常有用。有关详细信息,请参阅 ed25519::PublicKey::verify_trunc_raw()
和 p256::PublicKey::verify_trunc_hash()
。
FROST 阈值 Schnorr 签名
按照 v14 草案规范,已经实现了用于分布式 Schnorr 签名生成方案的 FROST 协议:draft-irtf-cfrg-frost-14。提供了四个具有类似 API 的加密套件,分别在 frost::ed25519
、frost::ristretto255
、frost::ed448
、frost::p256
和 frost::secp256k1
模块中。在 frost-sample.rs 文件中提供了如何使用 API 的示例代码。
虽然 FROST 本质上是一种分布式方案,但通过直接使用“组”私钥,该实现也可以用于单签名者模式。
基准测试
cargo bench
运行了一些基准测试,但有一些注意事项
-
在 x86 上使用循环计数器。如果未禁用频率缩放(“TurboBoost”),则会得到错误且无意义的结果。
-
在 aarch64 上,循环计数器也直接访问,通常会导致某些 CPU 异常。必须首先启用对计数器的访问,这需要在 Linux 上加载一个特定的内核模块。这个模块适用于我。
-
在 riscv64gc 上,循环计数器直接访问。通常,该计数器未启用,所有基准测试都返回零;要启用循环计数器,请将基准测试二进制文件在
perf
工具(随linux-tools
一起提供)中运行。 -
在 i386、x86-64、aarch64 和 riscv64gc 之外的架构上,基准测试代码将无法编译。
待办事项
一般来说,如果有关密码学的任何内容都有用,它都可能出现在这里。
依赖关系
~1.5MB
~12K SLoC