10个版本
| 4.0.0-rc.1 | 2023年2月2日 |
|---|---|
| 4.0.0-pre.17 | 2022年12月14日 |
| 4.0.0-pre.10 | 2022年11月27日 |
#875 in 密码学
每月下载 43次
1MB
25K SLoC
curve25519-dalek

Ristretto和Curve25519上的纯Rust实现的群操作。
curve25519-dalek是一个库,提供对Curve25519的Edwards和Montgomery形式的群操作,以及素数阶Ristretto群的群操作。
curve25519-dalek不是为了提供任何特定的加密协议的实现。相反,这些协议的实现(如x25519-dalek和ed25519-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_base和RistrettoPoint::mul_base的速度提高了约4倍,但代码大小增加了约30KB。 |
rand_core |
启用了Scalar::random和RistrettoPoint::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现在返回CtOptionScalar::is_canonical现在返回Choice- 弃用
EdwardsPoint::hash_from_bytes并将其重命名为EdwardsPoint::nonspec_map_to_curve - 要求在每次使用
EdwardsBasepointTable或RistrettoBasepointTable时包含一个新的特性,use curve25519_dalek::traits::BasepointTable
此次发布还进行了大量的依赖更新和放宽,以解决上游构建问题。
后端
通过选择以下后端之一来实现和使用曲线算术
| 后端 | 实现 | 目标后端 |
|---|---|---|
[默认] |
串行公式 | u32 u64 |
simd |
并行,使用高级向量扩展 | avx2 avx512ifma |
fiat |
来自 fiat-crypto 的形式化验证字段算术 | fiat_u32 fiat_u64 |
要选择除 [default] 串行后端之外的其他后端,请设置环境变量
RUSTFLAGS='--cfg curve25519_dalek_backend="BACKEND"'
其中 BACKEND 为 simd 或 fiat。同样,您也可以写入 ~/.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"'
其中 SIZE 为 32 或 64。与上述部分一样,这也可以放在 ~/.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 | 依赖项digest和rand_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位字段算术,已被重写。
快速u32和u64标量算术是由Andrew Moon实现的,标量求逆的加法链是由Brian Smith提供的。优化批量求逆是由Sean Bowe和Daira Hopwood贡献的。
no_std和zeroize支持是由Tony Arcieri贡献的。
形式化验证的fiat_backend集成了由Fiat Crypto项目生成的Rust代码,并由François Garillot贡献。
感谢Ashley Hauck、Lucas Salibian、Manish Goregaokar、Jack Grigg、Pratyush Mishra、Michael Rosenberg、@pinkforest以及无数其他人为他们的贡献。