rustfs_crypto/encdec/
decrypt.rs

1// Copyright 2024 RustFS Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#[cfg(any(test, feature = "crypto"))]
16pub fn decrypt_data(password: &[u8], data: &[u8]) -> Result<Vec<u8>, crate::Error> {
17    use crate::encdec::id::ID;
18    use crate::error::Error;
19    use aes_gcm::{Aes256Gcm, KeyInit as _};
20    use chacha20poly1305::ChaCha20Poly1305;
21
22    // 32: salt
23    // 1: id
24    // 12: nonce
25    const HEADER_LENGTH: usize = 45;
26    if data.len() < HEADER_LENGTH {
27        return Err(Error::ErrUnexpectedHeader);
28    }
29
30    let (salt, id, nonce) = (&data[..32], ID::try_from(data[32])?, &data[33..45]);
31    let data = &data[HEADER_LENGTH..];
32
33    match id {
34        ID::Argon2idChaCHa20Poly1305 => {
35            let key = id.get_key(password, salt)?;
36            decryp(ChaCha20Poly1305::new_from_slice(&key)?, nonce, data)
37        }
38        _ => {
39            let key = id.get_key(password, salt)?;
40            decryp(Aes256Gcm::new_from_slice(&key)?, nonce, data)
41        }
42    }
43}
44
45// use argon2::{Argon2, PasswordHasher};
46// use argon2::password_hash::{SaltString};
47// use aes_gcm::{Aes256Gcm, Key, Nonce}; // For AES-GCM
48// use chacha20poly1305::{ChaCha20Poly1305, Key as ChaChaKey, Nonce as ChaChaNonce}; // For ChaCha20
49// use pbkdf2::pbkdf2;
50// use sha2::Sha256;
51// use std::io::{self, Read};
52// use thiserror::Error;
53
54// #[derive(Debug, Error)]
55// pub enum DecryptError {
56//     #[error("unexpected header")]
57//     UnexpectedHeader,
58//     #[error("invalid encryption algorithm ID")]
59//     InvalidAlgorithmId,
60//     #[error("IO error")]
61//     Io(#[from] io::Error),
62//     #[error("decryption error")]
63//     DecryptionError,
64// }
65
66// pub fn decrypt_data2<R: Read>(password: &str, mut data: R) -> Result<Vec<u8>, DecryptError> {
67//     // Parse the stream header
68//     let mut hdr = [0u8; 32 + 1 + 8];
69//     if data.read_exact(&mut hdr).is_err() {
70//         return Err(DecryptError::UnexpectedHeader);
71//     }
72
73//     let salt = &hdr[0..32];
74//     let id = hdr[32];
75//     let nonce = &hdr[33..41];
76
77//     let key = match id {
78//         // Argon2id + AES-GCM
79//         0x01 => {
80//             let salt = SaltString::encode_b64(salt).map_err(|_| DecryptError::DecryptionError)?;
81//             let argon2 = Argon2::default();
82//             let hashed_key = argon2.hash_password(password.as_bytes(), &salt)
83//                 .map_err(|_| DecryptError::DecryptionError)?;
84//             hashed_key.hash.unwrap().as_bytes().to_vec()
85//         }
86//         // Argon2id + ChaCha20Poly1305
87//         0x02 => {
88//             let salt = SaltString::encode_b64(salt).map_err(|_| DecryptError::DecryptionError)?;
89//             let argon2 = Argon2::default();
90//             let hashed_key = argon2.hash_password(password.as_bytes(), &salt)
91//                 .map_err(|_| DecryptError::DecryptionError)?;
92//             hashed_key.hash.unwrap().as_bytes().to_vec()
93//         }
94//         // PBKDF2 + AES-GCM
95//         // 0x03 => {
96//         //     let mut key = [0u8; 32];
97//         //     pbkdf2::<Sha256>(password.as_bytes(), salt, 10000, &mut key);
98//         //     key.to_vec()
99//         // }
100//         _ => return Err(DecryptError::InvalidAlgorithmId),
101//     };
102
103//     // Decrypt data using the corresponding cipher
104//     let mut encrypted_data = Vec::new();
105//     data.read_to_end(&mut encrypted_data)?;
106
107//     let plaintext = match id {
108//         0x01 => {
109//             let cipher = Aes256Gcm::new(Key::from_slice(&key));
110//             let nonce = Nonce::from_slice(nonce);
111//             cipher
112//                 .decrypt(nonce, encrypted_data.as_ref())
113//                 .map_err(|_| DecryptError::DecryptionError)?
114//         }
115//         0x02 => {
116//             let cipher = ChaCha20Poly1305::new(ChaChaKey::from_slice(&key));
117//             let nonce = ChaChaNonce::from_slice(nonce);
118//             cipher
119//                 .decrypt(nonce, encrypted_data.as_ref())
120//                 .map_err(|_| DecryptError::DecryptionError)?
121//         }
122//         0x03 => {
123
124//             let cipher = Aes256Gcm::new(Key::from_slice(&key));
125//             let nonce = Nonce::from_slice(nonce);
126//             cipher
127//                 .decrypt(nonce, encrypted_data.as_ref())
128//                 .map_err(|_| DecryptError::DecryptionError)?
129//         }
130//         _ => return Err(DecryptError::InvalidAlgorithmId),
131//     };
132
133//     Ok(plaintext)
134// }
135
136#[cfg(any(test, feature = "crypto"))]
137#[inline]
138fn decryp<T: aes_gcm::aead::Aead>(stream: T, nonce: &[u8], data: &[u8]) -> Result<Vec<u8>, crate::Error> {
139    use crate::error::Error;
140    stream
141        .decrypt(aes_gcm::Nonce::from_slice(nonce), data)
142        .map_err(Error::ErrDecryptFailed)
143}
144
145#[cfg(not(any(test, feature = "crypto")))]
146pub fn decrypt_data(_password: &[u8], data: &[u8]) -> Result<Vec<u8>, crate::Error> {
147    Ok(data.to_vec())
148}