Docs.rs + README changes for 2.x (#241)

This commit is contained in:
pinkforest(she/her)
2023-01-27 17:06:24 +11:00
committed by GitHub
parent 861784f57e
commit 928d6d15f8
5 changed files with 121 additions and 4375 deletions

View File

@@ -14,13 +14,11 @@ description = "Fast and efficient ed25519 EdDSA key generations, signing, and ve
exclude = [ ".gitignore", "TESTVECTORS", "VALIDATIONVECTORS", "res/*" ]
rust-version = "1.60"
[badges]
travis-ci = { repository = "dalek-cryptography/ed25519-dalek", branch = "master"}
[package.metadata.docs.rs]
# Disabled for now since this is borked; tracking https://github.com/rust-lang/docs.rs/issues/302
# rustdoc-args = ["--html-in-header", ".cargo/registry/src/github.com-1ecc6299db9ec823/curve25519-dalek-0.13.2/rustdoc-include-katex-header.html"]
rustdoc-args = ["--cfg", "docsrs"]
rustdoc-args = [
"--html-in-header", "docs/assets/rustdoc-include-katex-header.html",
"--cfg", "docsrs",
]
features = ["nightly", "batch", "pkcs8"]
[dependencies]

223
README.md
View File

@@ -3,117 +3,148 @@
Fast and efficient Rust implementation of ed25519 key generation, signing, and
verification in Rust.
# Documentation
# Use
Documentation is available [here](https://docs.rs/ed25519-dalek).
# Installation
To install, add the following to your project's `Cargo.toml`:
To use, add the following to your project's `Cargo.toml`:
```toml
[dependencies.ed25519-dalek]
version = "1"
```
# Minimum Supported Rust Version
# Feature Flags
This crate requires Rust 1.60.0 at a minimum. Older 1.x releases of this crate supported an MSRV of 1.41.
This crate is `#[no_std]` compatible with `default-features = false`
In the future, MSRV changes will be accompanied by a minor version bump.
| Feature | Default? | Description |
| :--- | :--- | :--- |
| `alloc` | ✓ | Enables features that require dynamic heap allocation |
| `std` | ✓ | std::error::Error types |
| `zeroize` | ✓ | Enables `Zeroize` for `SigningKey` |
| `asm` | | Assembly implementation of SHA-2 compression functions |
| `batch` | | Batch verification. Requires `alloc` |
| `digest` | | TODO |
| `legacy_compatibility` | | See: A Note on Signature Malleability |
| `pkcs8` | | PKCS#8 Support |
| `pem` | | PEM Support |
| `rand_core` | | TODO |
# Changelog
# Major Changes
See [CHANGELOG.md](CHANGELOG.md) for a list of changes made in past version of this crate.
# Benchmarks
## 2.0.0 Breaking Changes
On an Intel Skylake i9-7900X running at 3.30 GHz, without TurboBoost, this code achieves
the following performance benchmarks:
* Update the MSRV from 1.41 to 1.60
* `batch` is now `batch_deterministic`
* Removed `ExpandedSecretKey` API
* [curve25519-backend selection] is more automatic
∃!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
[curve25519-backend selection]: https://github.com/dalek-cryptography/curve25519-dalek/#backends
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]
# Documentation
By enabling the avx2 backend (on machines with compatible microarchitectures),
the performance for signature verification is greatly improved:
Documentation is available [here](https://docs.rs/ed25519-dalek).
∃!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]
# Policies
In comparison, the equivalent package in Golang performs as follows:
All on-by-default features of this library are covered by semantic versioning (SemVer)
∃!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
SemVer exemptions are outlined below for MSRV and public API.
Making key generation and signing a rough average of 2x faster, and
verification 2.5-3x faster depending on the availability of avx2. Of course, this
is just my machine, and these results—nowhere near rigorous—should be taken
with a handful of salt.
## Minimum Supported Rust Version
Translating to a rough cycle count: we multiply by a factor of 3.3 to convert
nanoseconds to cycles per second on a 3300 Mhz CPU, that's 110256 cycles for
verification and 52618 for signing, which is competitive with hand-optimised
assembly implementations.
| Releases | MSRV |
| :--- | :--- |
| 2.x | 1.60 |
| 1.x | 1.41 |
MSRV changes will be accompanied by a minor version bump.
## Public API SemVer Exemptions
Breaking changes to SemVer exempted components affecting the public API will be accompanied by some version bump.
Below are the specific policies:
| Releases | Public API Component(s) | Policy |
| :--- | :--- | :--- |
| 2.x | Dependencies `digest`, `pkcs8` and `rand_core` | Minor SemVer bump |
## Safety
This crate does not require any unsafe and forbids all unsafe in-crate outside tests.
# Performance
Performance is a secondary goal behind correctness, safety, and clarity, but we
aim to be competitive with other implementations.
## Benchmarks
Benchmarks are run using [criterion.rs](https://github.com/japaric/criterion.rs):
```sh
cargo bench --features "batch"
# Uses avx2 or ifma only if compiled for an appropriate target.
export RUSTFLAGS='--cfg curve25519_dalek_backend="simd" -C target_cpu=native'
cargo +nightly bench --features "batch"
```
On an Intel 10700K running at stock comparing between the `curve25519-dalek` backends.
| Benchmark | u64 | simd +avx2 | fiat |
| :--- | :---- | :--- | :--- |
| signing | 15.017 µs | 13.906 µs -7.3967% | 15.877 µs +14.188% |
| signature verification | 40.144 µs | 25.963 µs -35.603% | 42.118 µs +62.758% |
| strict signature verification | 41.334 µs | 27.874 µs -32.660% | 43.985 µs +57.763% |
| batch signature verification/4 | 109.44 µs | 81.778 µs -25.079% | 117.80 µs +43.629% |
| batch signature verification/8 | 182.75 µs | 138.40 µs -23.871% | 195.86 µs +40.665% |
| batch signature verification/16 | 328.67 µs | 251.39 µs -23.744% | 351.55 µs +39.901% |
| batch signature verification/32 | 619.49 µs | 477.36 µs -23.053% | 669.41 µs +39.966% |
| batch signature verification/64 | 1.2136 ms | 936.85 µs -22.543% | 1.3028 ms +38.808% |
| batch signature verification/96 | 1.8677 ms | 1.2357 ms -33.936% | 2.0552 ms +66.439% |
| batch signature verification/128| 2.3281 ms | 1.5795 ms -31.996% | 2.5596 ms +61.678% |
| batch signature verification/256| 4.1868 ms | 2.8864 ms -31.061% | 4.6494 ms +61.081% |
| keypair generation | 13.973 µs | 13.108 µs -6.5062% | 15.099 µs +15.407% |
Additionally, if you're using a CSPRNG from the `rand` crate, the `nightly`
feature will enable `u128`/`i128` features there, resulting in potentially
faster performance.
If your protocol or application is able to batch signatures for verification,
the `verify_batch()` function has greatly improved performance. On the
aforementioned Intel Skylake i9-7900X, verifying a batch of 96 signatures takes
1.7673ms. That's 18.4094us, or roughly 60750 cycles, per signature verification,
more than double the speed of batch verification given in the original paper
(this is likely not a fair comparison as that was a Nehalem machine).
The numbers after the `/` in the test name refer to the size of the batch:
## Batch Performance
∃!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]
If your protocol or application is able to batch signatures for verification,
the `verify_batch()` function has greatly improved performance.
As you can see, there's an optimal batch size for each machine, so you'll likely
want to test the benchmarks on your target CPU to discover the best size. For
this machine, around 100 signatures per batch is the optimum:
want to test the benchmarks on your target CPU to discover the best size.
![](https://github.com/dalek-cryptography/ed25519-dalek/blob/master/res/batch-violin-benchmark.svg)
## (Micro)Architecture Specific Backends
Additionally, thanks to Rust, this implementation has both type and memory
safety. It's also easily readable by a much larger set of people than those who
can read qhasm, making it more readily and more easily auditable. We're of
the opinion that, ultimately, these features—combined with speed—are more
valuable than simply cycle counts alone.
`ed25519-dalek` uses the backends from the `curve25519-dalek` crate.
By default the serial backend is used and depending on the target
platform either the 32 bit or the 64 bit serial formula is automatically used.
To address variety of usage scenarios various backends are available that
include hardware optimisations as well as a formally verified fiat crypto
backend that does not use any hardware optimisations.
These backends can be overriden with various configuration predicates (cfg)
Please see the [curve25519_dalek backend documentation](https://docs.rs/curve25519-dalek/latest/curve25519_dalek).
# Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md)
# A Note on Signature Malleability
The signatures produced by this library are malleable, as discussed in
[the original paper](https://ed25519.cr.yp.to/ed25519-20110926.pdf):
![](https://github.com/dalek-cryptography/ed25519-dalek/blob/master/res/ed25519-malleability.png)
![](https://cdn.jsdelivr.net/gh/dalek-cryptography/ed25519-dalek/docs/assets/ed25519-malleability.png)
While the scalar component of our `Signature` struct is strictly *not*
malleable, because reduction checks are put in place upon `Signature`
@@ -175,51 +206,7 @@ prime order, but having a small cofactor of 8.
If you wish to also eliminate this source of signature malleability, please
review the
[documentation for the `verify_strict()` function](https://doc.dalek.rs/ed25519_dalek/struct.PublicKey.html#method.verify_strict).
# Features
## #![no_std]
This library aims is fully `#![no_std]` compliant. No features need to be
enabled or disabled to suppose no-std.
## Nightly Compilers
To cause your application to build `ed25519-dalek` with the nightly feature
enabled by default, instead do:
```toml
[dependencies.ed25519-dalek]
version = "1"
features = ["nightly"]
```
To cause your application to instead build with the nightly feature enabled
when someone builds with `cargo build --features="nightly"` add the following
to the `Cargo.toml`:
```toml
[features]
nightly = ["ed25519-dalek/nightly"]
```
## Serde
To enable [serde](https://serde.rs) support, build `ed25519-dalek` with the
`serde` feature.
## (Micro)Architecture Specific Backends
By default, `ed25519-dalek` builds against `curve25519-dalek`'s `u64_backend`
feature, which uses Rust's `i128` feature to achieve roughly double the speed as
the `u32_backend` feature. When targetting 32-bit systems, however, you'll
likely want to compile with `cargo build --no-default-features
--features="u32_backend"`. If you're building for a machine with avx2
instructions, there's also the experimental `simd_backend`s, currently
comprising either avx2 or avx512 backends. To use them, compile with
`RUSTFLAGS="-C target_cpu=native" cargo build --no-default-features
--features="simd_backend"`
[documentation for the `verify_strict()` function](https://docs.rs/ed25519-dalek/latest/ed25519_dalek/struct.PublicKey.html#method.verify_strict).
## Batch Signature Verification

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@@ -0,0 +1,12 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.3/dist/katex.min.css" integrity="sha384-Juol1FqnotbkyZUT5Z7gUPjQ9gzlwCENvUZTpQBAPxtusdwFLRy382PSDx5UUJ4/" crossorigin="anonymous">
<!-- The loading of KaTeX is deferred to speed up page rendering -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.3/dist/katex.min.js" integrity="sha384-97gW6UIJxnlKemYavrqDHSX3SiygeOwIZhwyOKRfSaf0JWKRVj9hLASHgFTzT+0O" crossorigin="anonymous"></script>
<!-- To automatically render math in text elements, include the auto-render extension: -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.3/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"
onload="renderMathInElement(document.body);"></script>
<style>
.katex { font-size: 1em !important; }
</style>

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 511 KiB