From e273e5e1f1af24748682bfc9a868a070dc9db2ff Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 11 Jan 2024 21:44:41 -0700 Subject: [PATCH] ssh-key: simplify DSA signature encoding --- ssh-key/src/signature.rs | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/ssh-key/src/signature.rs b/ssh-key/src/signature.rs index aa3729e..2a1e498 100644 --- a/ssh-key/src/signature.rs +++ b/ssh-key/src/signature.rs @@ -324,36 +324,25 @@ impl Verifier for public::KeyData { #[cfg(feature = "dsa")] impl Signer for DsaKeypair { fn try_sign(&self, message: &[u8]) -> signature::Result { - fn to_be_bytes_padded(v: &BigUint, len: usize) -> Vec { - let mut bytes = v.to_bytes_le(); - let pad_len = len.saturating_sub(bytes.len()); - if pad_len > 0 { - bytes.extend(iter::repeat(0).take(pad_len)); - } - bytes.reverse(); - bytes - } - let signature = dsa::SigningKey::try_from(self)? .try_sign_digest(Sha1::new_with_prefix(message)) .map_err(|_| signature::Error::new())?; - // Note that we need to roll our own signature encoding, as [RFC4253 section 6.6] - // specifies two raw 80 bit integer but the dsa::SigningKey serialization - // encodes to a der format. - let mut buf: Vec = Vec::new(); - let mut r = to_be_bytes_padded(signature.r(), DSA_SIGNATURE_SIZE / 2); - let mut s = to_be_bytes_padded(signature.s(), DSA_SIGNATURE_SIZE / 2); - buf.append(&mut r); - buf.append(&mut s); - - if buf.len() != DSA_SIGNATURE_SIZE { - return Err(signature::Error::new()); + // Encode the format specified in RFC4253 section 6.6: two raw 80-bit integers concatenated + let mut data = Vec::new(); + + for component in [signature.r(), signature.s()] { + let mut bytes = component.to_bytes_be(); + let pad_len = (DSA_SIGNATURE_SIZE / 2).saturating_sub(bytes.len()); + data.extend(iter::repeat(0).take(pad_len)); + data.append(&mut bytes); } + debug_assert_eq!(data.len(), DSA_SIGNATURE_SIZE); + Ok(Signature { algorithm: Algorithm::Dsa, - data: buf, + data, }) } }