diff --git a/Cargo.lock b/Cargo.lock index 0525d5e1..584e6f29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,37 +19,37 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aead" -version = "0.5.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +checksum = "1973cfbc1a2daf9cf550e74e1f088c28e7f7d8c1e1418fb6c9dc5184b7e84c99" dependencies = [ - "crypto-common 0.1.7", - "generic-array", + "crypto-common 0.2.2", + "inout", ] [[package]] name = "aes" -version = "0.8.4" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +checksum = "35f0f96ce78e38c3dc6d8948aa8163d06385be74000f3c7a95bf1eef35d3ea32" dependencies = [ - "cfg-if", "cipher", - "cpufeatures 0.2.17", + "cpubits", + "cpufeatures 0.3.0", ] [[package]] name = "aes-gcm" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +checksum = "7f2b8006a0c83f52b62ba44a97b58bf76fe2f70a329e588f67f89691d93d498f" dependencies = [ "aead", "aes", "cipher", "ctr", + "ctutils", "ghash", - "subtle", ] [[package]] @@ -621,11 +621,12 @@ dependencies = [ [[package]] name = "cipher" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c" dependencies = [ - "crypto-common 0.1.7", + "block-buffer 0.12.1", + "crypto-common 0.2.2", "inout", ] @@ -764,6 +765,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "cpubits" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -1066,7 +1073,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", - "rand_core 0.6.4", "typenum", ] @@ -1076,15 +1082,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ + "getrandom 0.4.3", "hybrid-array", "rand_core 0.10.1", ] [[package]] name = "ctr" -version = "0.9.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +checksum = "baaca1c4b237092596f64d571e9db6ce4109c4ef9742e27590f1709594461f21" dependencies = [ "cipher", ] @@ -1734,11 +1741,10 @@ dependencies = [ [[package]] name = "ghash" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +checksum = "2eecf2d5dc9b66b732b97707a0210906b1d30523eb773193ab777c0c84b3e8d5" dependencies = [ - "opaque-debug", "polyval", ] @@ -2223,11 +2229,11 @@ dependencies = [ [[package]] name = "inout" -version = "0.1.4" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] @@ -3016,12 +3022,6 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - [[package]] name = "openssl-probe" version = "0.2.1" @@ -3673,13 +3673,12 @@ dependencies = [ [[package]] name = "polyval" -version = "0.6.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +checksum = "f0fa31d631f2b2cb2a544d0aa321ce847a94764d701ca2becc411138b93d49cd" dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "opaque-debug", + "cpubits", + "cpufeatures 0.3.0", "universal-hash", ] @@ -5907,12 +5906,12 @@ dependencies = [ [[package]] name = "universal-hash" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +checksum = "f4987bdc12753382e0bec4a65c50738ffaabc998b9cdd1f952fb5f39b0048a96" dependencies = [ - "crypto-common 0.1.7", - "subtle", + "crypto-common 0.2.2", + "ctutils", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 5c954414..0eff8151 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,7 +81,7 @@ utoipa-swagger-ui = { version = "9", features = ["axum"] } # aead::OsRng convenience API used in orch8-types/src/encryption.rs. No # advisory forces the move, so we don't take on a crypto-code migration for a # version-number bump alone. Revisit together, deliberately, if ever needed. -aes-gcm = "0.10" +aes-gcm = "0.11" base64 = "0.23" # HTTP client diff --git a/orch8-types/src/encryption.rs b/orch8-types/src/encryption.rs index 62fbb51e..255e3db0 100644 --- a/orch8-types/src/encryption.rs +++ b/orch8-types/src/encryption.rs @@ -13,8 +13,8 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; -use aes_gcm::aead::{Aead, KeyInit, OsRng, Payload}; -use aes_gcm::{AeadCore, Aes256Gcm, Nonce}; +use aes_gcm::Aes256Gcm; +use aes_gcm::aead::{Aead, Generate, KeyInit, Nonce, Payload}; use base64::Engine; use base64::engine::general_purpose::STANDARD as B64; use zeroize::Zeroize; @@ -89,8 +89,8 @@ impl FieldEncryptor { key_bytes.zeroize(); return Err(EncryptionError::InvalidKeyLength(len)); } - let key = aes_gcm::Key::::from_slice(&key_bytes); - let cipher = Aes256Gcm::new(key); + let cipher = Aes256Gcm::new_from_slice(&key_bytes) + .map_err(|_| EncryptionError::InvalidKeyLength(len))?; key_bytes.zeroize(); Ok(Self { cipher, @@ -104,9 +104,8 @@ impl FieldEncryptor { /// Create an encryptor from raw 32 bytes. #[must_use] pub fn from_bytes(key: &[u8; 32]) -> Self { - let key = aes_gcm::Key::::from_slice(key); Self { - cipher: Aes256Gcm::new(key), + cipher: Aes256Gcm::new(key.into()), old_cipher: None, encrypt_count: Arc::new(AtomicU64::new(0)), budget_warned: Arc::new(AtomicBool::new(false)), @@ -165,8 +164,10 @@ impl FieldEncryptor { key_bytes.zeroize(); return Err(EncryptionError::InvalidKeyLength(len)); } - let key = aes_gcm::Key::::from_slice(&key_bytes); - self.old_cipher = Some(Aes256Gcm::new(key)); + self.old_cipher = Some( + Aes256Gcm::new_from_slice(&key_bytes) + .map_err(|_| EncryptionError::InvalidKeyLength(len))?, + ); key_bytes.zeroize(); Ok(self) } @@ -177,7 +178,7 @@ impl FieldEncryptor { value: &serde_json::Value, ) -> Result { let plaintext = serde_json::to_vec(value)?; - let nonce = Aes256Gcm::generate_nonce(&mut OsRng); + let nonce = Nonce::::generate(); let ciphertext = self .cipher .encrypt(&nonce, plaintext.as_slice()) @@ -222,10 +223,11 @@ impl FieldEncryptor { return Err(EncryptionError::InvalidCiphertext); } let (nonce_bytes, ciphertext) = payload.split_at(12); - let nonce = Nonce::from_slice(nonce_bytes); + let nonce = Nonce::::try_from(nonce_bytes) + .map_err(|_| EncryptionError::InvalidCiphertext)?; // Try primary key first. - if let Ok(plaintext) = self.cipher.decrypt(nonce, ciphertext) { + if let Ok(plaintext) = self.cipher.decrypt(&nonce, ciphertext) { let value = serde_json::from_slice(&plaintext)?; return Ok(value); } @@ -233,7 +235,7 @@ impl FieldEncryptor { // Fall back to old key if present. if let Some(ref old) = self.old_cipher { let plaintext = old - .decrypt(nonce, ciphertext) + .decrypt(&nonce, ciphertext) .map_err(|_| EncryptionError::DecryptFailed)?; let value = serde_json::from_slice(&plaintext)?; return Ok(value); @@ -277,7 +279,7 @@ impl FieldEncryptor { aad: &[u8], ) -> Result { let plaintext = serde_json::to_vec(value)?; - let nonce = Aes256Gcm::generate_nonce(&mut OsRng); + let nonce = Nonce::::generate(); let ciphertext = self .cipher .encrypt( @@ -323,10 +325,11 @@ impl FieldEncryptor { return Err(EncryptionError::InvalidCiphertext); } let (nonce_bytes, ciphertext) = payload.split_at(12); - let nonce = Nonce::from_slice(nonce_bytes); + let nonce = Nonce::::try_from(nonce_bytes) + .map_err(|_| EncryptionError::InvalidCiphertext)?; if let Ok(plaintext) = self.cipher.decrypt( - nonce, + &nonce, Payload { msg: ciphertext, aad, @@ -337,7 +340,7 @@ impl FieldEncryptor { if let Some(ref old) = self.old_cipher { let plaintext = old .decrypt( - nonce, + &nonce, Payload { msg: ciphertext, aad, @@ -361,7 +364,7 @@ impl FieldEncryptor { /// # Errors /// Returns [`EncryptionError::EncryptFailed`] if the AEAD seal fails. pub fn encrypt_bytes(&self, plaintext: &[u8]) -> Result, EncryptionError> { - let nonce = Aes256Gcm::generate_nonce(&mut OsRng); + let nonce = Nonce::::generate(); let ciphertext = self .cipher .encrypt(&nonce, plaintext) @@ -381,7 +384,7 @@ impl FieldEncryptor { plaintext: &[u8], aad: &[u8], ) -> Result, EncryptionError> { - let nonce = Aes256Gcm::generate_nonce(&mut OsRng); + let nonce = Nonce::::generate(); let ciphertext = self .cipher .encrypt( @@ -410,13 +413,14 @@ impl FieldEncryptor { return Err(EncryptionError::InvalidCiphertext); } let (nonce_bytes, ciphertext) = sealed.split_at(12); - let nonce = Nonce::from_slice(nonce_bytes); - if let Ok(plain) = self.cipher.decrypt(nonce, ciphertext) { + let nonce = Nonce::::try_from(nonce_bytes) + .map_err(|_| EncryptionError::InvalidCiphertext)?; + if let Ok(plain) = self.cipher.decrypt(&nonce, ciphertext) { return Ok(plain); } if let Some(ref old) = self.old_cipher { return old - .decrypt(nonce, ciphertext) + .decrypt(&nonce, ciphertext) .map_err(|_| EncryptionError::DecryptFailed); } Err(EncryptionError::DecryptFailed) @@ -433,18 +437,19 @@ impl FieldEncryptor { return Err(EncryptionError::InvalidCiphertext); } let (nonce_bytes, ciphertext) = sealed.split_at(12); - let nonce = Nonce::from_slice(nonce_bytes); + let nonce = Nonce::::try_from(nonce_bytes) + .map_err(|_| EncryptionError::InvalidCiphertext)?; let payload = Payload { msg: ciphertext, aad, }; - if let Ok(plain) = self.cipher.decrypt(nonce, payload) { + if let Ok(plain) = self.cipher.decrypt(&nonce, payload) { return Ok(plain); } if let Some(ref old) = self.old_cipher { return old .decrypt( - nonce, + &nonce, Payload { msg: ciphertext, aad,