#curve25519 #ristretto #ristretto255 #curve-point #crypto

无std test-curve25519-dalek

Ristretto255和Curve25519上的纯Rust实现的群操作

10个版本

4.0.0-rc.12023年2月2日
4.0.0-pre.172022年12月14日
4.0.0-pre.102022年11月27日

#875 in 密码学

每月下载 43次

BSD-3-Clause

1MB
25K SLoC

curve25519-dalek Rust

dalek-cryptography logo: a dalek with edwards curves as sparkles coming out of its radar-schnozzley blaster thingies

Ristretto和Curve25519上的纯Rust实现的群操作。

curve25519-dalek是一个库,提供对Curve25519的Edwards和Montgomery形式的群操作,以及素数阶Ristretto群的群操作。

curve25519-dalek不是为了提供任何特定的加密协议的实现。相反,这些协议的实现(如x25519-daleked25519-dalek)应使用curve25519-dalek作为库。

curve25519-dalek旨在提供一个干净且安全的中级 API,用于实现各种基于ECC的加密协议,例如密钥协商、签名、匿名凭证、rangeproofs和零知识证明系统。

特别是,curve25519-dalek实现了Ristretto,它从一个非素数阶Edwards曲线构建一个素数阶群。这提供了Edwards曲线算术的速度和安全性优势,而没有与因子相关的抽象不匹配的陷阱。

使用

稳定

要将curve25519-dalek导入到项目,请将以下内容添加到项目的Cargo.toml依赖项部分

curve25519-dalek = "3"

测试版

要使用最新的预发布版本(见下面的变更),请使用以下行替换项目的Cargo.toml

curve25519-dalek = "4.0.0-rc.0"

功能标志

功能 默认值? 描述
alloc 启用爱德华兹和里斯托多标量乘法、批量标量求逆和批量里斯托双倍压缩。还启用了zeroize
zeroize 为所有标量和曲线点类型启用Zeroize
预计算表 包括预计算的基点乘法表。这使EdwardsPoint::mul_baseRistrettoPoint::mul_base的速度提高了约4倍,但代码大小增加了约30KB。
rand_core 启用了Scalar::randomRistrettoPoint::random。这是一个可选依赖项,其版本不受SemVer约束。有关更多详细信息,请参阅下面
digest 启用了RistrettoPoint::{from_hash, hash_from_bytes}Scalar::{from_hash, hash_from_bytes}。这是一个可选依赖项,其版本不受SemVer约束。有关更多详细信息,请参阅下面
serde 启用了所有点和标量类型的serde序列化/反序列化。

当使用curve25519-dalek作为依赖项时禁用默认功能,请将default-features = false添加到您的Cargo.toml中的依赖项中。要在运行cargo时禁用它,请添加--no-default-features CLI标志。

主要版本API更改

每个主要版本发布的破坏性更改可以在CHANGELOG.md的“破坏性更改”子标题下找到,网址为https://github.com/dalek-cryptography/curve25519-dalek/blob/HEAD/CHANGELOG.md。以下是最新的破坏性更改:

4.0.0中的破坏性更改

  • 将MSRV从1.41更新到1.60
  • 更新后端选择以更自动
  • 删除std功能标志
  • 删除nightly功能标志
  • digest作为一个可选功能
  • rand_core作为一个可选功能
  • 用常量Scalar::{ZERO, ONE}替换方法Scalar::{zero, one}
  • Scalar::from_canonical_bytes现在返回CtOption
  • Scalar::is_canonical现在返回Choice
  • 弃用EdwardsPoint::hash_from_bytes并将其重命名为EdwardsPoint::nonspec_map_to_curve
  • 要求在每次使用 EdwardsBasepointTableRistrettoBasepointTable 时包含一个新的特性,use curve25519_dalek::traits::BasepointTable

此次发布还进行了大量的依赖更新和放宽,以解决上游构建问题。

后端

通过选择以下后端之一来实现和使用曲线算术

后端 实现 目标后端
[默认] 串行公式 u32
u64
simd 并行,使用高级向量扩展 avx2
avx512ifma
fiat 来自 fiat-crypto 的形式化验证字段算术 fiat_u32
fiat_u64

要选择除 [default] 串行后端之外的其他后端,请设置环境变量

RUSTFLAGS='--cfg curve25519_dalek_backend="BACKEND"'

其中 BACKENDsimdfiat。同样,您也可以写入 ~/.cargo/config

[build]
rustflags = ['--cfg=curve25519_dalek_backend="BACKEND"']

更多信息请参阅此处

simd 后端需要额外的配置。请参阅SIMD 部分

对于贡献者:目标后端之间并非完全独立。simd 后端直接依赖于 u64 后端的部分才能正常运行。

串行后端的字大小

