atomic_lti/
secure.rs

1use crate::errors::SecureError;
2use openssl::rsa::Rsa;
3use openssl::symm::Cipher;
4use rand::Rng;
5
6pub fn generate_secure_string(len: usize) -> String {
7  rand::rng()
8    .sample_iter(rand::distr::Alphanumeric)
9    .take(len)
10    .map(char::from)
11    .collect()
12}
13
14pub fn decrypt_rsa_private_key(
15  key: &str,
16  passphrase: &str,
17) -> Result<Rsa<openssl::pkey::Private>, SecureError> {
18  let decrypted = Rsa::private_key_from_pem_passphrase(key.as_bytes(), passphrase.as_bytes())
19    .map_err(|e| SecureError::PrivateKeyError(e.to_string()))?;
20
21  Ok(decrypted)
22}
23
24/// Generate a new RSA key pair and return the private key as a PEM string.
25/// The password is used to encrypt the private key and is required to decrypt it.
26pub fn generate_rsa_key_pair(
27  passphrase: &str,
28) -> Result<(Rsa<openssl::pkey::Private>, String), SecureError> {
29  let rsa_key_pair: Rsa<openssl::pkey::Private> =
30    Rsa::generate(2048).map_err(|e| SecureError::PrivateKeyGenerateFailed(e.to_string()))?;
31
32  let cipher = Cipher::aes_256_cbc();
33
34  let pem = rsa_key_pair
35    .private_key_to_pem_passphrase(cipher, passphrase.as_bytes())
36    .map_err(|e| SecureError::PrivateKeyGenerateFailed(e.to_string()))?;
37
38  let pem_string =
39    String::from_utf8(pem).map_err(|e| SecureError::PrivateKeyError(e.to_string()))?;
40
41  Ok((rsa_key_pair, pem_string))
42}
43
44#[cfg(test)]
45mod tests {
46  use super::*;
47
48  #[test]
49  fn test_generate_secure_string() {
50    let len = 10;
51    let secure_string = generate_secure_string(len);
52    assert_eq!(secure_string.len(), len);
53  }
54
55  #[test]
56  fn test_generate_rsa_key_pair() {
57    let passphrase = "asdfasdf";
58    let (rsa_key_pair, pem_string) =
59      generate_rsa_key_pair(passphrase).expect("Failed to generate RSA key pair");
60    let modulus = rsa_key_pair.n().to_owned().expect("Failed to get modulus");
61    let bit_size = modulus.num_bits();
62    assert_eq!(bit_size, 2048, "The key size should be 2048 bits");
63    assert!(pem_string.contains("BEGIN RSA PRIVATE KEY"));
64    assert!(pem_string.contains("END RSA PRIVATE KEY"));
65  }
66}