whisky_wallet/encryption/
cipher.rs1use aes_gcm::{aead::AeadMut, Aes256Gcm, KeyInit, Nonce}; use base64::{engine::general_purpose, Engine as _};
3use pbkdf2::pbkdf2_hmac; use rand::RngCore; use serde_json::json;
6use sha2::Sha256;
7use whisky_common::WError; const IV_LENGTH: usize = 16;
10
11pub fn encrypt_with_cipher(
12 data: &str,
13 key: &str,
14 initialization_vector_size: Option<usize>,
15) -> Result<String, WError> {
16 let initialization_vector_size = initialization_vector_size.unwrap_or(IV_LENGTH);
18
19 let salt = vec![0u8; initialization_vector_size]; let mut derived_key = vec![0u8; 32]; pbkdf2_hmac::<Sha256>(key.as_bytes(), &salt, 100_000, &mut derived_key);
25
26 let mut cipher = Aes256Gcm::new_from_slice(&derived_key).map_err(WError::from_err(
28 "encrypt_with_cipher - Aes256Gcm::new_from_slice",
29 ))?;
30
31 let mut iv = vec![0u8; initialization_vector_size];
33 rand::thread_rng().fill_bytes(&mut iv);
34 let nonce = Nonce::from_slice(&iv); let ciphertext = cipher
38 .encrypt(nonce, data.as_bytes())
39 .map_err(WError::from_err("encrypt_with_cipher - cipher.encrypt"))?;
40
41 let iv_base64 = general_purpose::STANDARD.encode(&iv); let ciphertext_base64 = general_purpose::STANDARD.encode(&ciphertext); let result = json!({
46 "iv": iv_base64,
47 "ciphertext": ciphertext_base64,
48 });
49
50 Ok(result.to_string())
51}
52
53pub fn decrypt_with_cipher(encrypted_data_json: &str, key: &str) -> Result<String, WError> {
54 let encrypted_data: serde_json::Value = serde_json::from_str(encrypted_data_json).map_err(
56 WError::from_err("decrypt_with_cipher - JSON parsing failed"),
57 )?;
58
59 let iv_base64 = encrypted_data["iv"]
60 .as_str()
61 .ok_or_else(WError::from_opt("decrypt_with_cipher", "Missing IV"))?;
62 let ciphertext_base64 = encrypted_data["ciphertext"]
63 .as_str()
64 .ok_or_else(WError::from_opt(
65 "decrypt_with_cipher",
66 "Missing ciphertext",
67 ))?;
68
69 let iv = general_purpose::STANDARD
71 .decode(iv_base64)
72 .map_err(WError::from_err(
73 "decrypt_with_cipher - Base64 decode of IV failed",
74 ))?;
75 let ciphertext = general_purpose::STANDARD
76 .decode(ciphertext_base64)
77 .map_err(WError::from_err(
78 "decrypt_with_cipher - Base64 decode of ciphertext failed",
79 ))?;
80
81 let salt = vec![0u8; iv.len()]; let mut derived_key = vec![0u8; 32]; pbkdf2_hmac::<Sha256>(key.as_bytes(), &salt, 100_000, &mut derived_key);
87
88 let mut cipher = Aes256Gcm::new_from_slice(&derived_key).map_err(WError::from_err(
90 "decrypt_with_cipher - Aes256Gcm::new_from_slice",
91 ))?;
92
93 let nonce = Nonce::from_slice(&iv);
95
96 let decrypted_data = cipher
98 .decrypt(nonce, ciphertext.as_ref())
99 .map_err(WError::from_err("decrypt_with_cipher - Decryption failed"))?;
100
101 let decrypted_str = String::from_utf8(decrypted_data).map_err(WError::from_err(
103 "decrypt_with_cipher - Failed to convert decrypted data to UTF-8",
104 ))?;
105
106 Ok(decrypted_str)
107}