Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ed25519: Add wycheproofs #640

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/workspace.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- run: rustup target add ${{ matrix.target }}
- run: ${{ matrix.deps }}
- run: cargo test --target ${{ matrix.target }} --no-default-features
- run: cargo test --workspace --exclude wycheproof-ed25519-dalek --target ${{ matrix.target }} --no-default-features
- run: cargo test --target ${{ matrix.target }}
- run: cargo test --target ${{ matrix.target }} --all-features
# wycheproof is excluded as --all-features turns on everything in the whole workspace collectively
# ed25519-dalek feature legacy_features cause wycheproof tc 63 & 85 to fail
- run: cargo test --workspace --exclude wycheproof-ed25519-dalek --target ${{ matrix.target }} --all-features

test-nightly:
name: Test Nightly
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
members = [
"curve25519-dalek",
"curve25519-dalek-derive",
"ed25519-dalek",
"ed25519-dalek", "wycheproofs/generate-wycheproofs", "wycheproofs/wycheproof-ed25519-dalek",
"x25519-dalek"
]
resolver = "2"
Expand Down
10 changes: 10 additions & 0 deletions wycheproofs/generate-wycheproofs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "generate-wycheproofs"
version = "0.1.0"
edition = "2021"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe adding publish = false may help because the crate looks primarily for testing and not meant to be used by other people.


[dependencies]
codegen = "0.2.0"
hex = "0.4.3"
itertools = "0.12.1"
wycheproof = "0.5.1"
133 changes: 133 additions & 0 deletions wycheproofs/generate-wycheproofs/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use codegen::Scope;
use itertools::Itertools;
use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
use std::path::Path;

fn usage(code: i32) -> ! {
eprintln!("Usage: cargo run --bin generate-wycheproofs [ed25519|..]");
std::process::exit(code)
}

#[derive(Debug, Eq, PartialEq, Hash, Clone, Ord, PartialOrd)]
enum TestExpectation {
Valid,
Invalid,
Acceptable,
}

impl From<wycheproof::TestResult> for TestExpectation {
fn from(res: wycheproof::TestResult) -> TestExpectation {
match res {
wycheproof::TestResult::Valid => TestExpectation::Valid,
wycheproof::TestResult::Invalid => TestExpectation::Invalid,
wycheproof::TestResult::Acceptable => TestExpectation::Acceptable,
}
}
}

use std::fmt::Display;

mod generator_ed25519 {

use super::*;

#[derive(Debug, Eq, PartialEq, Hash, Clone, Ord, PartialOrd)]
struct Ed25519tc {
tc_id: usize,
input_public_key_hexstring: String,
input_signature_hexstring: String,
input_msg_hexstring: String,
comment: String,
expect: TestExpectation,
}

struct Ed25519tcs {
tc: HashMap<usize, Ed25519tc>,
}

impl Display for Ed25519tcs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
let tcs: Vec<_> = self.tc.iter().sorted().collect();
write!(
f,
"{}",
tcs.into_iter().map(|a| a.1.to_string()).join("\n\n")
)
}
}

impl Display for Ed25519tc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
let mut scope = Scope::new();

let tc_name = format!("wycheproof_tc_{}", self.tc_id);

let test_fn = scope
.new_fn(&tc_name)
.attr("test")
.doc(format!("wycheproofs TC[{}] {}", self.tc_id, self.comment));

test_fn.line(format!(
"super::ed25519_dalek_wycheproof(\"{}\", \"{}\", \"{}\")",
self.input_public_key_hexstring,
self.input_signature_hexstring,
self.input_msg_hexstring
));

match self.expect {
TestExpectation::Valid => {}
_ => {
test_fn.attr("should_panic");
}
}

write!(f, "{}", scope.to_string())
}
}

pub fn run() {
let p = Path::new("./wycheproofs/wycheproof-ed25519-dalek/src");

if !p.exists() {
eprintln!("Run this from top level directory");
usage(2)
}

let mut gen_tests = Ed25519tcs { tc: HashMap::new() };

let test_set =
wycheproof::eddsa::TestSet::load(wycheproof::eddsa::TestName::Ed25519).unwrap();
for test_group in test_set.test_groups {
let wycheproof::EddsaPublic { pk, .. } = test_group.key;
for test in test_group.tests {
gen_tests.tc.insert(
test.tc_id,
Ed25519tc {
tc_id: test.tc_id,
input_public_key_hexstring: hex::encode(pk.clone()),
input_signature_hexstring: hex::encode(test.sig),
input_msg_hexstring: hex::encode(test.msg),
comment: test.comment,
expect: test.result.into(),
},
);
}
}

let full_p = p.join("generated.rs");

let mut file = File::create(full_p).expect("Could not create generated.rs");

file.write_all(gen_tests.to_string().as_bytes())
.expect("Failed to write the generated output.");
}
}

fn main() {
match std::env::args().last().unwrap().as_str() {
"ed25519" => generator_ed25519::run(),
_ => usage(1),
}
}
8 changes: 8 additions & 0 deletions wycheproofs/wycheproof-ed25519-dalek/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "wycheproof-ed25519-dalek"
version = "0.1.0"
edition = "2021"

[dependencies]
ed25519-dalek = { version = "2", path = "../../ed25519-dalek" }
hex = "0.4.3"
Loading
Loading