@@ -54,16 +54,20 @@ fn derive_key(password: &str, salt: &[u8]) -> Vec<u8> {
5454 key
5555}
5656
57- pub fn decrypt ( mut password : String , encrypted_data : Vec < u8 > ) -> Result < String , Error > {
58- if encrypted_data. len ( ) < SALT_LEN + NONCE_LEN + 16 {
57+ fn decrypt_legacy ( password : & str , encrypted_data : & [ u8 ] ) -> Result < String , Error > {
58+ if encrypted_data. len ( ) < NONCE_LEN + 16 {
5959 return Err ( aes_gcm:: Error ) ;
6060 }
6161
62- let ( salt, rest) = encrypted_data. split_at ( SALT_LEN ) ;
63- let ( nonce_bytes, ciphertext) = rest. split_at ( NONCE_LEN ) ;
62+ let ( nonce_bytes, ciphertext) = encrypted_data. split_at ( NONCE_LEN ) ;
6463
65- let mut key_bytes = derive_key ( & password, salt) ;
66- password. zeroize ( ) ;
64+ let mut padded = password. to_string ( ) ;
65+ if padded. len ( ) < 32 {
66+ padded += & "!" . repeat ( 32 - padded. len ( ) ) ;
67+ }
68+
69+ let mut key_bytes = padded. as_bytes ( ) . to_vec ( ) ;
70+ padded. zeroize ( ) ;
6771 let key = Key :: < Aes256Gcm > :: from_slice ( & key_bytes) ;
6872 let nonce = Nonce :: from_slice ( nonce_bytes) ;
6973 let cipher = Aes256Gcm :: new ( key) ;
@@ -75,6 +79,35 @@ pub fn decrypt(mut password: String, encrypted_data: Vec<u8>) -> Result<String,
7579 String :: from_utf8 ( plaintext) . map_err ( |_| aes_gcm:: Error )
7680}
7781
82+ pub fn decrypt ( mut password : String , encrypted_data : Vec < u8 > ) -> Result < String , Error > {
83+ // Try new format first (salt + nonce + ciphertext)
84+ if encrypted_data. len ( ) >= SALT_LEN + NONCE_LEN + 16 {
85+ let ( salt, rest) = encrypted_data. split_at ( SALT_LEN ) ;
86+ let ( nonce_bytes, ciphertext) = rest. split_at ( NONCE_LEN ) ;
87+
88+ let mut key_bytes = derive_key ( & password, salt) ;
89+ let key = Key :: < Aes256Gcm > :: from_slice ( & key_bytes) ;
90+ let nonce = Nonce :: from_slice ( nonce_bytes) ;
91+ let cipher = Aes256Gcm :: new ( key) ;
92+
93+ if let Ok ( plaintext) = cipher. decrypt ( nonce, ciphertext) {
94+ key_bytes. zeroize ( ) ;
95+ password. zeroize ( ) ;
96+ return String :: from_utf8 ( plaintext) . map_err ( |_| aes_gcm:: Error ) ;
97+ }
98+ key_bytes. zeroize ( ) ;
99+ }
100+
101+ // Fallback to legacy format (nonce + ciphertext, password padded with !)
102+ let result = decrypt_legacy ( & password, & encrypted_data) ;
103+ password. zeroize ( ) ;
104+ result
105+ }
106+
107+ pub fn decrypt_legacy_public ( password : & str , encrypted_data : & [ u8 ] ) -> Result < String , Error > {
108+ decrypt_legacy ( password, encrypted_data)
109+ }
110+
78111pub fn encrypt ( mut password : String , plaintext : String ) -> Vec < u8 > {
79112 let mut salt = [ 0u8 ; SALT_LEN ] ;
80113 aes_gcm:: aead:: OsRng . fill_bytes ( & mut salt) ;
0 commit comments