6 个版本 (1 个稳定版)
使用旧 Rust 2015
1.2.3 | 2019年10月10日 |
---|---|
0.0.5 | 2019年10月17日 |
#1386 in 密码学
620KB
13K SLoC
curve25519-dalek
ristretto 和 Curve25519 的纯 Rust 实现的群运算。
curve25519-dalek
是一个提供 Curve25519 的 Edwards 和 Montgomery 形式的群运算以及素数阶 Ristretto 群的群运算的库。
curve25519-dalek
的目的不是提供任何特定加密协议的实现。相反,那些协议的实现(如 x25519-dalek
和 ed25519-dalek
)应将 curve25519-dalek
作为库来使用。
curve25519-dalek
的目的是提供一个干净且安全的 中等级别 API,用于实现各种基于 ECC 的加密协议,如密钥协商、签名、匿名凭证、范围证明和零知识证明系统。
特别是,curve25519-dalek
实现了 Ristretto,它从非素数阶的 Edwards 曲线构建素数阶群。这提供了 Edwards 曲线算术的速度和安全性优势,而没有因因数相关抽象不匹配而导致的缺陷。
文档
稳定的、面向公众的 curve25519-dalek
API 文档在此处 文档。此外,不稳定内部实现细节在此处 文档。
curve25519-dalek
文档需要自定义的 HTML 标头以包含 KaTeX 进行数学支持。不幸的是,cargo doc
当前不支持此功能,但可以使用以下方法生成文档:
make doc
make doc-internal
使用
要导入curve25519-dalek
,请将以下内容添加到项目Cargo.toml
的依赖部分:
curve25519-dalek = "1"
然后按照以下方式导入crate:
extern crate curve25519_dalek;
后端和功能
nightly
功能允许在Rust夜间编译器中使用时才可用的功能。它对安全性很有帮助。
曲线算术是通过以下后端之一实现的:
- 使用
u64
产品的u32
后端; - 使用
u128
产品的u64
后端; - 使用并行公式的
avx2
后端,当为目标编译且启用target_feature=+avx2
时可用。
默认选择u64
后端。要选择特定的后端,请使用:
cargo build --no-default-features --features "std u32_backend"
cargo build --no-default-features --features "std u64_backend"
# Requires RUSTFLAGS="-C target_feature=+avx2"
cargo build --no-default-features --features "std avx2_backend"
使用curve25519-dalek
的crate可以为用户选择后端,或者公开控制curve25519-dalek
后端的功能标志。
std
功能默认启用,但可以通过使用--no-default-features
禁用它以进行无std
构建。请注意,这需要显式选择一个算术后端,可以使用_backend
功能之一。如果没有选择后端,则编译将失败。
yolocrypto
功能启用实验性功能。名称yolocrypto
旨在表明它尚未被认为是生产就绪的,并且我们不认为yolocrypto
功能受semver保证的覆盖。这旨在在首先稳定它们之前更容易地测试预期的新功能。请自行承担使用yolocrypto
的风险。
安全性
curve25519-dalek
类型旨在使非法状态无法表示。例如,任何EdwardsPoint
的实例都保证持有Edwards曲线上的点,任何RistrettoPoint
的实例都保证持有Ristretto群中的有效点。
所有操作都使用恒时逻辑实现(没有秘密依赖的分支,没有秘密依赖的内存访问),除非明确标记为可变时代码。我们相信我们的恒时逻辑被降低为恒时汇编,至少在x86_64
目标上是这样。
作为防止未来编译器优化的一种额外保护,nightly
功能在每个条件移动或赋值之前放置了一个优化障碍。更多详情请参阅subtle
crate的文档。这建议,但不是必需的。
某些功能(例如,多标量乘法或批反演)需要堆分配临时缓冲区。所有可能包含秘密数据的堆分配缓冲区在释放之前都明确地置零。
然而,我们没有尝试为零栈数据。原因有两个。首先,这不可能做到正确:我们没有控制栈分配,因此无法知道要擦除多少数据。其次,因为curve25519-dalek
提供了一级API,开始零化栈数据的位置很可能不是在curve25519-dalek
函数的入口点,而是在其他crate中函数的入口点。
实现是内存安全的,不包含任何显著的不安全
代码。AVX2后端内部使用不安全
来调用AVX2内嵌函数。这些被标记为不安全
,因为在非AVX2目标上调用它们会导致SIGILL
,但整个后端仅编译为支持target_feature=+avx2
。一些类型实现了不安全
特质来标记它们为零可清除(对于堆分配),但这不会影响内存安全。
性能
基准测试使用criterion.rs
进行。
# You must set RUSTFLAGS to enable AVX2 support.
export RUSTFLAGS="-C target_cpu=native"
cargo bench --no-default-features --features "std u32_backend"
cargo bench --no-default-features --features "std u64_backend"
cargo bench --no-default-features --features "std avx2_backend"
性能是正确性、安全性和清晰性之后的次要目标,但我们的目标是与其他实现具有竞争力。
FFI
遗憾的是,我们没有计划直接向curve25519-dalek
添加FFI。原因是,我们使用Rust功能提供维护安全不变量的API,这是无法在FFI边界上维护的。例如,如上文中安全部分所述,无法构造无效点,如果我们在FFI中公开点操作,则不会是这样。
然而,curve25519-dalek
被设计为一个中级别 API,旨在实现其他更高级的原始函数。而不是在中级别提供FFI,我们的建议是在Rust中实现高级原始函数(签名、PAKE、ZKP等),使用curve25519-dalek
作为依赖项,并让该crate为该原始函数提供最小、以字节缓冲区为中心的特定FFI。
贡献
请参阅CONTRIBUTING.md。
补丁和pull请求应针对develop
分支,而不是master
。
关于
剧透警告: 第十二任博士第一次遇到 Dalek 是在他的第二集全剧,“Into the Dalek”。一支“联合银河抵抗”的疲惫舰队发现了一个坏掉的 Dalek 变“好”了,希望杀死所有其他 Dalek。博士、克拉拉和一支士兵队伍被缩小并进入 Dalek,博士将其命名为 Rusty。他们修复了损坏,但意外地将它恢复到原始状态,导致它开始狂欢,并警告 Dalek 舰队叛变飞船的位置。然而,博士通过将自己的意识与 Dalek 连接起来,成功地使 Rusty 恢复到之前的状态:Rusty 与博士一样,分享了宇宙之美的观点,但也分享了博士对 Dalek 的深深仇恨。Rusty 毁灭了其他 Dalek,并离开了飞船,决心追踪并结束 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
支持由 Tony Arcieri 贡献。
感谢 Ashley Hauck、Lucas Salibian 和 Manish Goregaokar 的贡献。
依赖项
~0.5–1.3MB
~27K SLoC