Improve ssh crate API
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This commit is contained in:
parent
79c1372d33
commit
c8bff35229
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue