rustfs_crypto/encdec/
encrypt.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 encrypt_data(password: &[u8], data: &[u8]) -> Result<Vec<u8>, crate::Error> {
17    use crate::encdec::id::ID;
18    use aes_gcm::Aes256Gcm;
19    use aes_gcm::KeyInit as _;
20    use rand::random;
21
22    let salt: [u8; 32] = random();
23
24    #[cfg(feature = "fips")]
25    let id = ID::Pbkdf2AESGCM;
26
27    #[cfg(not(feature = "fips"))]
28    let id = if native_aes() {
29        ID::Argon2idAESGCM
30    } else {
31        ID::Argon2idChaCHa20Poly1305
32    };
33
34    let key = id.get_key(password, &salt)?;
35
36    #[cfg(feature = "fips")]
37    {
38        encrypt(Aes256Gcm::new_from_slice(&key)?, &salt, id, data)
39    }
40
41    #[cfg(not(feature = "fips"))]
42    {
43        if native_aes() {
44            encrypt(Aes256Gcm::new_from_slice(&key)?, &salt, id, data)
45        } else {
46            encrypt(ChaCha20Poly1305::new_from_slice(&key)?, &salt, id, data)
47        }
48    }
49}
50
51#[cfg(any(test, feature = "crypto"))]
52fn encrypt<T: aes_gcm::aead::Aead>(
53    stream: T,
54    salt: &[u8],
55    id: crate::encdec::id::ID,
56    data: &[u8],
57) -> Result<Vec<u8>, crate::Error> {
58    use crate::error::Error;
59    use aes_gcm::aead::rand_core::OsRng;
60
61    let nonce = T::generate_nonce(&mut OsRng);
62
63    let encryptor = stream.encrypt(&nonce, data).map_err(Error::ErrEncryptFailed)?;
64
65    let mut ciphertext = Vec::with_capacity(salt.len() + 1 + nonce.len() + encryptor.len());
66    ciphertext.extend_from_slice(salt);
67    ciphertext.push(id as u8);
68    ciphertext.extend_from_slice(nonce.as_slice());
69    ciphertext.extend_from_slice(&encryptor);
70
71    Ok(ciphertext)
72}
73
74#[cfg(not(any(test, feature = "crypto")))]
75pub fn encrypt_data(_password: &[u8], data: &[u8]) -> Result<Vec<u8>, crate::Error> {
76    Ok(data.to_vec())
77}