From 226fc49b8610911a2ad1339ef84589f6c1b08d5e Mon Sep 17 00:00:00 2001 From: silverpill Date: Sun, 13 Feb 2022 13:10:09 +0000 Subject: [PATCH] Allow non-standard wrap width when parsing public keys in PEM format --- Cargo.lock | 10 ++++++++++ Cargo.toml | 1 + src/http_signatures/verify.rs | 4 ++-- src/utils/crypto.rs | 16 +++++++++++++++- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 21d349b..b6baa62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1706,6 +1706,7 @@ dependencies = [ "mime-sniffer", "mime_guess", "num_cpus", + "pem", "postgres-protocol", "postgres-types", "postgres_query", @@ -1934,6 +1935,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "pem" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9a3b09a20e374558580a4914d3b7d89bd61b954a5a5e1dcbea98753addb1947" +dependencies = [ + "base64 0.13.0", +] + [[package]] name = "pem-rfc7468" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index d2258d2..6446df3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,7 @@ refinery = { version = "0.4.0", features = ["tokio-postgres"] } reqwest = { version = "0.10.10", features = ["json"] } # Used for working with RSA keys rsa = "0.5.0" +pem = "1.0.2" # Used for hashing passwords rust-argon2 = "0.8.3" # Used for working with ethereum keys diff --git a/src/http_signatures/verify.rs b/src/http_signatures/verify.rs index ce5fa4d..5534c71 100644 --- a/src/http_signatures/verify.rs +++ b/src/http_signatures/verify.rs @@ -32,8 +32,8 @@ pub enum VerificationError { #[error("{0}")] ActorError(String), - #[error("invalid key")] - InvalidKey(#[from] rsa::pkcs8::Error), + #[error("invalid public key")] + InvalidPublicKey(#[from] rsa::pkcs8::Error), #[error("invalid encoding")] InvalidEncoding(#[from] base64::DecodeError), diff --git a/src/utils/crypto.rs b/src/utils/crypto.rs index 516b601..d10b061 100644 --- a/src/utils/crypto.rs +++ b/src/utils/crypto.rs @@ -1,3 +1,4 @@ +use pem; use rand; use rand::prelude::*; use rsa::{Hash, PaddingScheme, PublicKey, RsaPrivateKey, RsaPublicKey}; @@ -47,7 +48,12 @@ pub fn get_public_key_pem( pub fn deserialize_public_key( public_key_pem: &str, ) -> Result { - RsaPublicKey::from_public_key_pem(public_key_pem.trim()) + // rsa package can't decode PEM string with non-standard wrap width, + // so the input should be normalized first + let parsed_pem = pem::parse(public_key_pem.trim().as_bytes()) + .map_err(|_| rsa::pkcs8::Error::Pem)?; + let normalized_pem = pem::encode(&parsed_pem); + RsaPublicKey::from_public_key_pem(&normalized_pem) } pub fn sign_message( @@ -88,6 +94,14 @@ mod tests { use rand::rngs::OsRng; use super::*; + #[test] + fn test_deserialize_public_key_nowrap() { + let public_key_pem = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8ehqQ7n6+pw19U8q2UtxE/9017STW3yRnnqV5nVk8LJ00ba+berqwekxDW+nw77GAu3TJ+hYeeSerUNPup7y3yO3V +YsFtrgWDQ/s8k86sNBU+Ce2GOL7seh46kyAWgJeohh4Rcrr23rftHbvxOcRM8VzYuCeb1DgVhPGtA0xULwIDAQAB\n-----END PUBLIC KEY-----"; + let result = deserialize_public_key(&public_key_pem); + assert_eq!(result.is_ok(), true); + } + #[test] fn test_public_key_serialization_deserialization() { let private_key = RsaPrivateKey::new(&mut OsRng, 512).unwrap();