Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
Improve ssh crate API
Alexis Sellier committed 3 years ago
commit c8bff352296a54ade1b87260833726527d6eea1a
parent 79c1372d3339c02b17b70ec3cec65c857a7ec89d
3 files changed +32 -19
modified radicle-ssh/src/agent/client.rs
@@ -218,10 +218,12 @@ impl<S: ClientStream> AgentClient<S> {
        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<S: ClientStream> AgentClient<S> {
        // 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<S: ClientStream> AgentClient<S> {
        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());
modified 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<Option<Self>, Self::Error>;
}

+
/// A private SSH key.
pub trait Private: Sized {
-
    type Error;
+
    type Error: Error + Send + Sync + 'static;

-
    fn read(reader: &mut Cursor) -> Result<Option<(Vec<u8>, Self)>, Self::Error>;
+
    /// Read a private key from the given reader.
+
    fn read(reader: &mut Cursor) -> Result<Option<Self>, Self::Error>;
+
    /// Write the key bytes to the supplied buffer.
    fn write(&self, buf: &mut Buffer) -> Result<(), Self::Error>;
-
    fn write_signature<T: AsRef<[u8]>>(
-
        &self,
-
        buf: &mut Buffer,
-
        to_sign: T,
-
    ) -> Result<(), Self::Error>;
+
    /// Sign the data and write the signature to the given buffer.
+
    fn write_signature<T: AsRef<[u8]>>(&self, data: T, buf: &mut Buffer)
+
        -> Result<(), Self::Error>;
}
modified 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<Vec<u8>>) -> usize {
+
    fn write(&self, buf: &mut Zeroizing<Vec<u8>>) -> usize {
        let mut n = 0;
        let typ = b"ssh-ed25519";
        let size = typ.len() + self.len() + mem::size_of::<u32>() * 2;
@@ -124,19 +124,21 @@ impl From<crypto::SecretKey> 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<Option<(Vec<u8>, Self)>, Self::Error> {
+
    fn read(r: &mut encoding::Cursor) -> Result<Option<Self>, 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<Bytes: AsRef<[u8]>>(
        &self,
+
        data: Bytes,
        buf: &mut Zeroizing<Vec<u8>>,
-
        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::<BigEndian>((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);
    }