#curve25519 #ristretto #ristretto255 #crypto

no-std curve25519-dalek-organism

ristretto255 和 Curve25519 的纯 Rust 实现的群运算

6 个版本 (1 个稳定版)

使用旧 Rust 2015

1.2.3 2019年10月10日
0.0.5 2019年10月17日

#1386 in 密码学

BSD-3-Clause

620KB
13K SLoC

curve25519-dalek

ristretto 和 Curve25519 的纯 Rust 实现的群运算。

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

curve25519-dalek 的目的不是提供任何特定加密协议的实现。相反,那些协议的实现(如 x25519-daleked25519-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位字段算术,都已重写。

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

no_std支持由 Tony Arcieri 贡献。

感谢 Ashley Hauck、Lucas Salibian 和 Manish Goregaokar 的贡献。

依赖项

~0.5–1.3MB
~27K SLoC