3个版本
使用旧的Rust 2015
0.1.2 | 2019年4月12日 |
---|---|
0.1.1 | 2019年4月12日 |
0.1.0 | 2019年3月23日 |
#2116 in 密码学
78KB
838 行
ed25519-dalek

在Rust中快速高效地实现ed25519密钥生成、签名和验证。
文档
文档可在 此处 获取。
基准测试
在一个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的可用性。当然,这只是我的机器,这些结果——远非严谨——应该带有一些盐。
换算成粗略的周期数:我们在3300 MHz CPU上以3.3的系数将纳秒转换为每秒周期数,验证为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的人阅读,使其更容易审计。我们认为,最终,这些功能——与速度相结合——比仅仅周期数更有价值。
关于签名可变形性的说明
这个库生成的签名是可变形的,正如在原始论文中所讨论的
我们可以通过乘以曲线特征因子来消除可变形性属性,但是这将导致我们的实现不会与现有的每个实现相匹配。截至本文撰写时,RFC 8032,“爱德华曲线数字签名算法(EdDSA)”,建议进行更强的检查。虽然我们同意应该进行更强的检查,但我们认为,不应该在十年后更改“ed25519验证”的定义,从而与每个其他实现不兼容。
简而言之,如果可变形性签名对您的协议不利,请不要使用它们。考虑使用基于curve25519的可验证随机函数(VRF),例如Trevor Perrin的VXEdDSA。我们计划最终在curve25519-dalek中支持VXEdDSA。
安装
要安装,请在项目的 Cargo.toml
中添加以下内容
[dependencies.ed25519-dalek]
version = "1"
然后,在您的库或可执行源文件中添加
extern crate ed25519_dalek;
功能
为了使应用程序默认启用nightly功能构建 ed25519-dalek
,请改为
[dependencies.ed25519-dalek]
version = "1"
features = ["nightly"]
要使应用程序在某人使用 cargo build --features="nightly"
时启用nightly功能,请将以下内容添加到 Cargo.toml
[features]
nightly = ["ed25519-dalek/nightly"]
要启用 serde 支持,使用以下方式构建 ed25519-dalek
[dependencies.ed25519-dalek]
version = "1"
features = ["serde"]
默认情况下,ed25519-dalek
会针对curve25519-dalek
的u64_backend
特性进行编译,该特性使用Rust的i128
特性,使速度大约提高一倍,相对于u32_backend
特性。然而,当针对32位系统进行编译时,您可能希望使用以下命令进行编译:cargo build --no-default-features --features="u32_backend"
。如果您为具有avx2指令的机器进行编译,还可以使用实验性的avx2_backend
。要使用它,请使用以下命令进行编译:RUSTFLAGS="-C target_cpu=native" cargo build --no-default-features --features="avx2_backend"
依赖项
~3MB
~58K SLoC