diff --git a/src/public_key/ed25519.rs b/src/public_key/ed25519.rs index e9fb887..7cbf208 100644 --- a/src/public_key/ed25519.rs +++ b/src/public_key/ed25519.rs @@ -4,7 +4,9 @@ use std::io::ErrorKind::InvalidData; use crypto::ed25519; use rand::RngCore; -use crate::public_key::{CryptoSystem, KeyPair}; +use crate::public_key::{ + CryptoSystem, KeyPair, KeyPairIdValidationError, SigningError +}; pub static ED25519: CryptoSystem = CryptoSystem { id: "ed25519", @@ -84,32 +86,34 @@ impl KeyPair for Ed25519KeyPair { self.private.is_some() } - fn verify(&self, data: &[u8], signature: &[u8]) -> Result { - use crate::packet::ReadPacketExt; + fn verify(&self, data: &[u8], signature: &[u8]) -> Result { use std::io::Cursor; + use crate::packet::ReadPacketExt; + + const EXPECTED_ID: &[u8] = b"ssh-ed25519"; let mut reader = Cursor::new(signature); - let id = reader.read_string().unwrap_or_default(); + let received_id = reader.read_string().unwrap_or_default(); - if id == b"ssh-ed25519" { + if received_id == EXPECTED_ID { if let Ok(sig) = reader.read_string() { return Ok(ed25519::verify(data, &self.public, sig.as_slice())); } } - Err(()) + Err(KeyPairIdValidationError {received_id, expected_id: EXPECTED_ID }) } - fn sign(&self, data: &[u8]) -> Result, ()> { + fn sign(&self, data: &[u8]) -> Result, SigningError> { use crate::packet::WritePacketExt; if let Some(private_key) = self.private { let mut result = Vec::new(); let sig = ed25519::signature(data, &private_key); - result.write_string("ssh-ed25519").or(Err(()))?; - result.write_bytes(&sig).or(Err(()))?; + result.write_string("ssh-ed25519")?; + result.write_bytes(&sig)?; Ok(result) } else { - Err(()) + Err(SigningError::NoPrivateKey) } } diff --git a/src/public_key/mod.rs b/src/public_key/mod.rs index 04f5ffb..d60eae1 100644 --- a/src/public_key/mod.rs +++ b/src/public_key/mod.rs @@ -11,8 +11,8 @@ pub trait KeyPair: Sync + Send { fn has_private(&self) -> bool; - fn verify(&self, data: &[u8], signature: &[u8]) -> Result; - fn sign(&self, data: &[u8]) -> Result, ()>; + fn verify(&self, data: &[u8], signature: &[u8]) -> Result; + fn sign(&self, data: &[u8]) -> Result, SigningError>; fn write_public(&self, w: &mut dyn Write) -> io::Result<()>; fn export(&self, w: &mut dyn Write) -> io::Result<()>; @@ -24,3 +24,21 @@ pub struct CryptoSystem { pub import: fn(r: &mut dyn Read) -> io::Result>, pub read_public: fn(r: &mut dyn Read) -> io::Result>, } + +#[derive(Debug)] +pub enum SigningError { + NoPrivateKey, + Io(io::Error), +} + +impl From for SigningError { + fn from(value: io::Error) -> Self { + SigningError::Io(value) + } +} + +#[derive(Debug)] +pub struct KeyPairIdValidationError<'a> { + pub expected_id: &'a [u8], + pub received_id: Vec, +}