Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

ed25519-dalek (NEM implementation)

Fast and efficient Rust implementation of ed25519 key generation, signing, and verification in Rust.

Documentation

Documentation is available here.

Benchmarks

On an Intel Skylake i9-7900X running at 3.30 GHz, without TurboBoost, this code achieves the following performance benchmarks:

∃!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]

By enabling the avx2 backend (on machines with compatible microarchitectures), the performance for signature verification is greatly improved:

∃!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]

In comparison, the equivalent package in Golang performs as follows:

∃!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

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.

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.

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:

∃!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]

As you can see, there's an optimal batch size for each machine, so you'll likely want to your the benchmarks on your target CPU to discover the best size. For this machine, around 100 signatures per batch is the optimum:

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.

A Note on Signature Malleability

The signatures produced by this library are malleable, as discussed in the original paper:

We could eliminate the malleability property by multiplying by the curve cofactor, however, this would cause our implementation to not match the behaviour of every other implementation in existence. As of this writing, RFC 8032, "Edwards-Curve Digital Signature Algorithm (EdDSA)," advises that the stronger check should be done. While we agree that the stronger check should be done, it is our opinion that one shouldn't get to change the definition of "ed25519 verification" a decade after the fact, breaking compatibility with every other implementation.

In short, if malleable signatures are bad for your protocol, don't use them. Consider using a curve25519-based Verifiable Random Function (VRF), such as Trevor Perrin's VXEdDSA, instead. We plan to eventually support VXEdDSA in curve25519-dalek.

Installation

To install, add the following to your project's Cargo.toml:

[dependencies]
ed25519-dalek = {git = "https://github.com/namuyan/ed25519-dalek"}

Then, in your library or executable source, add:

extern crate ed25519_dalek;

To use for python:

pip3 install --user nem_ed25519_rust
import nem_ed25519_rust
 
# keypair generation
sec, pub = nem_ed25519_rust.generate_keypair()
print("sk", sec.hex())
print("pk", pub.hex())
 
# message signature
msg = b"hello world, rust-python combination"
sig = nem_ed25519_rust.sign(msg, sec)
print("sig", sig.hex())
nem_ed25519_rust.verify(msg, sig, pub)
 
# message encryption
sec_other, pub_other = nem_ed25519_rust.generate_keypair()
enc = nem_ed25519_rust.encrypt(sec, pub_other, msg)
print("enc", enc.hex())
dec = nem_ed25519_rust.decrypt(sec_other, pub, enc).unwrap()
print("dec", dec)

Features

To cause your application to build ed25519-dalek with the nightly feature enabled by default, instead do:

[dependencies]
ed25519-dalek = {git = "https://github.com/namuyan/ed25519-dalek", 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:

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

To enable serde support, build ed25519-dalek with:

[dependencies]
ed25519-dalek = {git = "https://github.com/namuyan/ed25519-dalek", features = ["serde"]}

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 avx2_backend. To use it, compile with RUSTFLAGS="-C target_cpu=native" cargo build --no-default-features --features="avx2_backend"

Release files for nem-ed25519-rust 1.0.0rc4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nem-ed25519-rust 1.0.0rc4
File Size Uploaded
nem-ed25519-rust-1.0.0rc4.tar.gz 26.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nem-ed25519-rust 1.0.0rc4
File Interpreter ABI Platform
nem_ed25519_rust-1.0.0rc4-cp36-cp36m-win_amd64.whl CPython 3.6 CPython 3.6 pymalloc Windows x86-64 Details

Total release size:237.1 kB

Release files / nem-ed25519-rust-1.0.0rc4.tar.gz

Download URL nem-ed25519-rust-1.0.0rc4.tar.gz
Size 26.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a7598f0fb5aa8b1d6c4a1d7b2fe624aaef02c4a02c76dc1254953534411caadb
BLAKE2b-256 checksum
How to use checksums
43fc5d1b68c234931bbed60797f7295f2d47367a90db07346af63e4d514d7b31
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.13.0 pkginfo/1.5.0.1 requests/2.11.1 setuptools/40.8.0 requests-toolbelt/0.8.0 tqdm/4.19.5 CPython/3.6.0

Release files / nem_ed25519_rust-1.0.0rc4-cp36-cp36m-win_amd64.whl

Download URL nem_ed25519_rust-1.0.0rc4-cp36-cp36m-win_amd64.whl
Size 211.1 kB
Tags CPython 3.6 CPython 3.6 pymalloc Windows x86-64
SHA-256 checksum
How to use checksums
e5b564845d93c5a5e9fde04e4890b549e542576c2253837db424da680588b66a
BLAKE2b-256 checksum
How to use checksums
b10876e4547c2acd363dbe4c6a83aaf7c3e766d7f614878aeffa6e5956e70970
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.13.0 pkginfo/1.5.0.1 requests/2.11.1 setuptools/40.8.0 requests-toolbelt/0.8.0 tqdm/4.19.5 CPython/3.6.0

Release history Release notifications | RSS feed

This release

1.0.0rc4 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page