3个版本
0.1.0-alpha.2 | 2024年7月26日 |
---|---|
0.1.0-alpha.1 | 2024年6月26日 |
244 在 密码学
136 每月下载量
1.5MB
27K SLoC
curve25519-elligator2
这是一个为了方便而创建的分支
这个分支包含一个等待被合并到主流 curve25519-dalek
crate的 elligator2 实现。这个crate存在是为了在过渡期间使用。因此,这个crate
- 可能会更改其API以符合上游源的需求
- 如果功能被合并到上游源,它将被撤回。
使用
要导入 curve25519-elligator2
,请在项目的 Cargo.toml
依赖部分添加以下内容
curve25519-elligator2 = "0.1.0-alpha.2"
以下是底层 curve25519-dalek
crate 的文档。
curve25519-dalek
这是Ristretto和Curve25519群运算的纯Rust实现。
curve25519-dalek
是一个提供Edwards和Montgomery形式的Curve25519以及素阶Ristretto群群运算的库。
curve25519-dalek
并不旨在提供任何特定加密协议的实现。相反,这些协议的实现(如 x25519-dalek
和 ed25519-dalek
)应将 curve25519-dalek
作为库使用。
curve25519-dalek
的目的是提供一个干净且安全的 中级 API,用于实现各种基于椭圆曲线的加密协议,例如密钥协商、签名、匿名凭证、范围证明和零知识证明系统。
特别是,curve25519-dalek
实现了 Ristretto,它从非素数阶的 Edwards 曲线构建一个素数阶群。这提供了 Edwards 曲线算术的速度和安全性好处,而没有与系数相关的抽象不匹配的陷阱。
使用
稳定
要导入 curve25519-dalek
,请将以下内容添加到项目 Cargo.toml
的依赖项部分
curve25519-dalek = "4"
如果选择启用 SemVer 免责功能,可以使用范围来限定测试兼容的版本范围,例如。
curve25519-dalek = ">= 4.0, < 4.2"
功能标志
功能 | 默认? | 描述 |
---|---|---|
alloc |
✓ | 启用 Edwards 和 Ristretto 多标量乘法、批量标量求逆和批量 Ristretto 双倍和压缩。同时启用 zeroize 。 |
zeroize |
✓ | 为所有标量和曲线点类型启用 Zeroize 。 |
precomputed-tables |
✓ | 包含预计算的基点乘法表。这使 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 序列化/反序列化。 |
|
legacy_compatibility |
启用 Scalar::from_bits ,允许用户构建未简化的标量,其算术是损坏的。除非您知道自己在做什么,否则不要使用此功能。 |
|
group |
启用外部 group 和 ff crate 特性 |
|
elligator2 |
为支持的类型启用 elligator2 功能。这允许将曲线点编码到统一的随机表示,并将 32 字节值映射(回)到曲线点。 |
要在使用 curve25519-dalek
作为依赖项时禁用默认功能,请将 default-features = false
添加到您的 Cargo.toml
中的依赖项中。要在运行 cargo
时禁用它,请添加 CLI 标志 --no-default-features
。
主要版本 API 变更
每个主要版本发布中的破坏性变更可以在 CHANGELOG.md
下的 "破坏性变更" 子标题中找到。以下是高级别的最新破坏性变更:
4.0.0 中的破坏性变更
- 将 MSRV 从 1.41 更新到 1.60
- 提供 SemVer 策略
- 使
digest
和rand_core
成为可选功能 - 删除
std
和nightly
功能 - 替换后端选择 - 请参阅 CHANGELOG.md 和 后端
- 用常量
Scalar::{ZERO, ONE}
替换方法Scalar::{zero, one}
Scalar::from_canonical_bytes
现在返回CtOption
Scalar::is_canonical
现在返回Choice
- 删除
Scalar::from_bytes_clamped
和Scalar::reduce
- 废弃并使用
legacy_compatibility
功能门禁Scalar::from_bits
- 废弃
EdwardsPoint::hash_from_bytes
并将其重命名为EdwardsPoint::nonspec_map_to_curve
- 当使用
EdwardsBasepointTable
或RistrettoBasepointTable
时,需要包含一个新特性,use curve25519_dalek::traits::BasepointTable
此版本还对依赖项进行了大量的更新和放宽,以解决上游构建问题。
后端
曲线算术由以下后端之一实现和使用
后端 | 选择 | 实现 | 位 / 字大小 |
---|---|---|---|
serial |
自动 | 一个优化、非并行实现 | 32 和 64 |
fiat |
手动 | 来自 fiat-crypto 的形式验证字段算术 | 32 和 64 |
simd |
自动 | Intel AVX2 / AVX512 IFMA 加速后端 | 64 |
在运行时,curve25519-dalek
从其编译以支持的后端集中选择一个算术后端。对于 Intel x86-64 目标,除非另有说明,否则它将使用 simd
支持构建自身,并在运行时默认使用 serial
,如果检测不到适当的 CPU 功能。有关详细信息,请参阅 SIMD 后端。
在未来,simd
后端可能会扩展以支持更多的指令集。这种更改不会破坏现有功能,因为这被视为实现细节。
手动后端覆盖
您可以通过设置环境变量强制 crate 使用特定的后端支持,例如,为 x86-64 目标使用 serial
以节省代码大小,或使用 fiat
以强制运行时使用经过验证的代码。为此,请设置以下环境变量:
RUSTFLAGS='--cfg curve25519_dalek_backend="BACKEND"'
同样,您也可以写入 ~/.cargo/config
[build]
rustflags = ['--cfg=curve25519_dalek_backend="BACKEND"']
更多信息请参阅此处。
对贡献者的说明:目标后端并不是完全相互独立的。SIMD 后端直接依赖于串行后端的部分功能才能运行。
位 / 字大小
curve25519-dalek
将根据构建目标自动选择 fiat
和 serial
后端的字大小。例如,为 64 位机器构建时,如果选择了 serial
或 fiat
后端,将自动选择默认的 64 位字大小。
在某些目标上,可能需要覆盖字大小以获得更好的性能。可以通过设置环境变量覆盖 serial
和 fiat
的字大小:
RUSTFLAGS='--cfg curve25519_dalek_bits="SIZE"'
SIZE
是 32
或 64
。如上所述,这也可以放在 ~/.cargo/config
中。
注意:SIMD 后端需要 64 位字大小。尝试设置 bits=32 和 backend=simd
将导致编译错误。
交叉编译
由于后端选择是通过目标进行的,交叉编译将自动选择正确的字大小。例如,如果 x86-64 Linux 机器运行以下命令,curve25519-dalek
将使用 32 位的 serial
后端编译。
$ 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 后端(AVX512 / AVX2 / serial
默认)会根据当前可用的 CPU 功能以及是否使用 Rust 夜间构建自动选择。具体条件如下所述。
对于给定的 CPU 功能,您也可以指定适当的 -C target_feature
以构建假设所需的 SIMD 指令始终可用的二进制文件。如果没有充分的理由,请不要这样做。
后端 | RUSTFLAGS |
需要夜间版本吗? |
---|---|---|
avx2 | -C target_feature=+avx2 |
否 |
avx512 | -C target_feature=+avx512ifma,+avx512vl |
是 |
如果使用非夜间编译器编译,curve25519-dalek
将不会包含 AVX512 代码,因此在运行时永远不会选择它。
文档
公开的 curve25519-dalek
API 使用语义版本控制(SemVer)进行文档记录此处。
在本地构建文档
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 | 依赖项 group 、digest 和 rand_core |
次要SemVer提升 |
安全性
《curve25519-dalek》类型的目的是使非法状态无法表示。例如,任何EdwardsPoint
实例都保证在Edwards曲线上有一个点,任何RistrettoPoint
实例都保证在Ristretto群中有一个有效点。
所有操作都使用恒定时间逻辑(没有秘密相关的分支,没有秘密相关的内存访问)实现,除非特别标记为变量时间代码。我们相信我们的恒定时间逻辑降低到恒定时间汇编,至少在x86_64
目标上。
为了防止可能的未来编译器优化,subtle
包在每个条件移动或赋值之前放置了一个优化屏障。更多详细信息可以在《curve25519-dalek》包文档中找到。
某些功能(例如,多标量乘法或批量求逆)需要堆分配临时缓冲区。所有可能包含秘密数据的堆分配缓冲区在释放之前都明确地清零。
然而,我们没有尝试清零堆栈数据,原因有两个。首先,这样做不可能正确:我们没有控制堆分配,因此不知道要擦除多少数据。其次,因为《curve25519-dalek》提供的是中级别API,正确的开始清零堆栈数据的地方可能是《curve25519-dalek》函数的入口点,而不是其他包中函数的入口点。
实现是内存安全的,并且不包含任何显著的unsafe
代码。SIMD后端使用unsafe
内部调用SIMD内联函数。这些被标记为unsafe
,仅因为在不适当的CPU上调用它们会导致SIGILL
,但整个后端仅在运行时检测到适当的CPU功能或整个程序使用适当的target_feature
编译时才会调用。
性能
基准测试使用criterion.rs
运行。
cargo bench --features "rand_core"
export RUSTFLAGS='-C target_cpu=native'
cargo +nightly bench --features "rand_core"
性能是正确性、安全性和清晰度之后的次要目标,但我们的目标是与其他实现竞争。
FFI
遗憾的是,我们没有计划直接在《curve25519-dalek》中添加FFI。原因是我们使用Rust特性提供保持安全不变性的API,这些不变性不可能在FFI边界上保持。例如,如上所述的《安全性》部分中所述,无效点是不可能构造的,如果我们在FFI上公开点操作,则情况并非如此。
然而,《curve25519-dalek》被设计为中级别API,旨在实现其他更高级的原始功能。而不是在中级别提供FFI,我们的建议是在Rust中实现更高级的原语(例如签名、PAKE、ZKP等),将《curve25519-dalek》作为依赖项,并让该包提供针对该原语的特定于字节的缓冲区FFI。
贡献
请参阅《CONTRIBUTING.md。
关于
剧透警告: 第十二任博士与 Daleks 的第一次接触发生在他的第二集全剧,“进入 Dalek”。一艘“联合银河抵抗”的船发现了一台损坏的 Dalek 已经变成“善良”的,渴望杀死所有其他 Daleks。博士、克拉拉和一支士兵小队被缩小并进入 Dalek,博士将其命名为 Rusty。他们修复了损坏,但意外地将其恢复到原始状态,导致它大肆破坏并警告 Dalek 舰队叛乱船的位置。然而,博士通过将他的心灵与 Dalek 连接起来,设法将 Rusty 恢复到之前的状态:Rusty 分享了博士对宇宙之美的看法,同时也分享了他对 Daleks 的深深仇恨。Rusty 摧毁了其他 Daleks 并离开了船只,决心追踪并结束 Dalek 种族。
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 以及无数其他人为他们的贡献。
依赖项
~0–1.4MB
~30K SLoC