diff --git a/Cargo.lock b/Cargo.lock index a5cb8b40..cfc14ea0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2234,6 +2234,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b86f5297f0f04d08cabaa0f6bff7cb6aec4d9c3b49d87990d63da9d9156a8c3" dependencies = [ + "ed25519-dalek", "p256", "p384", "p521", diff --git a/Cargo.toml b/Cargo.toml index 75f5b5d0..06b0fa71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ walkdir = "2.5.0" [dev-dependencies] pretty_assertions = "1.4.1" -ssh-key = "0.6.0" +ssh-key = { version = "0.6.0", features = ["ed25519"] } tempfile = "3.24.0" [dev-dependencies.sequoia-openpgp] diff --git a/src/pgp.rs b/src/pgp.rs index 10062b9b..45054dc6 100644 --- a/src/pgp.rs +++ b/src/pgp.rs @@ -102,7 +102,7 @@ fn gpg_v4_signatures_can_be_verified() { } #[test] -fn pgp_v4_signatures_can_be_verified() { +fn pgp_v4_signatures_can_be_generated_and_verified() { // create message let message = { let manifest = Manifest { diff --git a/src/ssh.rs b/src/ssh.rs index b57738a9..0cc5965e 100644 --- a/src/ssh.rs +++ b/src/ssh.rs @@ -1,7 +1,7 @@ use super::*; #[test] -fn ssh_signatures_can_be_verified() { +fn ssh_keygen_signatures_can_be_verified() { let message_bytes = include_bytes!("../static/ssh-test/message"); let signature_str = include_str!("../static/ssh-test/message.sig"); let public_key_str = include_str!("../static/ssh-test/id_ed25519.pub"); @@ -49,3 +49,48 @@ fn ssh_signatures_can_be_verified() { eprintln!("SSH_PUBLIC_KEY: {public_key}"); eprintln!("SSH_SIGNATURE: {signature}"); } + +#[test] +fn ssh_signatures_can_be_generated_and_verified() { + use { + rand::rngs::OsRng, + ssh_key::{Algorithm, HashAlg}, + }; + + let message = { + let manifest = Manifest { + files: Directory::new(), + notes: Vec::new(), + }; + + Message { + fingerprint: manifest.fingerprint(), + time: None, + } + .serialize() + }; + + let private_key = ssh_key::PrivateKey::random(&mut OsRng, Algorithm::Ed25519).unwrap(); + + let ssh_sig = private_key + .sign("filepack", HashAlg::Sha512, message.as_bytes()) + .unwrap(); + + let signature = { + let sig_bytes: [u8; 64] = ssh_sig.signature_bytes().try_into().unwrap(); + Signature::new( + SignatureScheme::Ssh, + ed25519_dalek::Signature::from_bytes(&sig_bytes), + ) + }; + + let public_key = { + let ssh_key::public::KeyData::Ed25519(ed25519_key) = private_key.public_key().key_data() else { + panic!("expected ed25519"); + }; + + PublicKey::from_bytes(ed25519_key.0) + }; + + signature.verify(&message, public_key).unwrap(); +}