Skip to main content

cross_crypto_rs/
lib.rs

1use openssl::rsa::Rsa;
2use openssl::pkey::PKey;
3use openssl::encrypt::{Encrypter, Decrypter};
4use openssl::symm::{Cipher, encrypt_aead, decrypt_aead};
5use rand::Rng;
6use base64::{engine::general_purpose, Engine};
7use serde_json::json;
8use std::thread;
9use std::sync::mpsc;
10
11/// 📌 *Genera las llaves RSA en un hilo separado para mejorar rendimiento*
12pub fn generate_rsa_keys() -> (String, String) {
13    let (tx, rx) = mpsc::channel();
14
15    thread::spawn(move || {
16        let rsa = Rsa::generate(4096).expect("Error generando RSA");
17        let private_key = rsa.private_key_to_pem().expect("Error en clave privada");
18        let public_key = rsa.public_key_to_pem().expect("Error en clave pública");
19
20        tx.send((
21            String::from_utf8(private_key).unwrap(),
22            String::from_utf8(public_key).unwrap(),
23        ))
24        .unwrap();
25    });
26
27    rx.recv().expect("Error recibiendo claves")
28}
29
30/// 📌 *Cifra datos encriptando la clave AES con RSA*
31pub fn encrypt_hybrid(data: &str, public_key_pem: &str) -> String {
32    let rsa = Rsa::public_key_from_pem(public_key_pem.as_bytes()).expect("Error en clave pública");
33    let pkey = PKey::from_rsa(rsa).unwrap();
34
35    let aes_key: [u8; 32] = rand::thread_rng().gen();
36    let cipher = Cipher::aes_256_gcm();
37    let nonce: [u8; 12] = rand::thread_rng().gen();
38
39    let mut encrypter = Encrypter::new(&pkey).unwrap();
40    encrypter.set_rsa_padding(openssl::rsa::Padding::PKCS1_OAEP).unwrap();
41    let mut encrypted_key = vec![0; encrypter.encrypt_len(&aes_key).unwrap()];
42    let _ = encrypter.encrypt(&aes_key, &mut encrypted_key).unwrap();
43
44    // 🔹 Nuevo buffer mutable para el tag
45    let mut tag = vec![0; 16];
46    let ciphertext = encrypt_aead(cipher, &aes_key, Some(&nonce), &[], data.as_bytes(), &mut tag).unwrap();
47
48    json!({
49        "encryptedKey": general_purpose::STANDARD.encode(&encrypted_key),
50        "encryptedData": general_purpose::STANDARD.encode(&ciphertext),
51        "nonce": general_purpose::STANDARD.encode(&nonce),
52        "tag": general_purpose::STANDARD.encode(&tag)
53    }).to_string()
54}
55
56/// 📌 *Desencripta los datos encriptados con AES-GCM y RSA-OAEP*
57pub fn decrypt_hybrid(encrypted_data_json: &str, private_key_pem: &str) -> String {
58    let json_data: serde_json::Value = serde_json::from_str(encrypted_data_json).expect("Error en JSON");
59
60    let encrypted_key = general_purpose::STANDARD
61        .decode(json_data["encryptedKey"].as_str().unwrap())
62        .unwrap();
63
64    let ciphertext = general_purpose::STANDARD
65        .decode(json_data["encryptedData"].as_str().unwrap())
66        .unwrap();
67
68    let nonce = general_purpose::STANDARD
69        .decode(json_data["nonce"].as_str().unwrap())
70        .unwrap();
71
72    let tag = general_purpose::STANDARD
73        .decode(json_data["tag"].as_str().unwrap())
74        .unwrap();
75
76    let rsa = Rsa::private_key_from_pem(private_key_pem.as_bytes()).expect("Error en clave privada");
77    let pkey = PKey::from_rsa(rsa).unwrap();
78
79    let mut decrypter = Decrypter::new(&pkey).unwrap();
80    decrypter.set_rsa_padding(openssl::rsa::Padding::PKCS1_OAEP).unwrap();
81
82    let mut aes_key = vec![0; decrypter.decrypt_len(&encrypted_key).unwrap()];
83    let decrypted_len = decrypter.decrypt(&encrypted_key, &mut aes_key).unwrap();
84
85    // 📌 Asegurar que la clave AES tenga 32 bytes exactos
86    aes_key.truncate(decrypted_len);
87    if aes_key.len() != 32 {
88        panic!("❌ Error: La clave AES desencriptada no tiene 32 bytes, tiene {}", aes_key.len());
89    }
90
91    // 🔹 Desencriptar el mensaje con AES-GCM
92    let plaintext = decrypt_aead(
93        Cipher::aes_256_gcm(),
94        &aes_key,
95        Some(&nonce),
96        &[], // AAD vacío
97        &ciphertext,
98        &tag,
99    ).expect("Error al desencriptar AES");
100
101    String::from_utf8_lossy(&plaintext).to_string()
102}