curve25519-dalek 将根据构建目标自动选择 [default]fiat 串行后端的字大小。例如,在64位机器上构建时,如果选择了默认后端,则会自动选择默认的 u64 目标后端,而当选择了 `fiat 后端时,则选择 fiat_u64

可以通过设置环境变量来覆盖 [default]fiat 的后端字大小

RUSTFLAGS='--cfg curve25519_dalek_bits="SIZE"'

其中 SIZE3264。与上述部分一样,这也可以放在 ~/.cargo/config 中。

注意:simd 后端不能使用32位字大小。

交叉编译

由于后端选择是根据目标进行的,因此交叉编译将自动选择正确的字大小。例如,在x86-64 Linux机器上,如果运行以下命令,则 curve25519-dalek 将使用 u32 目标后端

$ sudo apt install gcc-multilib # (or whatever package manager you use)
$ rustup target add i686-unknown-linux-gnu
$ cargo build --target i686-unknown-linux-gnu

simd目标后端

必须在simd内部手动进行目标后端选择,通过设置RUSTFLAGS环境变量为以下选项之一

CPU特性 RUSTFLAGS
avx2 -C目标特性=+avx2
avx512ifma -C目标特性=+avx512ifma

或者,如果您不知道要设置什么,可以使用-C target_cpu=native

simd后端也要求使用夜间版本,例如通过运行cargo +nightly build来构建。

文档

semver-stable、面向公众的curve25519-dalek API的文档在这里

本地构建文档

curve25519-dalek的文档需要自定义HTML头部以包含KaTeX进行数学支持。不幸的是,目前cargo doc不支持此功能,但可以使用以下方法构建文档:

make doc

用于常规文档,以及

make doc-internal

用于包含私有项目的文档。

维护策略

此库的所有默认开启特性都受语义版本化(SemVer)的覆盖。以下概述了MSRV和公共API的SemVer豁免。

最低支持的Rust版本

版本 MSRV
4.x 1.60.0
3.x 1.41.0

从4.x开始,MSRV的变化将伴随着次要版本的提升。

公共API SemVer豁免

对影响公共API的SemVer豁免组件的破坏性变更将伴随着一些版本提升。以下是一些具体政策

版本 公共API组件 政策
4.x 依赖项digestrand_core 次要SemVer提升

安全性

curve25519-dalek类型旨在使非法状态不可表示。例如,任何EdwardsPoint的实例都将保证在Edwards曲线上有一个点,任何RistrettoPoint的实例都将保证在Ristretto群中有一个有效的点。

所有操作都是使用恒时逻辑实现的(没有依赖秘密的分支,没有依赖秘密的内存访问),除非明确标记为可变时长的代码。我们相信我们的恒时逻辑被降低到恒时汇编,至少在x86_64目标上。

作为对可能未来的编译器优化的额外保护,subtle crate在每个条件移动或赋值之前放置了一个优化屏障。更多详细信息可以在subtle crate的文档中找到。

某些功能(例如,多标量乘法或批逆运算)需要堆分配临时缓冲区。在释放之前,所有可能包含秘密数据的堆分配缓冲区都将明确地清零。

然而,我们不会尝试清除堆栈数据,有两个原因。首先,这不可能正确完成:我们没有控制堆栈分配,因此无法知道要擦除多少数据。其次,因为curve25519-dalek提供了一个中间层API,正确开始清除堆栈数据的位置可能不是curve25519-dalek函数的入口点,而是其他crate中函数的入口点。

实现是内存安全的,不包含任何显著的unsafe代码。SIMD后端内部使用unsafe调用SIMD内省。这些标记为unsafe仅因为在不适当的CPU上调用它们会导致SIGILL,但整个后端仅使用适当的target_feature编译,因此这种情况不可能发生。

性能

使用criterion.rs运行基准测试。

cargo bench --features "rand_core"
# Uses avx2 or ifma only if compiled for an appropriate target.
export RUSTFLAGS='--cfg curve25519_dalek_backend="simd" -C target_cpu=native'
cargo +nightly bench --features "rand_core"

性能是正确性、安全性和清晰性之后的次要目标,但我们旨在与其他实现具有竞争力。

FFI

遗憾的是,我们没有计划直接将FFI添加到curve25519-dalek中。原因是,我们使用Rust特性提供API,以保持安全性守恒,这在FFI边界上是无法维持的。例如,如上文中的安全性部分所述,无法构造无效点,如果通过FFI公开点操作,则情况并非如此。

然而,curve25519-dalek被设计为一个中级别API,旨在实现其他高级原始操作。而不是在中级别提供FFI,我们的建议是使用curve25519-dalek作为依赖项,在Rust中实现高级原始操作(签名、PAKE、ZKP等),并为该原始操作提供最小化、以字节数据缓冲区为特征的FFI。

贡献

请参阅CONTRIBUTING.md

补丁和pull请求应针对develop分支,而不是main分支。

关于

剧透警告: 第十二任医生的第一次与戴立克的遭遇是在他的第二集完整剧集“进入戴立克”。一支“联合银河抵抗”的疲惫舰队发现了一个损坏的戴立克,它已经“变好”,想要杀死所有其他戴立克。医生、克拉拉和一支士兵小队被微型化并进入戴立克,医生称之为Rusty。他们修复了损坏,但意外地将其恢复到原始状态,导致它开始肆虐并警告戴立克舰队叛乱舰队的位置。然而,医生通过将他的意识与戴立克连接起来,设法将Rusty恢复到先前状态:Rusty与医生对宇宙之美的看法相同,但同时也与他深恶痛绝的戴立克一样。Rusty摧毁了其他戴立克并离开船只,决心追踪并结束戴立克种族。

curve25519-dalek由Isis Agora Lovecruft和Henry de Valence编写。

此库的部分内容最初是Adam Langley的Golang ed25519库的移植,该库反过来又是参考实现ref10的移植。此后,大部分代码,包括32位字段算术,已被重写。

快速u32u64标量算术是由Andrew Moon实现的,标量求逆的加法链是由Brian Smith提供的。优化批量求逆是由Sean Bowe和Daira Hopwood贡献的。

no_stdzeroize支持是由Tony Arcieri贡献的。

形式化验证的fiat_backend集成了由Fiat Crypto项目生成的Rust代码,并由François Garillot贡献。

感谢Ashley Hauck、Lucas Salibian、Manish Goregaokar、Jack Grigg、Pratyush Mishra、Michael Rosenberg、@pinkforest以及无数其他人为他们的贡献。

依赖