#curve25519 #ristretto #ristretto255 #crypto

no-std curve25519-dalek-ng

Ristretto 和 Curve25519 群运算的纯 Rust 实现

6 个稳定版本

使用旧的 Rust 2015

4.1.1 2021 年 10 月 14 日
4.1.0 2021 年 9 月 16 日
4.0.1 2021 年 1 月 28 日
3.0.3 2021 年 1 月 28 日
3.0.2 2021 年 1 月 14 日

#222 in 加密学

Download history 56280/week @ 2024-03-14 60406/week @ 2024-03-21 56157/week @ 2024-03-28 61538/week @ 2024-04-04 60177/week @ 2024-04-11 58759/week @ 2024-04-18 51721/week @ 2024-04-25 51111/week @ 2024-05-02 51038/week @ 2024-05-09 50392/week @ 2024-05-16 61740/week @ 2024-05-23 61037/week @ 2024-05-30 53145/week @ 2024-06-06 57723/week @ 2024-06-13 58737/week @ 2024-06-20 44302/week @ 2024-06-27

224,863 每月下载量
234 软件包中使用 (22 直接使用)

BSD-3-Clause

1MB
26K SLoC

curve25519-dalek-ng

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 曲线算术的速度和安全性优势,而没有与系数相关的抽象不匹配的陷阱。

文档

semver-stable、面向公众的 curve25519-dalek API 在此处有文档:https://docs.rs/curve25519-dalek-ng/。此外,不稳定内部实现细节在此处有文档:https://doc-internal.dalek.rs/curve25519_dalek/

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系列与3.x系列的API几乎完全相同,唯一的区别是更新了rand_core版本。

3.x系列与2.x系列的API几乎完全相同,唯一的区别是更新了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 函数的入口点,而是在其他包中函数的入口点。

该实现是内存安全的,并且不包含任何显著的 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 作为依赖项,并让该包为该原始功能提供最小、以字节数据缓冲区为中心的FFI。

贡献

请参阅 CONTRIBUTING.md

关于

剧透警告:第十二任博士第一次遇见达莱克是在他的第二集全剧集 "Into the Dalek" 中。一个备受折磨的“联合银河抵抗”飞船发现了一个损坏的达莱克,它变成了“好人”,希望杀死所有其他达莱克。博士、克拉拉和一支士兵队伍被缩小并进入了达莱克,博士将其命名为Rusty。他们修复了损坏,但意外地将其恢复到原始状态,导致它大举进攻并警告达莱克舰队叛乱飞船的位置。然而,博士通过将自己的意识与达莱克连接起来,成功地让Rusty回到了之前的状态:Rusty分享了博士对宇宙之美的看法,但也分享了他对达莱克的深深仇恨。Rusty摧毁了其他达莱克并离开了飞船,决心追捕并结束达莱克种族。

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的贡献。

依赖项