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
现在返回CtOption
Scalar::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以及无数其他人为他们的贡献。