mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-04 20:24:10 +00:00
ed: Unvendor STROBE (#895)
* Fix bench build * Remove vendored strobe impl and use strobe-rs
This commit is contained in:
parent
bad078de58
commit
fc23dd4a86
6 changed files with 42 additions and 293 deletions
67
Cargo.lock
generated
67
Cargo.lock
generated
|
|
@ -76,12 +76,6 @@ version = "0.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
|
|
@ -144,12 +138,12 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|||
|
||||
[[package]]
|
||||
name = "chacha20"
|
||||
version = "0.10.0-rc.10"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c536927023d1c432e6e23a25ef45f6756094eac2ab460db5fb17a772acdfd312"
|
||||
checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures 0.2.17",
|
||||
"cpufeatures",
|
||||
"rand_core 0.10.0",
|
||||
]
|
||||
|
||||
|
|
@ -217,15 +211,6 @@ version = "0.10.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.3.0"
|
||||
|
|
@ -326,7 +311,7 @@ version = "5.0.0-pre.6"
|
|||
dependencies = [
|
||||
"bincode",
|
||||
"cfg-if",
|
||||
"cpufeatures 0.3.0",
|
||||
"cpufeatures",
|
||||
"criterion",
|
||||
"curve25519-dalek-derive",
|
||||
"digest",
|
||||
|
|
@ -612,7 +597,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures 0.3.0",
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -769,7 +754,7 @@ checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40"
|
|||
dependencies = [
|
||||
"bit-set",
|
||||
"bit-vec",
|
||||
"bitflags 2.10.0",
|
||||
"bitflags",
|
||||
"num-traits",
|
||||
"rand",
|
||||
"rand_chacha",
|
||||
|
|
@ -953,7 +938,7 @@ version = "1.1.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
|
|
@ -1052,7 +1037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures 0.3.0",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
|
|
@ -1087,14 +1072,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "strobe-rs"
|
||||
version = "0.5.4"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a9baee171ea889cfe5333700f0948777b483db8dc805c5c519ffe92e7714783"
|
||||
checksum = "83561175f0a962dea437885589480d216d8741debf853e0d36edd526344fd273"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"keccak",
|
||||
"subtle",
|
||||
"tiny-keccak",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1144,15 +1130,6 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.1"
|
||||
|
|
@ -1336,7 +1313,7 @@ version = "0.244.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"bitflags",
|
||||
"hashbrown 0.15.5",
|
||||
"indexmap",
|
||||
"semver",
|
||||
|
|
@ -1440,7 +1417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.10.0",
|
||||
"bitflags",
|
||||
"indexmap",
|
||||
"log",
|
||||
"serde",
|
||||
|
|
@ -1517,6 +1494,20 @@ name = "zeroize"
|
|||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
||||
dependencies = [
|
||||
"zeroize_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize_derive"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ keccak = { version = "0.2", default-features = false, optional = true }
|
|||
rand_core = { version = "0.10", default-features = false, optional = true }
|
||||
serde = { version = "1.0", default-features = false, optional = true }
|
||||
zeroize = { version = "1.5", default-features = false, optional = true }
|
||||
strobe-rs = { version = "0.13", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
curve25519-dalek = { version = "=5.0.0-pre.6", default-features = false, features = [
|
||||
|
|
@ -60,7 +61,6 @@ serde_json = "1.0"
|
|||
criterion = { version = "0.5", features = ["html_reports"] }
|
||||
hex-literal = "1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
strobe-rs = "0.5"
|
||||
toml = { version = "0.9" }
|
||||
|
||||
[[bench]]
|
||||
|
|
@ -78,7 +78,7 @@ alloc = [
|
|||
"zeroize?/alloc",
|
||||
]
|
||||
|
||||
batch = ["alloc", "dep:keccak", "rand_core"]
|
||||
batch = ["alloc", "dep:keccak", "rand_core", "strobe-rs"]
|
||||
fast = ["curve25519-dalek/precomputed-tables"]
|
||||
digest = ["signature/digest"]
|
||||
# Exposes the hazmat module
|
||||
|
|
|
|||
|
|
@ -14,11 +14,10 @@ mod ed25519_benches {
|
|||
use ed25519_dalek::Signature;
|
||||
use ed25519_dalek::Signer;
|
||||
use ed25519_dalek::SigningKey;
|
||||
use rand_core::prelude::ThreadRng;
|
||||
use rand_core::rng;
|
||||
use getrandom::{SysRng, rand_core::UnwrapErr};
|
||||
|
||||
fn sign(c: &mut Criterion) {
|
||||
let mut csprng: ThreadRng = rng();
|
||||
let mut csprng = UnwrapErr(SysRng);
|
||||
let keypair: SigningKey = SigningKey::generate(&mut csprng);
|
||||
let msg: &[u8] = b"";
|
||||
|
||||
|
|
@ -26,7 +25,7 @@ mod ed25519_benches {
|
|||
}
|
||||
|
||||
fn verify(c: &mut Criterion) {
|
||||
let mut csprng: ThreadRng = rng();
|
||||
let mut csprng = UnwrapErr(SysRng);
|
||||
let keypair: SigningKey = SigningKey::generate(&mut csprng);
|
||||
let msg: &[u8] = b"";
|
||||
let sig: Signature = keypair.sign(msg);
|
||||
|
|
@ -37,7 +36,7 @@ mod ed25519_benches {
|
|||
}
|
||||
|
||||
fn verify_strict(c: &mut Criterion) {
|
||||
let mut csprng: ThreadRng = rng();
|
||||
let mut csprng = UnwrapErr(SysRng);
|
||||
let keypair: SigningKey = SigningKey::generate(&mut csprng);
|
||||
let msg: &[u8] = b"";
|
||||
let sig: Signature = keypair.sign(msg);
|
||||
|
|
@ -58,7 +57,7 @@ mod ed25519_benches {
|
|||
for size in BATCH_SIZES {
|
||||
let name = format!("size={size}");
|
||||
group.bench_function(name, |b| {
|
||||
let mut csprng: ThreadRng = rng();
|
||||
let mut csprng = UnwrapErr(SysRng);
|
||||
let keypairs: Vec<SigningKey> = (0..size)
|
||||
.map(|_| SigningKey::generate(&mut csprng))
|
||||
.collect();
|
||||
|
|
@ -78,7 +77,7 @@ mod ed25519_benches {
|
|||
fn verify_batch_signatures(_: &mut Criterion) {}
|
||||
|
||||
fn key_generation(c: &mut Criterion) {
|
||||
let mut csprng: ThreadRng = rng();
|
||||
let mut csprng = UnwrapErr(SysRng);
|
||||
|
||||
c.bench_function("Ed25519 keypair generation", move |b| {
|
||||
b.iter(|| SigningKey::generate(&mut csprng))
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
//! Batch signature verification.
|
||||
|
||||
mod strobe;
|
||||
mod transcript;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
|
|
|
|||
|
|
@ -1,240 +0,0 @@
|
|||
//! Minimal implementation of (parts of) Strobe.
|
||||
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use keccak::Keccak;
|
||||
|
||||
#[cfg(feature = "zeroize")]
|
||||
use zeroize::Zeroize;
|
||||
|
||||
/// Strobe R value; security level 128 is hardcoded
|
||||
const STROBE_R: u8 = 166;
|
||||
|
||||
const FLAG_I: u8 = 1;
|
||||
const FLAG_A: u8 = 1 << 1;
|
||||
const FLAG_C: u8 = 1 << 2;
|
||||
const FLAG_T: u8 = 1 << 3;
|
||||
const FLAG_M: u8 = 1 << 4;
|
||||
const FLAG_K: u8 = 1 << 5;
|
||||
|
||||
fn transmute_state(st: &mut AlignedKeccakState) -> &mut [u64; 25] {
|
||||
unsafe { &mut *(st as *mut AlignedKeccakState as *mut [u64; 25]) }
|
||||
}
|
||||
|
||||
/// This is a wrapper around 200-byte buffer that's always 8-byte aligned
|
||||
/// to make pointers to it safely convertible to pointers to [u64; 25]
|
||||
/// (since u64 words must be 8-byte aligned)
|
||||
#[derive(Clone)]
|
||||
#[repr(align(8))]
|
||||
struct AlignedKeccakState([u8; 200]);
|
||||
|
||||
#[cfg(feature = "zeroize")]
|
||||
impl Drop for AlignedKeccakState {
|
||||
fn drop(&mut self) {
|
||||
self.0.zeroize();
|
||||
}
|
||||
}
|
||||
|
||||
/// A Strobe context for the 128-bit security level.
|
||||
///
|
||||
/// Only `meta-AD`, `AD`, `KEY`, and `PRF` operations are supported.
|
||||
#[derive(Clone)]
|
||||
pub struct Strobe128 {
|
||||
state: AlignedKeccakState,
|
||||
pos: u8,
|
||||
pos_begin: u8,
|
||||
cur_flags: u8,
|
||||
}
|
||||
|
||||
impl ::core::fmt::Debug for Strobe128 {
|
||||
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
|
||||
// Ensure that the Strobe state isn't accidentally logged
|
||||
write!(f, "Strobe128: STATE OMITTED")
|
||||
}
|
||||
}
|
||||
|
||||
impl Strobe128 {
|
||||
pub fn new(protocol_label: &[u8]) -> Strobe128 {
|
||||
let initial_state = {
|
||||
let mut st = AlignedKeccakState([0u8; 200]);
|
||||
st[0..6].copy_from_slice(&[1, STROBE_R + 2, 1, 0, 1, 96]);
|
||||
st[6..18].copy_from_slice(b"STROBEv1.0.2");
|
||||
Keccak::new().with_f1600(|f1600| f1600(transmute_state(&mut st)));
|
||||
|
||||
st
|
||||
};
|
||||
|
||||
let mut strobe = Strobe128 {
|
||||
state: initial_state,
|
||||
pos: 0,
|
||||
pos_begin: 0,
|
||||
cur_flags: 0,
|
||||
};
|
||||
|
||||
strobe.meta_ad(protocol_label, false);
|
||||
|
||||
strobe
|
||||
}
|
||||
|
||||
pub fn meta_ad(&mut self, data: &[u8], more: bool) {
|
||||
self.begin_op(FLAG_M | FLAG_A, more);
|
||||
self.absorb(data);
|
||||
}
|
||||
|
||||
pub fn ad(&mut self, data: &[u8], more: bool) {
|
||||
self.begin_op(FLAG_A, more);
|
||||
self.absorb(data);
|
||||
}
|
||||
|
||||
pub fn prf(&mut self, data: &mut [u8], more: bool) {
|
||||
self.begin_op(FLAG_I | FLAG_A | FLAG_C, more);
|
||||
self.squeeze(data);
|
||||
}
|
||||
|
||||
pub fn key(&mut self, data: &[u8], more: bool) {
|
||||
self.begin_op(FLAG_A | FLAG_C, more);
|
||||
self.overwrite(data);
|
||||
}
|
||||
}
|
||||
|
||||
impl Strobe128 {
|
||||
fn run_f(&mut self) {
|
||||
self.state[self.pos as usize] ^= self.pos_begin;
|
||||
self.state[(self.pos + 1) as usize] ^= 0x04;
|
||||
self.state[(STROBE_R + 1) as usize] ^= 0x80;
|
||||
Keccak::new().with_f1600(|f1600| f1600(transmute_state(&mut self.state)));
|
||||
self.pos = 0;
|
||||
self.pos_begin = 0;
|
||||
}
|
||||
|
||||
fn absorb(&mut self, data: &[u8]) {
|
||||
for byte in data {
|
||||
self.state[self.pos as usize] ^= byte;
|
||||
self.pos += 1;
|
||||
if self.pos == STROBE_R {
|
||||
self.run_f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn overwrite(&mut self, data: &[u8]) {
|
||||
for byte in data {
|
||||
self.state[self.pos as usize] = *byte;
|
||||
self.pos += 1;
|
||||
if self.pos == STROBE_R {
|
||||
self.run_f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn squeeze(&mut self, data: &mut [u8]) {
|
||||
for byte in data {
|
||||
*byte = self.state[self.pos as usize];
|
||||
self.state[self.pos as usize] = 0;
|
||||
self.pos += 1;
|
||||
if self.pos == STROBE_R {
|
||||
self.run_f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn begin_op(&mut self, flags: u8, more: bool) {
|
||||
// Check if we're continuing an operation
|
||||
if more {
|
||||
assert_eq!(
|
||||
self.cur_flags, flags,
|
||||
"You tried to continue op {:#b} but changed flags to {:#b}",
|
||||
self.cur_flags, flags,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip adjusting direction information (we just use AD, PRF)
|
||||
assert_eq!(
|
||||
flags & FLAG_T,
|
||||
0u8,
|
||||
"You used the T flag, which this implementation doesn't support"
|
||||
);
|
||||
|
||||
let old_begin = self.pos_begin;
|
||||
self.pos_begin = self.pos + 1;
|
||||
self.cur_flags = flags;
|
||||
|
||||
self.absorb(&[old_begin, flags]);
|
||||
|
||||
// Force running F if C or K is set
|
||||
let force_f = 0 != (flags & (FLAG_C | FLAG_K));
|
||||
|
||||
if force_f && self.pos != 0 {
|
||||
self.run_f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for AlignedKeccakState {
|
||||
type Target = [u8; 200];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for AlignedKeccakState {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use strobe_rs::{self, SecParam};
|
||||
|
||||
#[test]
|
||||
fn test_conformance() {
|
||||
let mut s1 = super::Strobe128::new(b"Conformance Test Protocol");
|
||||
let mut s2 = strobe_rs::Strobe::new(b"Conformance Test Protocol", SecParam::B128);
|
||||
|
||||
// meta-AD(b"msg"); AD(msg)
|
||||
|
||||
let msg = [99u8; 1024];
|
||||
|
||||
s1.meta_ad(b"ms", false);
|
||||
s1.meta_ad(b"g", true);
|
||||
s1.ad(&msg, false);
|
||||
|
||||
s2.meta_ad(b"ms", false);
|
||||
s2.meta_ad(b"g", true);
|
||||
s2.ad(&msg, false);
|
||||
|
||||
// meta-AD(b"prf"); PRF()
|
||||
|
||||
let mut prf1 = [0u8; 32];
|
||||
s1.meta_ad(b"prf", false);
|
||||
s1.prf(&mut prf1, false);
|
||||
|
||||
let mut prf2 = [0u8; 32];
|
||||
s2.meta_ad(b"prf", false);
|
||||
s2.prf(&mut prf2, false);
|
||||
|
||||
assert_eq!(prf1, prf2);
|
||||
|
||||
// meta-AD(b"key"); KEY(prf output)
|
||||
|
||||
s1.meta_ad(b"key", false);
|
||||
s1.key(&prf1, false);
|
||||
|
||||
s2.meta_ad(b"key", false);
|
||||
s2.key(&prf2, false);
|
||||
|
||||
// meta-AD(b"prf"); PRF()
|
||||
|
||||
let mut prf1 = [0u8; 32];
|
||||
s1.meta_ad(b"prf", false);
|
||||
s1.prf(&mut prf1, false);
|
||||
|
||||
let mut prf2 = [0u8; 32];
|
||||
s2.meta_ad(b"prf", false);
|
||||
s2.prf(&mut prf2, false);
|
||||
|
||||
assert_eq!(prf1, prf2);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
use super::MERLIN_PROTOCOL_LABEL;
|
||||
use super::strobe::Strobe128;
|
||||
use core::convert::Infallible;
|
||||
use strobe_rs::{SecParam, Strobe};
|
||||
|
||||
fn encode_usize_as_u32(x: usize) -> [u8; 4] {
|
||||
u32::try_from(x).expect("usize too large").to_le_bytes()
|
||||
|
|
@ -37,7 +37,7 @@ fn encode_usize_as_u32(x: usize) -> [u8; 4] {
|
|||
/// Merlin](https://merlin.cool/use/index.html) section.
|
||||
#[derive(Clone)]
|
||||
pub struct Transcript {
|
||||
strobe: Strobe128,
|
||||
strobe: Strobe,
|
||||
}
|
||||
|
||||
impl Transcript {
|
||||
|
|
@ -53,7 +53,7 @@ impl Transcript {
|
|||
/// the Merlin website for more details on why.
|
||||
pub fn new(label: &'static [u8]) -> Transcript {
|
||||
let mut transcript = Transcript {
|
||||
strobe: Strobe128::new(MERLIN_PROTOCOL_LABEL),
|
||||
strobe: Strobe::new(MERLIN_PROTOCOL_LABEL, SecParam::B128),
|
||||
};
|
||||
transcript.append_message(b"dom-sep", label);
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ impl Transcript {
|
|||
/// [rekey_with_witness_bytes]: TranscriptRngBuilder::rekey_with_witness_bytes
|
||||
/// [finalize]: TranscriptRngBuilder::finalize
|
||||
pub struct TranscriptRngBuilder {
|
||||
strobe: Strobe128,
|
||||
strobe: Strobe,
|
||||
}
|
||||
|
||||
impl TranscriptRngBuilder {
|
||||
|
|
@ -183,7 +183,7 @@ impl TranscriptRngBuilder {
|
|||
/// Randomness](https://merlin.cool/transcript/rng.html) section of
|
||||
/// the Merlin website.
|
||||
pub struct TranscriptRng {
|
||||
strobe: Strobe128,
|
||||
strobe: Strobe,
|
||||
}
|
||||
|
||||
impl rand_core::TryRng for TranscriptRng {
|
||||
|
|
|
|||
Loading…
Reference in a new issue