#curve25519 #ristretto #curve-point #ristretto255 #crypto

无需std curve25519-elligator2

ristretto255和Curve25519群运算的纯Rust实现

3个版本

0.1.0-alpha.22024年7月26日
0.1.0-alpha.12024年6月26日

244密码学

Download history 318/week @ 2024-06-24 94/week @ 2024-07-01 118/week @ 2024-07-22 18/week @ 2024-07-29

136 每月下载量

BSD-3-Clause

1.5MB
27K SLoC

curve25519-elligator2 CI

这是一个为了方便而创建的分支

这个分支包含一个等待被合并到主流 curve25519-dalek crate的 elligator2 实现。这个crate存在是为了在过渡期间使用。因此,这个crate

  1. 可能会更改其API以符合上游源的需求
  2. 如果功能被合并到上游源,它将被撤回。

使用

要导入 curve25519-elligator2,请在项目的 Cargo.toml 依赖部分添加以下内容

curve25519-elligator2 = "0.1.0-alpha.2"

以下是底层 curve25519-dalek crate 的文档。



curve25519-dalek CI

dalek-cryptography logo: a dalek with edwards curves as sparkles coming out of its radar-schnozzley blaster thingies

这是Ristretto和Curve25519群运算的纯Rust实现。

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

curve25519-dalek 并不旨在提供任何特定加密协议的实现。相反,这些协议的实现(如 x25519-daleked25519-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_baseRistrettoPoint::mul_base 的速度提高了 ~4 倍,但代码大小增加了 ~30KB。
rand_core 启用 Scalar::randomRistrettoPoint::random。这是一个可选依赖项,其版本不受 SemVer 的约束。有关更多详细信息,请参见 以下内容
digest 启用 RistrettoPoint::{from_hash, hash_from_bytes}Scalar::{from_hash, hash_from_bytes}。这是一个可选依赖项,其版本不受 SemVer 的约束。有关更多详细信息,请参见 以下内容
serde 启用所有点和标量类型的 serde 序列化/反序列化。
legacy_compatibility 启用 Scalar::from_bits,允许用户构建未简化的标量,其算术是损坏的。除非您知道自己在做什么,否则不要使用此功能。
group 启用外部 groupff 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 策略
  • 使 digestrand_core 成为可选功能
  • 删除 stdnightly 功能
  • 替换后端选择 - 请参阅 CHANGELOG.md后端
  • 用常量 Scalar::{ZERO, ONE} 替换方法 Scalar::{zero, one}
  • Scalar::from_canonical_bytes 现在返回 CtOption
  • Scalar::is_canonical 现在返回 Choice
  • 删除 Scalar::from_bytes_clampedScalar::reduce
  • 废弃并使用 legacy_compatibility 功能门禁 Scalar::from_bits
  • 废弃 EdwardsPoint::hash_from_bytes 并将其重命名为 EdwardsPoint::nonspec_map_to_curve
  • 当使用 EdwardsBasepointTableRistrettoBasepointTable 时,需要包含一个新特性,use curve25519_dalek::traits::BasepointTable

此版本还对依赖项进行了大量的更新和放宽,以解决上游构建问题。

后端

曲线算术由以下后端之一实现和使用

后端 选择 实现 位 / 字大小
serial 自动 一个优化、非并行实现 3264
fiat 手动 来自 fiat-crypto 的形式验证字段算术 3264
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 将根据构建目标自动选择 fiatserial 后端的字大小。例如,为 64 位机器构建时,如果选择了 serialfiat 后端,将自动选择默认的 64 位字大小。

在某些目标上,可能需要覆盖字大小以获得更好的性能。可以通过设置环境变量覆盖 serialfiat 的字大小:

RUSTFLAGS='--cfg curve25519_dalek_bits="SIZE"'

SIZE3264。如上所述,这也可以放在 ~/.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 依赖项 groupdigestrand_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 位字段算术,都已重写。

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

no_stdzeroize 的支持由 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