#curve25519 #ristretto #ristretto255 #zero-knowledge-proofs #anonymous-credentials #crypto

no-std sunscreen_curve25519

Rust 语言实现的 ristretto255 和 Curve25519 群运算

2 个版本

使用旧版 Rust 2015

0.8.1 2023 年 9 月 11 日
0.8.0 2023 年 8 月 22 日

#1492 in 加密学

36 每月下载量
用于 6 个 crate (4 个直接使用)

BSD-3-Clause 协议

1MB
26K SLoC

curve25519-dalek-ng

Rust 语言实现的 Ristretto 和 Curve25519 群运算。

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

curve25519-dalek 不旨在提供任何特定加密协议的实现。相反,那些协议的实现(如 x25519-daleked25519-dalek)应使用 curve25519-dalek 作为库。

curve25519-dalek 旨在提供一个干净且安全的 中级 API,用于实现各种基于 ECC 的加密协议,例如密钥协商、签名、匿名凭证、rangeproofs 和零知识证明系统。

特别是,curve25519-dalek 实现了 Ristretto,它从非素阶 Edwards 曲线构建素阶群。这提供了 Edwards 曲线算术的速度和安全优势,而没有与因数相关的抽象不匹配的陷阱。

文档

semver 稳定的、面向公共的 curve25519-dalek API 文档在此处提供。此外,不稳定的内部实现细节在此处提供文档。

curve25519-dalek 文档需要自定义 HTML 标头以包含 KaTeX 进行数学支持。不幸的是,当前 cargo doc 不支持此功能,但可以使用以下方法构建文档:

make doc
make doc-internal

使用

要导入 curve25519-dalek,请将以下内容添加到您项目 Cargo.toml 文件的依赖部分

curve25519-dalek-ng = "4.1"

在不更改代码的情况下切换到之前的 curve25519-dalek crate,请使用以下方法

curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" }

该 crate 在不同的包名下继续 curve25519-dalek 系列的开发。不幸的是,前一个 crate 的维护者控制了 dalek-cryptography GitHub 组织以及 subtlecurve25519-dalek crate,他们通过悄悄移除所有其他共同维护者来夺取了控制权。

4.x 系列的 API 几乎与 3.x 系列完全相同,只是更新了 rand_core 版本。

3.x 系列的 API 几乎与 2.x 系列完全相同,只是更新了 digest 版本。

2.x 系列的 API 几乎与 1.x 系列完全相同,只是

  • 修正了 (可选) serde 功能的数据建模错误,因此当使用 2.x 系列的 serde 实现与 serde-bincode 一起使用时,派生的序列化与常用的 X/Ed25519 格式相匹配;

  • 更新了 rand 版本。

有关更多详细信息,请参阅 CHANGELOG.md

后端和功能

nightly 功能启用仅在 Rust 夜间编译器使用时才可用的功能。特别是,它对于渲染文档和 SIMD 后端是必需的。

曲线算术是使用以下后端之一实现的

  • 使用串行公式和 u64 积的 u32 后端;
  • 使用串行公式和 u128 积的 u64 后端;
  • 使用 并行公式avx2 指令(设置速度记录)的 avx2 后端;
  • 使用 并行公式ifma 指令(设置速度记录)的 ifma 后端;

默认情况下选择 u64 后端。要选择特定的后端,请使用

cargo build --no-default-features --features "std u32_backend"
cargo build --no-default-features --features "std u64_backend"
# Requires nightly, RUSTFLAGS="-C target_feature=+avx2" to use avx2
cargo build --no-default-features --features "std simd_backend"
# Requires nightly, RUSTFLAGS="-C target_feature=+avx512ifma" to use ifma
cargo build --no-default-features --features "std simd_backend"

使用 curve25519-dalek 的 crate 可以代表其用户选择后端,或者公开功能标志以控制 curve25519-dalek 后端。

默认情况下启用 std 功能,但可以使用 --no-default-features 禁用无 std 构建。请注意,这需要使用其中一个 _backend 功能显式选择算术后端。如果没有选择后端,则编译将失败。

安全性

curve25519-dalek 类型被设计为使非法状态无法表示。例如,任何 EdwardsPoint 的实例都保证在 Edwards 曲线上持有一点,任何 RistrettoPoint 的实例都保证在 Ristretto 群中持有有效的点。

所有操作都是使用恒时逻辑实现的(没有秘密相关的分支,没有秘密相关的内存访问),除非明确标记为变时代码。我们相信我们的恒时逻辑至少在 x86_64 目标上被降低为恒时汇编。

为了防止未来编译器优化可能带来的潜在风险,subtle 库在每次条件移动或赋值之前放置了一个优化屏障。更多详细信息可以在 subtle 库的文档 中找到。

一些功能(例如多标量乘法或批量求逆)需要堆分配临时缓冲区。所有可能包含机密数据的堆分配缓冲区在释放前都会显式地清零。

然而,我们并不尝试清零栈数据,原因有两个。首先,这样做不可能正确完成:我们没有控制栈分配,所以无法知道要擦除多少数据。其次,因为 curve25519-dalek 提供了一个中间层 API,正确的开始清零栈数据的位置可能不是在 curve25519-dalek 函数的入口点,而是在其他 crate 中函数的入口点。

实现是内存安全的,不包含任何显著的 unsafe 代码。SIMD 后端内部使用 unsafe 调用 SIMD 内置函数。这些函数被标记为 unsafe 只是因为在不适当的 CPU 上调用它们会导致 SIGILL,但是整个后端只使用适当的 target_feature 编译,因此这种情况不可能发生。

性能

基准测试使用 criterion.rs 运行。

cargo bench --no-default-features --features "std u32_backend"
cargo bench --no-default-features --features "std u64_backend"
# Uses avx2 or ifma only if compiled for an appropriate target.
export RUSTFLAGS="-C target_cpu=native"
cargo bench --no-default-features --features "std simd_backend"

性能是正确性、安全性和清晰性之后的次要目标,但我们的目标是与其他实现具有竞争力。

FFI

不幸的是,我们没有任何计划直接在 curve25519-dalek 中添加 FFI。原因是,我们使用 Rust 功能提供一个维护安全性公理的 API,这些公理在 FFI 边界上无法维护。例如,如上文中 安全性 部分所述,无法构造无效点,如果我们在 FFI 中公开点操作,则情况并非如此。

然而,curve25519-dalek 被设计为一个 中间层 API,旨在实现其他更高层的原语。我们建议在 Rust 中实现更高层原语(签名、PAKE、ZKP 等),将 curve25519-dalek 作为依赖项,并让该 crate 为该原语提供一个最小化、以字节缓冲区为中心的特定 FFI。

贡献

请参阅 CONTRIBUTING.md

关于

剧透警告: 第十二任医生的第一次遇到 Daleks 是在他的第二集全剧 "Into the 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 位字段算术,都已被重写。

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

no_stdzeroize 支持是由 Tony Arcieri 贡献的。

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

依赖关系