Skip to content

Commit

Permalink
highly optimized ed25519 sign bench
Browse files Browse the repository at this point in the history
  • Loading branch information
naftulikay committed Nov 4, 2023
1 parent b4e5616 commit 0bdfaa4
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 7 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ anyhow = "1"
clap = { version = "4", features = ["derive"] }
criterion = "0.5"
nom = "7"
rand = "0.8"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
5 changes: 5 additions & 0 deletions example_crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ publish = false
name = "keygen"
harness = false

[[bench]]
name = "sign"
harness = false

[dependencies]
openssl = { version = "0.10", features = ["vendored"] }
rand.workspace = true

[dev-dependencies]
criterion.workspace = true
15 changes: 9 additions & 6 deletions example_crypto/benches/keygen.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use criterion::{criterion_group, criterion_main, Criterion};
use example_crypto::openssl::keygen::{
keygen, keygen_ed25519, keygen_ed448, keygen_rsa, keygen_x25519, keygen_x448,
};
use example_crypto::openssl::keygen::{keygen_ec, keygen_ed25519, keygen_ed448, keygen_rsa, keygen_x25519, keygen_x448};
use openssl::ec::EcGroup;
use openssl::nid::Nid;

Expand All @@ -16,7 +14,7 @@ pub fn bench_keygen(c: &mut Criterion) {

// ecdsa
c.bench_function("openssl::keygen::secp256", |b| {
b.iter(|| keygen(&secp256k1))
b.iter(|| keygen_ec(&secp256k1))
});

// rsa
Expand All @@ -25,5 +23,10 @@ pub fn bench_keygen(c: &mut Criterion) {
c.bench_function("openssl::keygen::rsa4096", |b| b.iter(|| keygen_rsa(4096)));
}

criterion_group!(benches, bench_keygen);
criterion_main!(benches);
criterion_group!{
name = keygen;
config = Criterion::default();
targets = bench_keygen
}

criterion_main!(keygen);
50 changes: 50 additions & 0 deletions example_crypto/benches/sign.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use criterion::{criterion_group, criterion_main, Criterion};
use example_crypto::openssl::sign::Ed25519Signer;
use rand::{thread_rng, RngCore};
use std::sync::atomic::{AtomicUsize, Ordering};

fn bench_sign(c: &mut Criterion) {
// eddsa
c.bench_function("openssl::sign::ed25519", |b| {
const KEY_COUNT: usize = 256;
const DATA_COUNT: usize = 512;

// build 256 signers
let keys: Vec<Ed25519Signer> = (0..KEY_COUNT)
.into_iter()
.map(|_| Ed25519Signer::random())
.collect();

let data: Vec<[u8; 32]> = (0..DATA_COUNT)
.into_iter()
.map(|_| {
let mut d = [0; 32];
thread_rng().fill_bytes(&mut d);
d
})
.collect();

let (signer_index, data_index) = (AtomicUsize::new(0), AtomicUsize::new(0));

b.iter(|| {
let (current_signer, current_data) = (
signer_index.fetch_add(1, Ordering::AcqRel) % KEY_COUNT,
data_index.fetch_add(1, Ordering::AcqRel) % DATA_COUNT,
);

// get em fast
let _sig = unsafe {
keys.get_unchecked(current_signer)
.sign(data.get_unchecked(current_data))
};
})
});
}

criterion_group! {
name = sign;
config = Criterion::default();
targets = bench_sign
}

criterion_main!(sign);
1 change: 1 addition & 0 deletions example_crypto/src/openssl.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod keygen;
pub mod sign;
2 changes: 1 addition & 1 deletion example_crypto/src/openssl/keygen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub struct KeyPair {
pub public: Vec<u8>,
}

pub fn keygen(group: &EcGroup) -> KeyPair {
pub fn keygen_ec(group: &EcGroup) -> KeyPair {
let private = EcKey::generate(group).unwrap();

KeyPair {
Expand Down
38 changes: 38 additions & 0 deletions example_crypto/src/openssl/sign.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use openssl::pkey::{Id, PKey, Private};
use openssl::sign::Signer;
use rand::{thread_rng, RngCore};

pub struct Ed25519Signer {
key: PKey<Private>,
}

impl Ed25519Signer {
/// Generate a new signer with a randomly generated key.
///
/// All values are legal in EdDSA keys, so it's simply generating 32 bytes from the CSPNG.
pub fn random() -> Self {
// generate 32 bytes of random data on the stack
let key_bytes = {
let mut k = [0; 32];
thread_rng().fill_bytes(&mut k);
k
};

// construct a pkey
let key = PKey::private_key_from_raw_bytes(&key_bytes, Id::ED25519)
.expect("unable to create ed25519 private key");

Self { key }
}

pub fn sign(&self, data: &[u8]) -> [u8; 64] {
let mut sig = [0; 64];

let _signature_length = Signer::new_without_digest(&self.key)
.expect("unable to create signer")
.sign_oneshot(&mut sig, data)
.expect("unable to sign data");

sig
}
}

0 comments on commit 0bdfaa4

Please sign in to comment.