Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normalize provided private key string to the correct PEM format #22

Merged
merged 1 commit into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# 0.6.0
- Normalize provided private key string to the correct PEM format.
- Update thiserror to version 2.

# 0.5.0
- Convert from anyhow to thiserror.

# 0.4.1
- Add the Debug and Clone traits to `Signer` and `Verifier`.

Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mauth-core"
version = "0.5.0"
version = "0.6.0"
edition = "2021"
authors = ["Medidata Solutions <support@mdsol.com>"]
description = "Generate and verify Medidata MAuth protocol signatures"
Expand All @@ -13,7 +13,7 @@ keywords = ["security", "authentication"]
categories = ["authentication"]

[dependencies]
thiserror = "1"
thiserror = "2"
base64 = "0.22"
hex = "0.4"
lazy-regex = "3"
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ pub(crate) mod signable;
pub mod signer;
/// Signature verification for incoming requests
pub mod verifier;

mod pem_format;
54 changes: 54 additions & 0 deletions src/pem_format.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const RSA_PRIVATE_KEY_HEADER: &str = "-----BEGIN RSA PRIVATE KEY-----";
const RSA_PRIVATE_KEY_FOOTER: &str = "-----END RSA PRIVATE KEY-----";

pub fn normalize_rsa_private_key(key: impl Into<String>) -> String {
let key = key.into();

match key.contains('\n') {
true => key,
false => {
let body = key
.trim()
.trim_start_matches(RSA_PRIVATE_KEY_HEADER)
.trim_end_matches(RSA_PRIVATE_KEY_FOOTER)
.trim();

let body = match body.contains(' ') {
true => body.replace(' ', "\n"),
false => body
.chars()
.collect::<Vec<char>>()
.chunks(64)
.map(|chunk| chunk.iter().collect::<String>())
.collect::<Vec<String>>()
.join("\n"),
};
format!(
"{}\n{}\n{}",
RSA_PRIVATE_KEY_HEADER, body, RSA_PRIVATE_KEY_FOOTER
)
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn normalize_rsa_private_key_test() {
let rsa_private_key = "-----BEGIN RSA PRIVATE KEY-----\nMIIBOgIBAAJBAKj34GkxFhD90vcNLYLInFEX6Ppy1tPf9Cnzj4p4WGeKLs1Pt8Qu\n/5OiPgoTdSy7bcF9IGpSE8ZgGKzgYQVZeN97YE00\n-----END RSA PRIVATE KEY-----";
let rsa_private_key_with_space = rsa_private_key.replace('\n', " ");
let rsa_private_key_without_newline = rsa_private_key.replace('\n', "");

assert_eq!(normalize_rsa_private_key(rsa_private_key), rsa_private_key);
assert_eq!(
normalize_rsa_private_key(rsa_private_key_with_space),
rsa_private_key
);
assert_eq!(
normalize_rsa_private_key(rsa_private_key_without_newline),
rsa_private_key
);
}
}
5 changes: 4 additions & 1 deletion src/signer.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::pem_format;
use crate::{error::Error, signable::Signable};
use base64::{engine::general_purpose, Engine as _};
use rsa::pkcs1::DecodeRsaPrivateKey;
Expand Down Expand Up @@ -27,7 +28,9 @@ impl Signer {
/// assert!(signer.is_ok());
/// ```
pub fn new(app_uuid: impl Into<String>, private_key_data: String) -> Result<Self, Error> {
let private_key = RsaPrivateKey::from_pkcs1_pem(&private_key_data)?;
let private_key = RsaPrivateKey::from_pkcs1_pem(&pem_format::normalize_rsa_private_key(
private_key_data,
))?;
let signing_key = rsa::pkcs1v15::SigningKey::<Sha512>::new(private_key.to_owned());

Ok(Self {
Expand Down
Loading