Skip to content

Commit 966936e

Browse files
authored
ssh-key: added optional support for verifying legacy ssh-rsa SHA1 signatures (#315)
1 parent c7aaebd commit 966936e

2 files changed

Lines changed: 34 additions & 11 deletions

File tree

ssh-key/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ rand_core = { version = "0.6.4", optional = true, default-features = false }
4141
rsa = { version = "=0.10.0-pre.3", optional = true, default-features = false, features = ["sha2"] }
4242
sec1 = { version = "0.8.0-rc.3", optional = true, default-features = false, features = ["point"] }
4343
serde = { version = "1.0.16", optional = true }
44-
sha1 = { version = "=0.11.0-pre.4", optional = true, default-features = false }
44+
sha1 = { version = "=0.11.0-pre.4", optional = true, default-features = false, features = ["oid"] }
4545

4646
[dev-dependencies]
4747
hex-literal = "0.4.1"
@@ -84,6 +84,7 @@ p384 = ["dep:p384", "ecdsa"]
8484
p521 = ["dep:p521", "ecdsa"]
8585
ppk = ["dep:hex", "alloc", "cipher/aes-cbc", "dep:hmac", "dep:argon2", "dep:sha1"]
8686
rsa = ["dep:bigint", "dep:rsa", "alloc", "rand_core"]
87+
sha1 = ["dep:sha1"]
8788
tdes = ["cipher/tdes", "encryption"]
8889

8990
[package.metadata.docs.rs]

ssh-key/src/signature.rs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use crate::{private::Ed25519Keypair, public::Ed25519PublicKey};
1313
use {
1414
crate::{private::DsaKeypair, public::DsaPublicKey},
1515
bigint::BigUint,
16-
sha1::Sha1,
1716
signature::{DigestSigner, DigestVerifier},
1817
};
1918

@@ -32,6 +31,9 @@ use {
3231
sha2::Sha512,
3332
};
3433

34+
#[cfg(any(all(feature = "sha1", feature = "rsa"), feature = "dsa"))]
35+
use sha1::Sha1;
36+
3537
#[cfg(any(feature = "ed25519", feature = "rsa", feature = "p256"))]
3638
use sha2::Sha256;
3739

@@ -680,15 +682,20 @@ impl Signer<Signature> for RsaKeypair {
680682
impl Verifier<Signature> for RsaPublicKey {
681683
fn verify(&self, message: &[u8], signature: &Signature) -> signature::Result<()> {
682684
match signature.algorithm {
683-
// TODO(tarcieri): optional off-by-default support for legacy SHA1 signatures?
684-
Algorithm::Rsa { hash: Some(hash) } => {
685+
Algorithm::Rsa { hash } => {
685686
let signature = rsa::pkcs1v15::Signature::try_from(signature.data.as_ref())?;
686687

687688
match hash {
688-
HashAlg::Sha256 => rsa::pkcs1v15::VerifyingKey::<Sha256>::try_from(self)?
689+
#[cfg(not(all(feature = "rsa", feature = "sha1")))]
690+
None => Err(Algorithm::Rsa { hash: None }.unsupported_error().into()),
691+
#[cfg(all(feature = "rsa", feature = "sha1"))]
692+
None => rsa::pkcs1v15::VerifyingKey::<Sha1>::try_from(self)?
693+
.verify(message, &signature)
694+
.map_err(|_| signature::Error::new()),
695+
Some(HashAlg::Sha256) => rsa::pkcs1v15::VerifyingKey::<Sha256>::try_from(self)?
689696
.verify(message, &signature)
690697
.map_err(|_| signature::Error::new()),
691-
HashAlg::Sha512 => rsa::pkcs1v15::VerifyingKey::<Sha512>::try_from(self)?
698+
Some(HashAlg::Sha512) => rsa::pkcs1v15::VerifyingKey::<Sha512>::try_from(self)?
692699
.verify(message, &signature)
693700
.map_err(|_| signature::Error::new()),
694701
}
@@ -706,11 +713,10 @@ mod tests {
706713
use encoding::Encode;
707714
use hex_literal::hex;
708715

716+
#[cfg(any(feature = "ed25519", all(feature = "rsa", feature = "sha1")))]
717+
use signature::Verifier;
709718
#[cfg(feature = "ed25519")]
710-
use {
711-
super::Ed25519Keypair,
712-
signature::{Signer, Verifier},
713-
};
719+
use {super::Ed25519Keypair, signature::Signer};
714720

715721
#[cfg(feature = "p256")]
716722
use super::{zero_pad_field_bytes, Mpint};
@@ -722,7 +728,7 @@ mod tests {
722728
const RSA_SHA512_SIGNATURE: &[u8] = &hex!("0000000c7273612d736861322d3531320000018085a4ad1a91a62c00c85de7bb511f38088ff2bce763d76f4786febbe55d47624f9e2cffce58a680183b9ad162c7f0191ea26cab001ac5f5055743eced58e9981789305c208fc98d2657954e38eb28c7e7f3fbe92393a14324ed77aebb772a41aa7a107b38cb9bd1d9ad79b275135d1d7e019bb1d56d74f2450be6db0771f48f6707d3fcf9789592ca2e55595acc16b6e8d0139b56c5d1360b3a1e060f4151a3d7841df2c2a8c94d6f8a1bf633165ee0bcadac5642763df0dd79d3235ae5506595145f199d8abe8f9980411bf70a16e30f273736324d047043317044c36374d6a5ed34cac251e01c6795e4578393f9090bf4ae3e74a0009275a197315fc9c62f1c9aec1ba3b2d37c3b207e5500df19e090e7097ebc038fb9c9e35aea9161479ba6b5190f48e89e1abe51e8ec0e120ef89776e129687ca52d1892c8e88e6ef062a7d96b8a87682ca6a42ff1df0cdf5815c3645aeed7267ca7093043db0565e0f109b796bf117b9d2bb6d6debc0c67a4c9fb3aae3e29b00c7bd70f6c11cf53c295ff");
723729

724730
/// Example test vector for signing.
725-
#[cfg(feature = "ed25519")]
731+
#[cfg(any(feature = "ed25519", all(feature = "rsa", feature = "sha1")))]
726732
const EXAMPLE_MSG: &[u8] = b"Hello, world!";
727733

728734
#[cfg(feature = "p256")]
@@ -924,4 +930,20 @@ mod tests {
924930
Err(encoding::Error::Length)
925931
);
926932
}
933+
934+
#[cfg(all(feature = "rsa", feature = "sha1"))]
935+
#[test]
936+
fn sign_and_verify_rsa_sha1() {
937+
use encoding::Decode;
938+
939+
use crate::PrivateKey;
940+
941+
let key = PrivateKey::from_openssh(include_str!("../tests/examples/id_rsa_3072")).unwrap();
942+
let key = key.key_data().rsa().unwrap();
943+
let encoded = hex!("000000077373682d727361000001809485247d72bf853272c86dd8c1c3fa0d2bebcdea9d91a376525a4bcc4a9ca2b19d31af48cfc07da086b244c65b37f3eb8fcab9661ccf777ed2f45404dd602b405526e19323f065b44d19f1bbda3eaf87b922b01049fcd8b82f08ffab6582e8427b0af3305f32961816d499d7b4925c1293b2d658dc6ca7cfb2d47c203c7d9512c0ee33e3d74f362d339a112fc94a74e8f388fc7fd1e9b95c7dd94e62ff16c9463476b7cf0e42af0f17fd2b9e325a50fc40ffd02b4a39e692727186b47c8ce9d7037de7e94615966df462238e214e7440bedabc5fbf79cfa93b96be5f27268da7c1ae2246bcabcc18a0d2c507be8727d04e41ed38686e5c455c159ee371f477668e89720191a72fbdb4eef86f1aa5c3596cefad12b20b1a1220accf6145f8583d7559751b2d0445e2e8a8fda85bf30f24b446ac6d0b943f7c519e5a021b1468cf120ed565d95ed8ddf022f97537ec5491226198ec58dd96c6bd218ddb237aa80785ceafa7722f1d2ba3e39dce2a9fdb0038f4124e2aa27d28eef927d87c8708f6");
944+
945+
let decoded = Signature::decode(&mut &encoded[..]).unwrap();
946+
947+
assert!(Verifier::verify(key.public(), EXAMPLE_MSG, &decoded).is_ok());
948+
}
927949
}

0 commit comments

Comments
 (0)