mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-11 23:56:53 +00:00
🔒 Upgrade Cryptography Libraries to Latest RC Versions (#837)
* fix * chore: upgrade cryptography libraries to RC versions - Upgrade aes-gcm to 0.11.0-rc.2 with rand_core support - Upgrade chacha20poly1305 to 0.11.0-rc.2 - Upgrade argon2 to 0.6.0-rc.2 with std features - Upgrade hmac to 0.13.0-rc.3 - Upgrade pbkdf2 to 0.13.0-rc.2 - Upgrade rsa to 0.10.0-rc.10 - Upgrade sha1 and sha2 to 0.11.0-rc.3 - Upgrade md-5 to 0.11.0-rc.3 These upgrades provide enhanced security features and performance improvements while maintaining backward compatibility with existing encryption workflows. * add * improve code * fix
This commit is contained in:
@@ -19,12 +19,12 @@ use crate::config::KmsConfig;
|
||||
use crate::config::LocalConfig;
|
||||
use crate::error::{KmsError, Result};
|
||||
use crate::types::*;
|
||||
use aes_gcm::aead::rand_core::RngCore;
|
||||
use aes_gcm::{
|
||||
Aes256Gcm, Key, Nonce,
|
||||
aead::{Aead, AeadCore, KeyInit, OsRng},
|
||||
aead::{Aead, KeyInit},
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use rand::Rng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
@@ -105,8 +105,9 @@ impl LocalKmsClient {
|
||||
hasher.update(master_key.as_bytes());
|
||||
hasher.update(b"rustfs-kms-local"); // Salt to prevent rainbow tables
|
||||
let hash = hasher.finalize();
|
||||
|
||||
Ok(*Key::<Aes256Gcm>::from_slice(&hash))
|
||||
let key = Key::<Aes256Gcm>::try_from(hash.as_slice())
|
||||
.map_err(|_| KmsError::cryptographic_error("key", "Invalid key length"))?;
|
||||
Ok(key)
|
||||
}
|
||||
|
||||
/// Get the file path for a master key
|
||||
@@ -117,7 +118,6 @@ impl LocalKmsClient {
|
||||
/// Load a master key from disk
|
||||
async fn load_master_key(&self, key_id: &str) -> Result<MasterKey> {
|
||||
let key_path = self.master_key_path(key_id);
|
||||
|
||||
if !key_path.exists() {
|
||||
return Err(KmsError::key_not_found(key_id));
|
||||
}
|
||||
@@ -127,9 +127,16 @@ impl LocalKmsClient {
|
||||
|
||||
// Decrypt key material if master cipher is available
|
||||
let _key_material = if let Some(ref cipher) = self.master_cipher {
|
||||
let nonce = Nonce::from_slice(&stored_key.nonce);
|
||||
if stored_key.nonce.len() != 12 {
|
||||
return Err(KmsError::cryptographic_error("nonce", "Invalid nonce length"));
|
||||
}
|
||||
|
||||
let mut nonce_array = [0u8; 12];
|
||||
nonce_array.copy_from_slice(&stored_key.nonce);
|
||||
let nonce = Nonce::from(nonce_array);
|
||||
|
||||
cipher
|
||||
.decrypt(nonce, stored_key.encrypted_key_material.as_ref())
|
||||
.decrypt(&nonce, stored_key.encrypted_key_material.as_ref())
|
||||
.map_err(|e| KmsError::cryptographic_error("decrypt", e.to_string()))?
|
||||
} else {
|
||||
stored_key.encrypted_key_material
|
||||
@@ -155,7 +162,10 @@ impl LocalKmsClient {
|
||||
|
||||
// Encrypt key material if master cipher is available
|
||||
let (encrypted_key_material, nonce) = if let Some(ref cipher) = self.master_cipher {
|
||||
let nonce = Aes256Gcm::generate_nonce(&mut OsRng);
|
||||
let mut nonce_bytes = [0u8; 12];
|
||||
rand::rng().fill(&mut nonce_bytes[..]);
|
||||
let nonce = Nonce::from(nonce_bytes);
|
||||
|
||||
let encrypted = cipher
|
||||
.encrypt(&nonce, key_material)
|
||||
.map_err(|e| KmsError::cryptographic_error("encrypt", e.to_string()))?;
|
||||
@@ -202,7 +212,7 @@ impl LocalKmsClient {
|
||||
/// Generate a random 256-bit key
|
||||
fn generate_key_material() -> Vec<u8> {
|
||||
let mut key_material = vec![0u8; 32]; // 256 bits
|
||||
OsRng.fill_bytes(&mut key_material);
|
||||
rand::rng().fill(&mut key_material[..]);
|
||||
key_material
|
||||
}
|
||||
|
||||
@@ -219,9 +229,14 @@ impl LocalKmsClient {
|
||||
|
||||
// Decrypt key material if master cipher is available
|
||||
let key_material = if let Some(ref cipher) = self.master_cipher {
|
||||
let nonce = Nonce::from_slice(&stored_key.nonce);
|
||||
if stored_key.nonce.len() != 12 {
|
||||
return Err(KmsError::cryptographic_error("nonce", "Invalid nonce length"));
|
||||
}
|
||||
let mut nonce_array = [0u8; 12];
|
||||
nonce_array.copy_from_slice(&stored_key.nonce);
|
||||
let nonce = Nonce::from(nonce_array);
|
||||
cipher
|
||||
.decrypt(nonce, stored_key.encrypted_key_material.as_ref())
|
||||
.decrypt(&nonce, stored_key.encrypted_key_material.as_ref())
|
||||
.map_err(|e| KmsError::cryptographic_error("decrypt", e.to_string()))?
|
||||
} else {
|
||||
stored_key.encrypted_key_material
|
||||
@@ -234,25 +249,39 @@ impl LocalKmsClient {
|
||||
async fn encrypt_with_master_key(&self, key_id: &str, plaintext: &[u8]) -> Result<(Vec<u8>, Vec<u8>)> {
|
||||
// Load the actual master key material
|
||||
let key_material = self.get_key_material(key_id).await?;
|
||||
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(&key_material));
|
||||
let key = Key::<Aes256Gcm>::try_from(key_material.as_slice())
|
||||
.map_err(|_| KmsError::cryptographic_error("key", "Invalid key length"))?;
|
||||
let cipher = Aes256Gcm::new(&key);
|
||||
|
||||
let mut nonce_bytes = [0u8; 12];
|
||||
rand::rng().fill(&mut nonce_bytes[..]);
|
||||
|
||||
let nonce = Nonce::from(nonce_bytes);
|
||||
|
||||
let nonce = Aes256Gcm::generate_nonce(&mut OsRng);
|
||||
let ciphertext = cipher
|
||||
.encrypt(&nonce, plaintext)
|
||||
.map_err(|e| KmsError::cryptographic_error("encrypt", e.to_string()))?;
|
||||
|
||||
Ok((ciphertext, nonce.to_vec()))
|
||||
Ok((ciphertext, nonce_bytes.to_vec()))
|
||||
}
|
||||
|
||||
/// Decrypt data using a master key
|
||||
async fn decrypt_with_master_key(&self, key_id: &str, ciphertext: &[u8], nonce: &[u8]) -> Result<Vec<u8>> {
|
||||
if nonce.len() != 12 {
|
||||
return Err(KmsError::cryptographic_error("nonce", "Invalid nonce length"));
|
||||
}
|
||||
// Load the actual master key material
|
||||
let key_material = self.get_key_material(key_id).await?;
|
||||
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(&key_material));
|
||||
let key = Key::<Aes256Gcm>::try_from(key_material.as_slice())
|
||||
.map_err(|_| KmsError::cryptographic_error("key", "Invalid key length"))?;
|
||||
let cipher = Aes256Gcm::new(&key);
|
||||
|
||||
let mut nonce_array = [0u8; 12];
|
||||
nonce_array.copy_from_slice(nonce);
|
||||
let nonce_ref = Nonce::from(nonce_array);
|
||||
|
||||
let nonce = Nonce::from_slice(nonce);
|
||||
let plaintext = cipher
|
||||
.decrypt(nonce, ciphertext)
|
||||
.decrypt(&nonce_ref, ciphertext)
|
||||
.map_err(|e| KmsError::cryptographic_error("decrypt", e.to_string()))?;
|
||||
|
||||
Ok(plaintext)
|
||||
@@ -275,7 +304,7 @@ impl KmsClient for LocalKmsClient {
|
||||
};
|
||||
|
||||
let mut plaintext_key = vec![0u8; key_length];
|
||||
OsRng.fill_bytes(&mut plaintext_key);
|
||||
rand::rng().fill(&mut plaintext_key[..]);
|
||||
|
||||
// Encrypt the data key with the master key
|
||||
let (encrypted_key, nonce) = self.encrypt_with_master_key(&request.master_key_id, &plaintext_key).await?;
|
||||
@@ -776,9 +805,14 @@ impl KmsBackend for LocalKmsBackend {
|
||||
|
||||
// Decrypt the existing key material to preserve it
|
||||
let existing_key_material = if let Some(ref cipher) = self.client.master_cipher {
|
||||
let nonce = Nonce::from_slice(&stored_key.nonce);
|
||||
if stored_key.nonce.len() != 12 {
|
||||
return Err(KmsError::cryptographic_error("nonce", "Invalid nonce length"));
|
||||
}
|
||||
let mut nonce_array = [0u8; 12];
|
||||
nonce_array.copy_from_slice(&stored_key.nonce);
|
||||
let nonce = Nonce::from(nonce_array);
|
||||
cipher
|
||||
.decrypt(nonce, stored_key.encrypted_key_material.as_ref())
|
||||
.decrypt(&nonce, stored_key.encrypted_key_material.as_ref())
|
||||
.map_err(|e| KmsError::cryptographic_error("decrypt", e.to_string()))?
|
||||
} else {
|
||||
stored_key.encrypted_key_material
|
||||
|
||||
@@ -20,7 +20,6 @@ use async_trait::async_trait;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub mod local;
|
||||
|
||||
pub mod vault;
|
||||
|
||||
/// Abstract KMS client interface that all backends must implement
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
use crate::error::{KmsError, Result};
|
||||
use crate::types::EncryptionAlgorithm;
|
||||
use aes_gcm::aead::rand_core::RngCore;
|
||||
use aes_gcm::{
|
||||
Aes256Gcm, Key, Nonce,
|
||||
aead::{Aead, KeyInit, OsRng},
|
||||
aead::{Aead, KeyInit},
|
||||
};
|
||||
use chacha20poly1305::ChaCha20Poly1305;
|
||||
use rand::Rng;
|
||||
|
||||
/// Trait for object encryption ciphers
|
||||
#[cfg_attr(not(test), allow(dead_code))]
|
||||
@@ -57,8 +57,8 @@ impl AesCipher {
|
||||
return Err(KmsError::invalid_key_size(32, key.len()));
|
||||
}
|
||||
|
||||
let key = Key::<Aes256Gcm>::from_slice(key);
|
||||
let cipher = Aes256Gcm::new(key);
|
||||
let key = Key::<Aes256Gcm>::try_from(key).map_err(|_| KmsError::cryptographic_error("key", "Invalid key length"))?;
|
||||
let cipher = Aes256Gcm::new(&key);
|
||||
|
||||
Ok(Self { cipher })
|
||||
}
|
||||
@@ -70,12 +70,12 @@ impl ObjectCipher for AesCipher {
|
||||
return Err(KmsError::invalid_key_size(12, iv.len()));
|
||||
}
|
||||
|
||||
let nonce = Nonce::from_slice(iv);
|
||||
let nonce = Nonce::try_from(iv).map_err(|_| KmsError::cryptographic_error("nonce", "Invalid nonce length"))?;
|
||||
|
||||
// AES-GCM includes the tag in the ciphertext
|
||||
let ciphertext_with_tag = self
|
||||
.cipher
|
||||
.encrypt(nonce, aes_gcm::aead::Payload { msg: plaintext, aad })
|
||||
.encrypt(&nonce, aes_gcm::aead::Payload { msg: plaintext, aad })
|
||||
.map_err(KmsError::from_aes_gcm_error)?;
|
||||
|
||||
// Split ciphertext and tag
|
||||
@@ -98,7 +98,7 @@ impl ObjectCipher for AesCipher {
|
||||
return Err(KmsError::invalid_key_size(self.tag_size(), tag.len()));
|
||||
}
|
||||
|
||||
let nonce = Nonce::from_slice(iv);
|
||||
let nonce = Nonce::try_from(iv).map_err(|_| KmsError::cryptographic_error("nonce", "Invalid nonce length"))?;
|
||||
|
||||
// Combine ciphertext and tag for AES-GCM
|
||||
let mut ciphertext_with_tag = ciphertext.to_vec();
|
||||
@@ -107,7 +107,7 @@ impl ObjectCipher for AesCipher {
|
||||
let plaintext = self
|
||||
.cipher
|
||||
.decrypt(
|
||||
nonce,
|
||||
&nonce,
|
||||
aes_gcm::aead::Payload {
|
||||
msg: &ciphertext_with_tag,
|
||||
aad,
|
||||
@@ -147,8 +147,8 @@ impl ChaCha20Cipher {
|
||||
return Err(KmsError::invalid_key_size(32, key.len()));
|
||||
}
|
||||
|
||||
let key = chacha20poly1305::Key::from_slice(key);
|
||||
let cipher = ChaCha20Poly1305::new(key);
|
||||
let key = chacha20poly1305::Key::try_from(key).map_err(|_| KmsError::cryptographic_error("key", "Invalid key length"))?;
|
||||
let cipher = ChaCha20Poly1305::new(&key);
|
||||
|
||||
Ok(Self { cipher })
|
||||
}
|
||||
@@ -160,12 +160,13 @@ impl ObjectCipher for ChaCha20Cipher {
|
||||
return Err(KmsError::invalid_key_size(12, iv.len()));
|
||||
}
|
||||
|
||||
let nonce = chacha20poly1305::Nonce::from_slice(iv);
|
||||
let nonce =
|
||||
chacha20poly1305::Nonce::try_from(iv).map_err(|_| KmsError::cryptographic_error("nonce", "Invalid nonce length"))?;
|
||||
|
||||
// ChaCha20-Poly1305 includes the tag in the ciphertext
|
||||
let ciphertext_with_tag = self
|
||||
.cipher
|
||||
.encrypt(nonce, chacha20poly1305::aead::Payload { msg: plaintext, aad })
|
||||
.encrypt(&nonce, chacha20poly1305::aead::Payload { msg: plaintext, aad })
|
||||
.map_err(KmsError::from_chacha20_error)?;
|
||||
|
||||
// Split ciphertext and tag
|
||||
@@ -188,7 +189,8 @@ impl ObjectCipher for ChaCha20Cipher {
|
||||
return Err(KmsError::invalid_key_size(self.tag_size(), tag.len()));
|
||||
}
|
||||
|
||||
let nonce = chacha20poly1305::Nonce::from_slice(iv);
|
||||
let nonce =
|
||||
chacha20poly1305::Nonce::try_from(iv).map_err(|_| KmsError::cryptographic_error("nonce", "Invalid nonce length"))?;
|
||||
|
||||
// Combine ciphertext and tag for ChaCha20-Poly1305
|
||||
let mut ciphertext_with_tag = ciphertext.to_vec();
|
||||
@@ -197,7 +199,7 @@ impl ObjectCipher for ChaCha20Cipher {
|
||||
let plaintext = self
|
||||
.cipher
|
||||
.decrypt(
|
||||
nonce,
|
||||
&nonce,
|
||||
chacha20poly1305::aead::Payload {
|
||||
msg: &ciphertext_with_tag,
|
||||
aad,
|
||||
@@ -241,7 +243,7 @@ pub fn generate_iv(algorithm: &EncryptionAlgorithm) -> Vec<u8> {
|
||||
};
|
||||
|
||||
let mut iv = vec![0u8; iv_size];
|
||||
OsRng.fill_bytes(&mut iv);
|
||||
rand::rng().fill(&mut iv[..]);
|
||||
iv
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user