#ed25519 #signature #signature-verification #blake3 #ed25519-key #ecc #curve25519

无需std ed25519-dalek-blake3

基于ed25519-dalek分支,将sha512替换为blake3

8个稳定版本

1.0.11 2022年5月10日
1.0.8 2022年2月14日
1.0.6 2021年11月9日
1.0.5 2021年10月25日
1.0.2 2021年5月28日

#1037 in 密码学

每月44次下载

BSD-3-Clause

99KB
949

ed25519-dalek

ed25519密钥生成、签名和验证的Rust快速高效实现。

文档

文档可在此处找到。

安装

要安装,请在项目的Cargo.toml中添加以下内容

[dependencies.ed25519-dalek]
version = "1"

基准测试

在一个运行在3.30 GHz的Intel Skylake i9-7900X处理器上,没有TurboBoost的情况下,此代码实现了以下性能基准

!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ cargo bench
   Compiling ed25519-dalek v0.7.0 (file:///home/isis/code/rust/ed25519-dalek)
    Finished release [optimized] target(s) in 3.11s
      Running target/release/deps/ed25519_benchmarks-721332beed423bce

Ed25519 signing                     time:   [15.617 us 15.630 us 15.647 us]
Ed25519 signature verification      time:   [45.930 us 45.968 us 46.011 us]
Ed25519 keypair generation          time:   [15.440 us 15.465 us 15.492 us]

通过启用avx2后端(在具有兼容微架构的机器上),签名验证的性能得到了大幅提升

!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ export RUSTFLAGS=-Ctarget_cpu=native
∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ cargo bench --features=avx2_backend
   Compiling ed25519-dalek v0.7.0 (file:///home/isis/code/rust/ed25519-dalek)
    Finished release [optimized] target(s) in 4.28s
      Running target/release/deps/ed25519_benchmarks-e4866664de39c84d
Ed25519 signing                     time:   [15.923 us 15.945 us 15.967 us]
Ed25519 signature verification      time:   [33.382 us 33.411 us 33.445 us]
Ed25519 keypair generation          time:   [15.246 us 15.260 us 15.275 us]

与之相比,Golang中的等效软件包表现如下

!isisⒶmistakenot:(master *=)~/code/go/src/github.com/agl/ed25519 ∴ go test -bench .
BenchmarkKeyGeneration     30000             47007 ns/op
BenchmarkSigning           30000             48820 ns/op
BenchmarkVerification      10000            119701 ns/op
ok      github.com/agl/ed25519  5.775s

使密钥生成和签名平均快2倍,验证快2.5-3倍(取决于avx2的可用性)。当然,这只是我的机器,这些结果——远远不是严格的——应该带着一撮盐来对待。

将其转换为大致的周期计数:我们乘以3.3的系数,将纳秒转换为在3300 MHz CPU上的每秒周期数,验证为110256周期,签名为52618周期,这可以与手动优化的汇编实现相媲美。

此外,如果您使用的是rand包中的CSPRNG,nightly特性将启用那里的u128/i128特性,从而可能提高性能。

如果你的协议或应用能够对签名进行批量验证,那么 verify_batch() 函数将显著提高性能。在前面提到的英特尔Skylake i9-7900X上,验证96个签名的批处理需要1.7673毫秒。这相当于每个签名验证大约18.4094微秒,或大约60750个周期,比原始论文中给出的批量验证速度快了一倍以上(这很可能不是一个公平的比较,因为那是一台Nehalem机器)。测试名称中/后面的数字指的是批处理的大小

!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ export RUSTFLAGS=-Ctarget_cpu=native
∃!isisⒶmistakenot:(master *=)~/code/rust/ed25519-dalek ∴ cargo bench --features=avx2_backend batch
   Compiling ed25519-dalek v0.8.0 (file:///home/isis/code/rust/ed25519-dalek)
    Finished release [optimized] target(s) in 34.16s
      Running target/release/deps/ed25519_benchmarks-cf0daf7d68fc71b6
Ed25519 batch signature verification/4   time:   [105.20 us 106.04 us 106.99 us]
Ed25519 batch signature verification/8   time:   [178.66 us 179.01 us 179.39 us]
Ed25519 batch signature verification/16  time:   [325.65 us 326.67 us 327.90 us]
Ed25519 batch signature verification/32  time:   [617.96 us 620.74 us 624.12 us]
Ed25519 batch signature verification/64  time:   [1.1862 ms 1.1900 ms 1.1943 ms]
Ed25519 batch signature verification/96  time:   [1.7611 ms 1.7673 ms 1.7742 ms]
Ed25519 batch signature verification/128 time:   [2.3320 ms 2.3376 ms 2.3446 ms]
Ed25519 batch signature verification/256 time:   [5.0124 ms 5.0290 ms 5.0491 ms]

正如你所见,每个机器都有一个最佳批处理大小,因此你可能会想要在你的目标CPU上测试基准测试以发现最佳大小。对于这台机器,每批大约100个签名是最佳选择

此外,多亏了Rust,这个实现既有类型安全也有内存安全。它也比能阅读qhasm的人更容易被更多人阅读,使其更容易审计。我们认为,最终,这些特性——结合速度——比仅仅周期数更有价值。

关于签名可变性的说明

本库生成的签名是可变的,正如在原始论文中所讨论的

尽管我们的Signature结构体的标量组件严格来说不是可变的,因为在从字节串反序列化Signature时放置了缩减检查,但对于这个crate中的所有类型的签名,仍然存在由于群元素组件可能导致的潜在可变性。

我们可以通过乘以曲线系数来消除这种可变性属性,但这会使我们的实现不符合现有每个实现的行为。截至本文写作时,RFC 8032,“Edwards-Curve数字签名算法(EdDSA)”,建议进行更强的检查。虽然我们同意应该进行更强的检查,但我们的观点是,一个人不应该在十年后改变“ed25519验证”的定义,从而与每个其他实现不兼容。

但是,如果你需要这个,请参阅verify_strict()函数的文档,该函数对群元素进行了全面检查。此功能默认可用。

如果出于某种原因——虽然我们强烈建议不要这样做——你需要符合原始的ed25519签名规范,如上文的摘录所示,你可以通过--features='legacy_compatibility'禁用标量可变性检查。我们强烈反对这样做。

legacy_compatibility功能

默认情况下,这个库在签名反序列化时对签名字段的标量组件的可变性执行更严格的检查。这个更严格的检查是s < \ell,其中\ell是基点的阶,这是由RFC 8032规定的。然而,该RFC是在原始论文十年后标准化的,正如上面所述,通常错误地声称可变性无关紧要。

因此,大多数ed25519实现仅执行有限的、更复杂的检查,即标量的最高三位未设置。如果您需要与旧实现兼容,包括

  • ed25519-donna
  • Golang的/x/crypto ed25519
  • libsodium(仅当使用-DED25519_COMPAT构建时)
  • NaCl的“ref”实现
  • 可能还有许多其他实现

然后启用 ed25519-daleklegacy_compatibility 功能。请注意并提前警告,这样做允许签名可变,意味着对于相同的消息,可能存在两个不同且“有效”的签名,这对于许多环境来说都是极其危险的,包括但不限于身份验证协议和加密货币交易。

verify_strict() 函数

签名的标量分量不是唯一可能引起签名可变的来源。用于签名验证的公钥和签名中的群元素分量也都是可变的,因为它们可能包含由于曲线25519群不是素数阶但有一个小的系数为8的小扭分量。

如果您还想消除这种签名可变性的来源,请查阅 verify_strict() 函数的文档

关于随机数生成的说明

原始论文的规范和RFC8032的标准化并没有精确地说明如何生成随机数,除了使用一个密码学安全的随机数生成器(CSPRNG)。特别是在签名验证的情况下,安全证明依赖于盲因子/随机数的唯一性,因此这些随机样本必须对对手来说是不可预测的。正因为如此,当前许多密码学家普遍认为,选择合成随机数更安全。

为了解释合成随机数,我们首先应该解释 ed25519-dalek 如何处理生成确定性随机数。这种模式默认是禁用的,因为这种模式将用户暴露于故障攻击的风险,其中对手控制了批量验证的所有输入(即公钥、签名和消息),可以以专门的方式制作它们,例如诱导故障(例如,在RAM中错误地翻转位,过热处理器等)。在确定性模式下,我们通过创建一个基于公输入的Fiat-Shamir变换的PRNG来为PRNG生成种子,该PRNG生成我们的盲因子/随机数。这种模式对于需要强大可审计性保证的协议以及没有访问到安全系统/芯片提供的随机数的协议可能很有用。可以通过 --features='batch_deterministic' 启用此功能。请注意,我们不支持确定性签名,因为其中存在许多陷阱,包括意外重复使用随机数可能会泄露秘密密钥。

在默认模式下,我们像上面在完全确定性模式下做的那样,但是基于系统/芯片提供的随机数额外推动底层keccak-f1600函数(用于基于提供的基于转写的PRNG)向前。这提供了合成随机数,即基于确定性和非确定性数据的随机数。这样做的原因是为了防止不良的种子系统RNG破坏签名验证方案的安全性。

特性

#![no_std]

这个库旨在符合 #![no_std]。如果需要批量验证(--features='batch'),请启用 stdalloc 特性之一。

夜间编译器

为了使您的应用程序在默认情况下启用夜间功能构建 ed25519-dalek,请执行以下操作

[dependencies.ed25519-dalek]
version = "1"
features = ["nightly"]

要在有人使用 cargo build --features="nightly" 构建时,使您的应用程序启用夜间功能,请将以下内容添加到 Cargo.toml

[features]
nightly = ["ed25519-dalek/nightly"]

Serde

要启用 serde 支持,请使用 ed25519-dalekserde 功能进行构建。

(微)架构特定后端

默认情况下,ed25519-dalek 会构建针对 curve25519-daleku64_backend 功能,该功能使用 Rust 的 i128 功能,以大约是 u32_backend 功能两倍的速度实现。然而,当针对 32 位系统时,您可能希望使用 cargo build --no-default-features --features="u32_backend" 进行编译。如果您正在为具有 avx2 指令的机器构建,还有实验性的 simd_backend,目前包括 avx2 或 avx512 后端。要使用它们,请使用以下命令进行编译:RUSTFLAGS="-C target_cpu=native" cargo build --no-default-features --features="simd_backend"

批量签名验证

通过 batch 功能提供了批量签名验证的标准变体(即使用许多不同公钥在许多不同消息上生成的许多签名)。它使用如上所述的合成随机性。

确定性批量签名验证

可以通过 batch_deterministic 功能启用与上述相同的批量签名验证概念,但具有纯确定性随机性。

依赖项

~3.5–5.5MB
~120K SLoC