diff --git a/radicle-ssh/src/agent/client.rs b/radicle-ssh/src/agent/client.rs index 2ff9f931..0654829e 100644 --- a/radicle-ssh/src/agent/client.rs +++ b/radicle-ssh/src/agent/client.rs @@ -218,10 +218,12 @@ impl AgentClient { if self.buf[0] == msg::IDENTITIES_ANSWER { let mut r = self.buf.reader(1); let n = r.read_u32()?; + for _ in 0..n { let key = r.read_string()?; let _ = r.read_string()?; let mut r = key.reader(0); + if let Some(pk) = K::read(&mut r).map_err(|err| Error::Public(Box::new(err)))? { keys.push(pk); } @@ -261,7 +263,7 @@ impl AgentClient { // uint32 flags let mut pk = Vec::new().into(); - let n = public.write_blob(&mut pk); + let n = public.write(&mut pk); let total = 1 + n + 4 + data.len() + 4; debug_assert_eq!(n, pk.len()); @@ -295,7 +297,7 @@ impl AgentClient { K: Public, { let mut pk = Vec::new().into(); - let n = public.write_blob(&mut pk); + let n = public.write(&mut pk); let total = 1 + n; debug_assert_eq!(n, pk.len()); diff --git a/radicle-ssh/src/key.rs b/radicle-ssh/src/key.rs index 638e7d42..20d904e6 100644 --- a/radicle-ssh/src/key.rs +++ b/radicle-ssh/src/key.rs @@ -1,20 +1,26 @@ +use std::error::Error; + use crate::encoding::{Buffer, Cursor}; +/// A public SSH key. pub trait Public: Sized { - type Error; + type Error: Error + Send + Sync + 'static; - fn write_blob(&self, buf: &mut Buffer) -> usize; + /// Write the public key to the given buffer, in SSH "blob" format. + fn write(&self, buf: &mut Buffer) -> usize; + /// Read the public key from the given reader. fn read(reader: &mut Cursor) -> Result, Self::Error>; } +/// A private SSH key. pub trait Private: Sized { - type Error; + type Error: Error + Send + Sync + 'static; - fn read(reader: &mut Cursor) -> Result, Self)>, Self::Error>; + /// Read a private key from the given reader. + fn read(reader: &mut Cursor) -> Result, Self::Error>; + /// Write the key bytes to the supplied buffer. fn write(&self, buf: &mut Buffer) -> Result<(), Self::Error>; - fn write_signature>( - &self, - buf: &mut Buffer, - to_sign: T, - ) -> Result<(), Self::Error>; + /// Sign the data and write the signature to the given buffer. + fn write_signature>(&self, data: T, buf: &mut Buffer) + -> Result<(), Self::Error>; } diff --git a/radicle/src/ssh.rs b/radicle/src/ssh.rs index 2552ef2d..268c37c1 100644 --- a/radicle/src/ssh.rs +++ b/radicle/src/ssh.rs @@ -86,7 +86,7 @@ pub enum PublicKeyError { impl radicle_ssh::key::Public for PublicKey { type Error = PublicKeyError; - fn write_blob(&self, buf: &mut Zeroizing>) -> usize { + fn write(&self, buf: &mut Zeroizing>) -> usize { let mut n = 0; let typ = b"ssh-ed25519"; let size = typ.len() + self.len() + mem::size_of::() * 2; @@ -124,19 +124,21 @@ impl From for SecretKey { } #[derive(Debug, Error)] -pub enum SigningKeyError { +pub enum SecretKeyError { #[error(transparent)] Encoding(#[from] encoding::Error), #[error(transparent)] Crypto(#[from] crypto::Error), #[error(transparent)] Io(#[from] io::Error), + #[error("public key does not match secret key")] + Mismatch, } impl radicle_ssh::key::Private for SecretKey { - type Error = SigningKeyError; + type Error = SecretKeyError; - fn read(r: &mut encoding::Cursor) -> Result, Self)>, Self::Error> { + fn read(r: &mut encoding::Cursor) -> Result, Self::Error> { match r.read_string()? { b"ssh-ed25519" => { let public = r.read_string()?; @@ -144,7 +146,10 @@ impl radicle_ssh::key::Private for SecretKey { let _comment = r.read_string()?; let key = crypto::SecretKey::from_slice(pair).unwrap(); - Ok(Some((public.to_vec(), SecretKey(key)))) + if public != key.public_key().as_ref() { + return Err(SecretKeyError::Mismatch); + } + Ok(Some(SecretKey(key))) } _ => Ok(None), } @@ -164,11 +169,11 @@ impl radicle_ssh::key::Private for SecretKey { fn write_signature>( &self, + data: Bytes, buf: &mut Zeroizing>, - to_sign: Bytes, ) -> Result<(), Self::Error> { let name = "ssh-ed25519"; - let signature: [u8; 64] = *self.0.sign(to_sign.as_ref(), None); + let signature: [u8; 64] = *self.0.sign(data.as_ref(), None); buf.deref_mut() .write_u32::((name.len() + signature.len() + 8) as u32)?; @@ -221,7 +226,7 @@ mod test { SecretKey(sk).write(&mut buf).unwrap(); let mut cursor = buf.reader(0); - let (_, output) = SecretKey::read(&mut cursor).unwrap().unwrap(); + let output = SecretKey::read(&mut cursor).unwrap().unwrap(); assert_eq!(sk, output.0); }