use base64::{engine::general_purpose::STANDARD, Engine};
use num_bigint_dig::BigUint;
use rsa::{Pkcs1v15Encrypt, RsaPublicKey};
use crate::error::SessionError;
pub fn rsa_encrypt_password(password: &str, public_key_mod: &str, public_key_exp: &str) -> Result<String, SessionError> {
let modulus = BigUint::parse_bytes(public_key_mod.as_bytes(), 16).ok_or_else(|| SessionError::CryptoError("Invalid modulus: not a valid hex string".into()))?;
let exponent = BigUint::parse_bytes(public_key_exp.as_bytes(), 16).ok_or_else(|| SessionError::CryptoError("Invalid exponent: not a valid hex string".into()))?;
let public_key = RsaPublicKey::new(rsa::BigUint::from_bytes_be(&modulus.to_bytes_be()), rsa::BigUint::from_bytes_be(&exponent.to_bytes_be())).map_err(SessionError::from)?;
let mut rng = rand::thread_rng();
let encrypted = public_key.encrypt(&mut rng, Pkcs1v15Encrypt, password.as_bytes()).map_err(SessionError::from)?;
Ok(STANDARD.encode(&encrypted))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_rsa_encrypt_password_valid_key() {
let test_mod = "D23BA8F7C8E2E3E9B6C7D8E9F0A1B2C3D4E5F6A7B8C9D0E1F2A3B4C5D6E7F8A9B0C1D2E3F4A5B6C7D8E9F0A1B2C3D4E5F6A7B8C9D0E1F2A3B4C5D6E7F8A9B0C1";
let test_exp = "010001";
let result = rsa_encrypt_password("testpassword123", test_mod, test_exp);
assert!(result.is_err() || result.is_ok());
}
#[test]
fn test_rsa_encrypt_password_invalid_modulus() {
let result = rsa_encrypt_password("password", "not_valid_hex!", "010001");
assert!(result.is_err());
match result {
Err(SessionError::CryptoError(msg)) => {
assert!(msg.contains("Invalid modulus"));
}
_ => panic!("Expected CryptoError with 'Invalid modulus'"),
}
}
#[test]
fn test_rsa_encrypt_password_invalid_exponent() {
let valid_mod = "D23BA8F7C8E2E3E9B6C7D8E9F0A1B2C3";
let result = rsa_encrypt_password("password", valid_mod, "not_hex!");
assert!(result.is_err());
match result {
Err(SessionError::CryptoError(msg)) => {
assert!(msg.contains("Invalid exponent"));
}
_ => panic!("Expected CryptoError with 'Invalid exponent'"),
}
}
#[test]
fn test_rsa_encrypt_password_empty_modulus() {
let result = rsa_encrypt_password("password", "", "010001");
assert!(result.is_err());
}
#[test]
fn test_rsa_encrypt_password_empty_password() {
let test_mod = "D23BA8F7C8E2E3E9B6C7D8E9F0A1B2C3D4E5F6A7B8C9D0E1F2A3B4C5D6E7F8A9B0C1D2E3F4A5B6C7D8E9F0A1B2C3D4E5F6A7B8C9D0E1F2A3B4C5D6E7F8A9B0C1";
let result = rsa_encrypt_password("", test_mod, "010001");
assert!(result.is_err() || result.is_ok());
}
}