chore(deps): upgrade RustCrypto stack to latest versions

Upgrade all cryptography dependencies to their latest versions and
migrate the codebase to the new RustCrypto 0.11 ecosystem APIs.

Dependency updates:
- aes-gcm 0.10 -> 0.11.0-rc.3
- aes-gcm-siv 0.11 -> 0.12.0-rc.3
- ccm 0.5 -> 0.6.0-rc.3
- chacha20poly1305 0.10 -> 0.11.0-rc.3
- aead 0.5 -> 0.6.0-rc.10
- aes 0.8 -> 0.9
- chacha20 0.9 -> 0.10
- ctr 0.9 -> 0.10
- camellia 0.1 -> 0.2
- sm4 0.5 -> 0.6
- ghash 0.5 -> 0.6
- subtle 2.5 -> 2.6
- bytes 1.3 -> 1.11
- blake3 1.3 -> 1.8

The AEAD crates remain on their 0.11 rc releases because the stable
0.10 line still pins aes 0.8 and ghash 0.5, which would conflict with
the upgraded block/universal-hash stack.

API migration:
- Replace aead::generic_array with aead::array (hybrid-array)
- Replace AeadInPlace with AeadInOut (encrypt_inout_detached /
  decrypt_inout_detached take InOutBuf)
- Update AeadCore impl for SM4-GCM: drop CiphertextOverhead, add
  TAG_POSITION constant
- Replace deprecated Array::from_slice / from_mut_slice with TryFrom
- Rename cipher::{BlockEncrypt, BlockDecrypt} imports to their
  BlockCipher{Encrypt,Decrypt} counterparts
- Import Unsigned from typenum (cipher::typenum / aead::array::typenum)
- Use cipher::Iv for chacha20 nonce (Nonce is no longer re-exported)

Also bump rust-version to 1.85 to match the MSRV of the new
RustCrypto crates.
This commit is contained in:
ty authored and ty committed 2026-08-27 01:25:38 +08:00
1 parent 2affa6c39b
commit 31e8910b6a
15 files changed
+198 -156

No files matched your search

+15 -15
View File
@@ -8,7 +8,7 @@ keywords = ["Cryptography"]
description = "Shadowsocks Crypto"
repository = "https://github.com/shadowsocks/shadowsocks-crypto"
documentation = "https://docs.rs/shadowsocks-crypto"
rust-version = "1.71"
rust-version = "1.85"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
@@ -39,10 +39,10 @@ aws-lc = ["dep:aws-lc-rs"]
[dependencies]
cfg-if = { version = "1.0", optional = true }
rand = "0.10"
aes-gcm = { version = "0.10", optional = true }
aes-gcm-siv = { version = "0.11", optional = true }
ccm = { version = "0.5", optional = true }
chacha20poly1305 = { version = "0.10", optional = true }
aes-gcm = { version = "0.11.0-rc.3", optional = true }
aes-gcm-siv = { version = "0.12.0-rc.3", optional = true }
ccm = { version = "0.6.0-rc.3", optional = true }
chacha20poly1305 = { version = "0.11.0-rc.3", optional = true }
ring-compat = { version = "0.8", default-features = false, features = [
"aead",
"alloc",
@@ -51,16 +51,16 @@ aws-lc-rs = { version = "1.16", optional = true }
md-5 = { version = "0.11", optional = true }
hkdf = { version = "0.13", optional = true }
sha1 = { version = "0.11", optional = true }
blake3 = { version = "1.3", optional = true }
chacha20 = { version = "0.9", features = [], optional = true }
aes = { version = "0.8", optional = true }
ctr = { version = "0.9", optional = true }
bytes = { version = "1.3", optional = true }
camellia = { version = "0.1", optional = true }
sm4 = { version = "0.5", optional = true }
ghash = { version = "0.5", optional = true }
aead = { version = "0.5", optional = true }
subtle = { version = "2.5", optional = true }
blake3 = { version = "1.8", optional = true }
chacha20 = { version = "0.10", features = [], optional = true }
aes = { version = "0.9", optional = true }
ctr = { version = "0.10", optional = true }
bytes = { version = "1.11", optional = true }
camellia = { version = "0.2", optional = true }
sm4 = { version = "0.6", optional = true }
ghash = { version = "0.6", optional = true }
aead = { version = "0.6.0-rc.10", optional = true }
subtle = { version = "2.6", optional = true }
#[target.'cfg(all(unix, any(target_arch = "x86", target_arch = "x86_64")))'.dependencies]
#md-5 = { version = "0.10", features = ["asm"] }
+17 -11
View File
@@ -1,6 +1,6 @@
use aes::{Aes128, Aes256};
use ccm::{
aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeyInit, KeySizeUser},
aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeyInit, KeySizeUser},
consts::{U12, U16},
Ccm,
Nonce,
@@ -27,22 +27,25 @@ impl Aes128Ccm {
}
pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::<U12>::try_from(nonce).expect("AES_128_CCM nonce");
let (plaintext, out_tag) =
plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size());
let tag = self
.0
.encrypt_in_place_detached(nonce, &[], plaintext)
.encrypt_inout_detached(&nonce, &[], plaintext.into())
.expect("AES_128_CCM encrypt");
out_tag.copy_from_slice(tag.as_slice())
}
pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::<U12>::try_from(nonce).expect("AES_128_CCM nonce");
let (ciphertext, in_tag) =
ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size());
let in_tag = Tag::from_slice(in_tag);
self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok()
let in_tag = match Tag::<U16>::try_from(&*in_tag) {
Ok(t) => t,
Err(_) => return false,
};
self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok()
}
}
@@ -66,21 +69,24 @@ impl Aes256Ccm {
}
pub fn encrypt(&mut self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::<U12>::try_from(nonce).expect("AES_256_CCM nonce");
let (plaintext, out_tag) =
plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size());
let tag = self
.0
.encrypt_in_place_detached(nonce, &[], plaintext)
.encrypt_inout_detached(&nonce, &[], plaintext.into())
.expect("AES_256_CCM encrypt");
out_tag.copy_from_slice(tag.as_slice())
}
pub fn decrypt(&mut self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::<U12>::try_from(nonce).expect("AES_256_CCM nonce");
let (ciphertext, in_tag) =
ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size());
let in_tag = Tag::from_slice(in_tag);
self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok()
let in_tag = match Tag::<U16>::try_from(&*in_tag) {
Ok(t) => t,
Err(_) => return false,
};
self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok()
}
}
+25 -18
View File
@@ -99,19 +99,20 @@ cfg_if! {
}
} else {
use aes_gcm::{
aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeySizeUser, KeyInit},
Key,
Nonce,
Tag,
aead::{self, array::typenum::Unsigned, AeadCore, AeadInOut, KeySizeUser, KeyInit},
};
use aes_gcm::{Aes128Gcm as CryptoAes128Gcm, Aes256Gcm as CryptoAes256Gcm};
type Key<A> = aead::Key<A>;
type Nonce<A> = aead::Nonce<A>;
type Tag<A> = aead::Tag<A>;
pub struct Aes128Gcm(Box<CryptoAes128Gcm>);
impl Aes128Gcm {
pub fn new(key: &[u8]) -> Aes128Gcm {
let key = Key::<CryptoAes128Gcm>::from_slice(key);
Aes128Gcm(Box::new(CryptoAes128Gcm::new(key)))
let key = Key::<CryptoAes128Gcm>::try_from(key).expect("AES_128_GCM key");
Aes128Gcm(Box::new(CryptoAes128Gcm::new(&key)))
}
pub fn key_size() -> usize {
@@ -127,22 +128,25 @@ cfg_if! {
}
pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::<CryptoAes128Gcm>::try_from(nonce).expect("AES_128_GCM nonce");
let (plaintext, out_tag) =
plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size());
let tag = self
.0
.encrypt_in_place_detached(nonce, &[], plaintext)
.encrypt_inout_detached(&nonce, &[], plaintext.into())
.expect("AES_128_GCM encrypt");
out_tag.copy_from_slice(tag.as_slice())
}
pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::<CryptoAes128Gcm>::try_from(nonce).expect("AES_128_GCM nonce");
let (ciphertext, in_tag) =
ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size());
let in_tag = Tag::from_slice(in_tag);
self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok()
let in_tag = match Tag::<CryptoAes128Gcm>::try_from(&*in_tag) {
Ok(t) => t,
Err(_) => return false,
};
self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok()
}
}
@@ -150,8 +154,8 @@ cfg_if! {
impl Aes256Gcm {
pub fn new(key: &[u8]) -> Aes256Gcm {
let key = Key::<CryptoAes256Gcm>::from_slice(key);
Aes256Gcm(Box::new(CryptoAes256Gcm::new(key)))
let key = Key::<CryptoAes256Gcm>::try_from(key).expect("AES_256_GCM key");
Aes256Gcm(Box::new(CryptoAes256Gcm::new(&key)))
}
pub fn key_size() -> usize {
@@ -167,22 +171,25 @@ cfg_if! {
}
pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::<CryptoAes256Gcm>::try_from(nonce).expect("AES_256_GCM nonce");
let (plaintext, out_tag) =
plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size());
let tag = self
.0
.encrypt_in_place_detached(nonce, &[], plaintext)
.encrypt_inout_detached(&nonce, &[], plaintext.into())
.expect("AES_256_GCM encrypt");
out_tag.copy_from_slice(tag.as_slice())
}
pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::<CryptoAes256Gcm>::try_from(nonce).expect("AES_256_GCM nonce");
let (ciphertext, in_tag) =
ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size());
let in_tag = Tag::from_slice(in_tag);
self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok()
let in_tag = match Tag::<CryptoAes256Gcm>::try_from(&*in_tag) {
Ok(t) => t,
Err(_) => return false,
};
self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok()
}
}
}
+21 -15
View File
@@ -66,7 +66,7 @@ cfg_if! {
aead_gcm_siv_cipher!(Aes256GcmSiv, AES_256_GCM_SIV);
} else {
use aes_gcm_siv::{
aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeyInit, KeySizeUser},
aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeyInit, KeySizeUser},
Aes128GcmSiv as CryptoAes128GcmSiv,
Aes256GcmSiv as CryptoAes256GcmSiv,
Key,
@@ -78,8 +78,8 @@ cfg_if! {
impl Aes128GcmSiv {
pub fn new(key: &[u8]) -> Aes128GcmSiv {
let key = Key::<CryptoAes128GcmSiv>::from_slice(key);
Aes128GcmSiv(CryptoAes128GcmSiv::new(key))
let key = Key::<CryptoAes128GcmSiv>::try_from(key).expect("AES_128_GCM_SIV key");
Aes128GcmSiv(CryptoAes128GcmSiv::new(&key))
}
pub fn key_size() -> usize {
@@ -95,22 +95,25 @@ cfg_if! {
}
pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::try_from(nonce).expect("AES_128_GCM_SIV nonce");
let (plaintext, out_tag) =
plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size());
let tag = self
.0
.encrypt_in_place_detached(nonce, &[], plaintext)
.encrypt_inout_detached(&nonce, &[], plaintext.into())
.expect("AES_128_GCM_SIV encrypt");
out_tag.copy_from_slice(tag.as_slice())
}
pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::try_from(nonce).expect("AES_128_GCM_SIV nonce");
let (ciphertext, in_tag) =
ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size());
let in_tag = Tag::from_slice(in_tag);
self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok()
let in_tag = match Tag::try_from(&*in_tag) {
Ok(t) => t,
Err(_) => return false,
};
self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok()
}
}
@@ -118,8 +121,8 @@ cfg_if! {
impl Aes256GcmSiv {
pub fn new(key: &[u8]) -> Aes256GcmSiv {
let key = Key::<CryptoAes256GcmSiv>::from_slice(key);
Aes256GcmSiv(CryptoAes256GcmSiv::new(key))
let key = Key::<CryptoAes256GcmSiv>::try_from(key).expect("AES_256_GCM_SIV key");
Aes256GcmSiv(CryptoAes256GcmSiv::new(&key))
}
pub fn key_size() -> usize {
@@ -135,22 +138,25 @@ cfg_if! {
}
pub fn encrypt(&mut self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::try_from(nonce).expect("AES_256_GCM_SIV nonce");
let (plaintext, out_tag) =
plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size());
let tag = self
.0
.encrypt_in_place_detached(nonce, &[], plaintext)
.encrypt_inout_detached(&nonce, &[], plaintext.into())
.expect("AES_256_GCM_SIV encrypt");
out_tag.copy_from_slice(tag.as_slice())
}
pub fn decrypt(&mut self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::try_from(nonce).expect("AES_256_GCM_SIV nonce");
let (ciphertext, in_tag) =
ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size());
let in_tag = Tag::from_slice(in_tag);
self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok()
let in_tag = match Tag::try_from(&*in_tag) {
Ok(t) => t,
Err(_) => return false,
};
self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok()
}
}
}
+11 -8
View File
@@ -76,7 +76,7 @@ cfg_if! {
} else {
use chacha20poly1305::ChaCha20Poly1305 as CryptoChaCha20Poly1305;
use chacha20poly1305::{
aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeySizeUser, KeyInit},
aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeySizeUser, KeyInit},
Key,
Nonce,
Tag,
@@ -86,8 +86,8 @@ cfg_if! {
impl ChaCha20Poly1305 {
pub fn new(key: &[u8]) -> ChaCha20Poly1305 {
let key = Key::from_slice(key);
ChaCha20Poly1305(CryptoChaCha20Poly1305::new(key))
let key = Key::try_from(key).expect("CHACHA20_POLY1305 key");
ChaCha20Poly1305(CryptoChaCha20Poly1305::new(&key))
}
pub fn key_size() -> usize {
@@ -103,22 +103,25 @@ cfg_if! {
}
pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::try_from(nonce).expect("CHACHA20_POLY1305 nonce");
let (plaintext, out_tag) =
plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size());
let tag = self
.0
.encrypt_in_place_detached(nonce, &[], plaintext)
.encrypt_inout_detached(&nonce, &[], plaintext.into())
.expect("CHACHA20_POLY1305 encrypt");
out_tag.copy_from_slice(tag.as_slice())
}
pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::try_from(nonce).expect("CHACHA20_POLY1305 nonce");
let (ciphertext, in_tag) =
ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size());
let in_tag = Tag::from_slice(in_tag);
self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok()
let in_tag = match Tag::try_from(&*in_tag) {
Ok(t) => t,
Err(_) => return false,
};
self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok()
}
}
}
+11 -8
View File
@@ -3,7 +3,7 @@
//! https://datatracker.ietf.org/doc/html/rfc8998
use ccm::{
aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeyInit, KeySizeUser},
aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeyInit, KeySizeUser},
consts::{U12, U16},
Ccm,
Nonce,
@@ -31,22 +31,25 @@ impl Sm4Ccm {
}
pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::<U12>::try_from(nonce).expect("SM4_CCM nonce");
let (plaintext, out_tag) =
plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size());
let tag = self
.0
.encrypt_in_place_detached(nonce, &[], plaintext)
.encrypt_inout_detached(&nonce, &[], plaintext.into())
.expect("SM4_CCM encrypt");
out_tag.copy_from_slice(tag.as_slice())
}
pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::<U12>::try_from(nonce).expect("SM4_CCM nonce");
let (ciphertext, in_tag) =
ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size());
let in_tag = Tag::from_slice(in_tag);
self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok()
let in_tag = match Tag::<U16>::try_from(&*in_tag) {
Ok(t) => t,
Err(_) => return false,
};
self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok()
}
}
@@ -69,14 +72,14 @@ mod test {
let mut tag = hex::decode("16842D4FA186F56AB33256971FA110F4").unwrap();
cipher_text.append(&mut tag); // postfix tag
let nonce = super::Nonce::from_slice(&iv);
let nonce = super::Nonce::<U12>::try_from(&iv[..]).unwrap();
let cipher = Ccm::<Sm4, U16, U12>::new_from_slice(&key).unwrap();
let plain_text_payload = Payload {
msg: &plain_text,
aad: &aad,
};
let result = cipher.encrypt(nonce, plain_text_payload).unwrap();
let result = cipher.encrypt(&nonce, plain_text_payload).unwrap();
assert_eq!(result, cipher_text);
}
+11 -9
View File
@@ -1,7 +1,6 @@
//! SM4-GCM
use aead::{AeadCore, AeadInPlace, Key, KeyInit, KeySizeUser};
use sm4::cipher::Unsigned;
use aead::{array::typenum::Unsigned, AeadCore, AeadInOut, Key, KeyInit, KeySizeUser};
use super::sm4_gcm_cipher::{Nonce, Sm4Gcm as CryptoSm4Gcm, Tag};
@@ -9,8 +8,8 @@ pub struct Sm4Gcm(CryptoSm4Gcm);
impl Sm4Gcm {
pub fn new(key: &[u8]) -> Sm4Gcm {
let key = Key::<CryptoSm4Gcm>::from_slice(key);
Sm4Gcm(CryptoSm4Gcm::new(key))
let key = Key::<CryptoSm4Gcm>::try_from(key).expect("SM4_GCM key");
Sm4Gcm(CryptoSm4Gcm::new(&key))
}
pub fn key_size() -> usize {
@@ -26,21 +25,24 @@ impl Sm4Gcm {
}
pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::try_from(nonce).expect("SM4_GCM nonce");
let (plaintext, out_tag) =
plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size());
let tag = self
.0
.encrypt_in_place_detached(nonce, &[], plaintext)
.encrypt_inout_detached(&nonce, &[], plaintext.into())
.expect("SM4_GCM encrypt");
out_tag.copy_from_slice(tag.as_slice())
}
pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::try_from(nonce).expect("SM4_GCM nonce");
let (ciphertext, in_tag) =
ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size());
let in_tag = Tag::from_slice(in_tag);
self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok()
let in_tag = match Tag::try_from(&*in_tag) {
Ok(t) => t,
Err(_) => return false,
};
self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok()
}
}
+26 -19
View File
@@ -3,17 +3,19 @@
//! https://datatracker.ietf.org/doc/html/rfc8998
use aead::{
consts::{U0, U12, U16},
generic_array::GenericArray,
array::{typenum::Unsigned, Array},
consts::{U12, U16},
inout::InOutBuf,
AeadCore,
AeadInPlace,
AeadInOut,
Key,
KeyInit,
KeySizeUser,
TagPosition,
};
use ghash::{universal_hash::UniversalHash, GHash};
use sm4::{
cipher::{BlockEncrypt, InnerIvInit, StreamCipherCore, Unsigned},
cipher::{BlockCipherEncrypt, InnerIvInit, StreamCipherCore},
Sm4,
};
@@ -27,13 +29,13 @@ pub const P_MAX: u64 = 1 << 36;
pub const C_MAX: u64 = (1 << 36) + 16;
/// SM4-GCM nonces.
pub type Nonce = GenericArray<u8, U12>;
pub type Nonce = Array<u8, U12>;
/// SM4-GCM tags.
pub type Tag = GenericArray<u8, U16>;
pub type Tag = Array<u8, U16>;
/// SM4 block.
type Block = GenericArray<u8, U16>;
type Block = Array<u8, U16>;
/// Counter mode with a 32-bit big endian counter.
type Ctr32BE<'a> = ctr::CtrCore<&'a Sm4, ctr::flavors::Ctr32BE>;
@@ -67,13 +69,18 @@ impl From<Sm4> for Sm4Gcm {
}
impl AeadCore for Sm4Gcm {
type CiphertextOverhead = U0;
type NonceSize = U12;
type TagSize = U16;
const TAG_POSITION: TagPosition = TagPosition::Postfix;
}
impl AeadInPlace for Sm4Gcm {
fn encrypt_in_place_detached(&self, nonce: &Nonce, associated_data: &[u8], buffer: &mut [u8]) -> aead::Result<Tag> {
impl AeadInOut for Sm4Gcm {
fn encrypt_inout_detached(
&self,
nonce: &Nonce,
associated_data: &[u8],
mut buffer: InOutBuf<'_, '_, u8>,
) -> aead::Result<Tag> {
if buffer.len() as u64 > P_MAX || associated_data.len() as u64 > A_MAX {
return Err(aead::Error);
}
@@ -82,17 +89,17 @@ impl AeadInPlace for Sm4Gcm {
// TODO(tarcieri): interleave encryption with GHASH
// See: <https://github.com/RustCrypto/AEADs/issues/74>
ctr.apply_keystream_partial(buffer.into());
ctr.apply_keystream_partial(buffer.reborrow());
let full_tag = self.compute_tag(mask, associated_data, buffer);
Ok(Tag::clone_from_slice(&full_tag[..Self::TagSize::to_usize()]))
let full_tag = self.compute_tag(mask, associated_data, buffer.get_out());
Ok(Tag::try_from(&full_tag[..Self::TagSize::to_usize()]).expect("tag size"))
}
fn decrypt_in_place_detached(
fn decrypt_inout_detached(
&self,
nonce: &Nonce,
associated_data: &[u8],
buffer: &mut [u8],
mut buffer: InOutBuf<'_, '_, u8>,
tag: &Tag,
) -> aead::Result<()> {
if buffer.len() as u64 > C_MAX || associated_data.len() as u64 > A_MAX {
@@ -103,14 +110,14 @@ impl AeadInPlace for Sm4Gcm {
// TODO(tarcieri): interleave encryption with GHASH
// See: <https://github.com/RustCrypto/AEADs/issues/74>
let expected_tag = self.compute_tag(mask, associated_data, buffer);
let expected_tag = self.compute_tag(mask, associated_data, buffer.get_in());
use subtle::ConstantTimeEq;
if expected_tag[..<Self as AeadCore>::TagSize::to_usize()]
.ct_eq(tag)
.into()
{
ctr.apply_keystream_partial(buffer.into());
ctr.apply_keystream_partial(buffer.reborrow());
Ok(())
} else {
Err(aead::Error)
@@ -188,14 +195,14 @@ mod test {
let mut tag = hex::decode("83DE3541E4C2B58177E065A9BF7B62EC").unwrap();
cipher_text.append(&mut tag); // postfix tag
let nonce = super::Nonce::from_slice(&iv);
let nonce = super::Nonce::try_from(&iv[..]).unwrap();
let cipher = super::Sm4Gcm::new_from_slice(&key).unwrap();
let plain_text_payload = Payload {
msg: &plain_text,
aad: &aad,
};
let result = cipher.encrypt(nonce, plain_text_payload).unwrap();
let result = cipher.encrypt(&nonce, plain_text_payload).unwrap();
assert_eq!(result, cipher_text);
}
+11 -8
View File
@@ -1,6 +1,6 @@
pub use chacha20poly1305::XChaCha20Poly1305 as CryptoXChaCha20Poly1305;
use chacha20poly1305::{
aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeyInit, KeySizeUser},
aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeyInit, KeySizeUser},
Key,
Tag,
XNonce,
@@ -10,8 +10,8 @@ pub struct XChaCha20Poly1305(CryptoXChaCha20Poly1305);
impl XChaCha20Poly1305 {
pub fn new(key: &[u8]) -> XChaCha20Poly1305 {
let key = Key::from_slice(key);
XChaCha20Poly1305(CryptoXChaCha20Poly1305::new(key))
let key = Key::try_from(key).expect("XCHACHA20_POLY1305 key");
XChaCha20Poly1305(CryptoXChaCha20Poly1305::new(&key))
}
pub fn key_size() -> usize {
@@ -27,21 +27,24 @@ impl XChaCha20Poly1305 {
}
pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
let nonce = XNonce::from_slice(nonce);
let nonce = XNonce::try_from(nonce).expect("XCHACHA20_POLY1305 nonce");
let (plaintext, out_tag) =
plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size());
let tag = self
.0
.encrypt_in_place_detached(nonce, &[], plaintext)
.encrypt_inout_detached(&nonce, &[], plaintext.into())
.expect("XCHACHA20_POLY1305 encrypt");
out_tag.copy_from_slice(tag.as_slice())
}
pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool {
let nonce = XNonce::from_slice(nonce);
let nonce = XNonce::try_from(nonce).expect("XCHACHA20_POLY1305 nonce");
let (ciphertext, in_tag) =
ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size());
let in_tag = Tag::from_slice(in_tag);
self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok()
let in_tag = match Tag::try_from(&*in_tag) {
Ok(t) => t,
Err(_) => return false,
};
self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok()
}
}
+4 -5
View File
@@ -1,8 +1,7 @@
use chacha20::{
cipher::{IvSizeUser, KeyIvInit, KeySizeUser, StreamCipher, Unsigned},
cipher::{IvSizeUser, Iv, KeyIvInit, KeySizeUser, StreamCipher, typenum::Unsigned},
ChaCha20,
Key,
Nonce,
};
/// ChaCha20 for IETF Protocols
@@ -14,9 +13,9 @@ pub struct Chacha20 {
impl Chacha20 {
pub fn new(key: &[u8], nonce: &[u8]) -> Self {
let key = Key::from_slice(key);
let nonce = Nonce::from_slice(nonce);
let cipher = ChaCha20::new(key, nonce);
let key = Key::try_from(key).expect("chacha20 key");
let nonce = Iv::<ChaCha20>::try_from(nonce).expect("chacha20 nonce");
let cipher = ChaCha20::new(&key, &nonce);
Self { cipher }
}
+7 -7
View File
@@ -1,7 +1,7 @@
#![allow(dead_code)]
use aes::{
cipher::{BlockDecrypt, BlockEncrypt, BlockSizeUser, KeyInit, Unsigned},
cipher::{BlockCipherDecrypt, BlockCipherEncrypt, BlockSizeUser, KeyInit, typenum::Unsigned},
Aes128 as CryptoAes128,
Aes192 as CryptoAes192,
Aes256 as CryptoAes256,
@@ -20,12 +20,12 @@ impl Aes128 {
}
pub fn encrypt(&self, block: &mut [u8]) {
let block = Block::from_mut_slice(block);
let block = <&mut Block>::try_from(block).expect("block size");
self.0.encrypt_block(block);
}
pub fn decrypt(&self, block: &mut [u8]) {
let block = Block::from_mut_slice(block);
let block = <&mut Block>::try_from(block).expect("block size");
self.0.decrypt_block(block);
}
}
@@ -42,12 +42,12 @@ impl Aes192 {
}
pub fn encrypt(&self, block: &mut [u8]) {
let block = Block::from_mut_slice(block);
let block = <&mut Block>::try_from(block).expect("block size");
self.0.encrypt_block(block);
}
pub fn decrypt(&self, block: &mut [u8]) {
let block = Block::from_mut_slice(block);
let block = <&mut Block>::try_from(block).expect("block size");
self.0.decrypt_block(block);
}
}
@@ -64,12 +64,12 @@ impl Aes256 {
}
pub fn encrypt(&self, block: &mut [u8]) {
let block = Block::from_mut_slice(block);
let block = <&mut Block>::try_from(block).expect("block size");
self.0.encrypt_block(block);
}
pub fn decrypt(&self, block: &mut [u8]) {
let block = Block::from_mut_slice(block);
let block = <&mut Block>::try_from(block).expect("block size");
self.0.decrypt_block(block);
}
}
+7 -7
View File
@@ -1,7 +1,7 @@
#![allow(dead_code)]
use camellia::{
cipher::{Block, BlockDecrypt, BlockEncrypt, BlockSizeUser, KeyInit, KeySizeUser, Unsigned},
cipher::{Block, BlockCipherDecrypt, BlockCipherEncrypt, BlockSizeUser, KeyInit, KeySizeUser, typenum::Unsigned},
Camellia128 as CryptoCamellia128,
Camellia192 as CryptoCamellia192,
Camellia256 as CryptoCamellia256,
@@ -19,12 +19,12 @@ impl Camellia128 {
}
pub fn encrypt(&self, block: &mut [u8]) {
let block = Block::<CryptoCamellia128>::from_mut_slice(block);
let block = <&mut Block<CryptoCamellia128>>::try_from(block).expect("block size");
self.0.encrypt_block(block);
}
pub fn decrypt(&self, block: &mut [u8]) {
let block = Block::<CryptoCamellia128>::from_mut_slice(block);
let block = <&mut Block<CryptoCamellia128>>::try_from(block).expect("block size");
self.0.decrypt_block(block);
}
}
@@ -41,12 +41,12 @@ impl Camellia192 {
}
pub fn encrypt(&self, block: &mut [u8]) {
let block = Block::<CryptoCamellia192>::from_mut_slice(block);
let block = <&mut Block<CryptoCamellia192>>::try_from(block).expect("block size");
self.0.encrypt_block(block);
}
pub fn decrypt(&self, block: &mut [u8]) {
let block = Block::<CryptoCamellia192>::from_mut_slice(block);
let block = <&mut Block<CryptoCamellia192>>::try_from(block).expect("block size");
self.0.decrypt_block(block);
}
}
@@ -63,12 +63,12 @@ impl Camellia256 {
}
pub fn encrypt(&self, block: &mut [u8]) {
let block = Block::<CryptoCamellia256>::from_mut_slice(block);
let block = <&mut Block<CryptoCamellia256>>::try_from(block).expect("block size");
self.0.encrypt_block(block);
}
pub fn decrypt(&self, block: &mut [u8]) {
let block = Block::<CryptoCamellia256>::from_mut_slice(block);
let block = <&mut Block<CryptoCamellia256>>::try_from(block).expect("block size");
self.0.decrypt_block(block);
}
}
+10 -10
View File
@@ -2,7 +2,7 @@
// https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf
use aes::{
cipher::{Iv, IvSizeUser, Key, KeyIvInit, StreamCipher, Unsigned},
cipher::{Iv, IvSizeUser, Key, KeyIvInit, StreamCipher, typenum::Unsigned},
Aes128 as CryptoAes128,
Aes192 as CryptoAes192,
Aes256 as CryptoAes256,
@@ -25,9 +25,9 @@ impl Aes128Ctr {
pub const KEY_LEN: usize = Aes128::KEY_LEN;
pub fn new(key: &[u8], iv: &[u8]) -> Aes128Ctr {
let key = Key::<CryptoAes128Ctr>::from_slice(key);
let iv = Iv::<CryptoAes128Ctr>::from_slice(iv);
let ctr = CryptoAes128Ctr::new(key, iv);
let key = Key::<CryptoAes128Ctr>::try_from(key).expect("Aes128Ctr key");
let iv = Iv::<CryptoAes128Ctr>::try_from(iv).expect("Aes128Ctr iv");
let ctr = CryptoAes128Ctr::new(&key, &iv);
Aes128Ctr(ctr)
}
@@ -47,9 +47,9 @@ impl Aes192Ctr {
pub const KEY_LEN: usize = Aes192::KEY_LEN;
pub fn new(key: &[u8], iv: &[u8]) -> Aes192Ctr {
let key = Key::<CryptoAes192Ctr>::from_slice(key);
let iv = Iv::<CryptoAes192Ctr>::from_slice(iv);
let ctr = CryptoAes192Ctr::new(key, iv);
let key = Key::<CryptoAes192Ctr>::try_from(key).expect("Aes192Ctr key");
let iv = Iv::<CryptoAes192Ctr>::try_from(iv).expect("Aes192Ctr iv");
let ctr = CryptoAes192Ctr::new(&key, &iv);
Aes192Ctr(ctr)
}
@@ -69,9 +69,9 @@ impl Aes256Ctr {
pub const KEY_LEN: usize = Aes256::KEY_LEN;
pub fn new(key: &[u8], iv: &[u8]) -> Aes256Ctr {
let key = Key::<CryptoAes256Ctr>::from_slice(key);
let iv = Iv::<CryptoAes256Ctr>::from_slice(iv);
let ctr = CryptoAes256Ctr::new(key, iv);
let key = Key::<CryptoAes256Ctr>::try_from(key).expect("Aes256Ctr key");
let iv = Iv::<CryptoAes256Ctr>::try_from(iv).expect("Aes256Ctr iv");
let ctr = CryptoAes256Ctr::new(&key, &iv);
Aes256Ctr(ctr)
}
+11 -8
View File
@@ -1,6 +1,6 @@
pub use chacha20poly1305::ChaCha8Poly1305 as CryptoChaCha8Poly1305;
use chacha20poly1305::{
aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeyInit, KeySizeUser},
aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeyInit, KeySizeUser},
Key,
Nonce,
Tag,
@@ -10,8 +10,8 @@ pub struct ChaCha8Poly1305(CryptoChaCha8Poly1305);
impl ChaCha8Poly1305 {
pub fn new(key: &[u8]) -> ChaCha8Poly1305 {
let key = Key::from_slice(key);
ChaCha8Poly1305(CryptoChaCha8Poly1305::new(key))
let key = Key::try_from(key).expect("CHACHA8_POLY1305 key");
ChaCha8Poly1305(CryptoChaCha8Poly1305::new(&key))
}
pub fn key_size() -> usize {
@@ -27,21 +27,24 @@ impl ChaCha8Poly1305 {
}
pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::try_from(nonce).expect("CHACHA8_POLY1305 nonce");
let (plaintext, out_tag) =
plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size());
let tag = self
.0
.encrypt_in_place_detached(nonce, &[], plaintext)
.encrypt_inout_detached(&nonce, &[], plaintext.into())
.expect("CHACHA8_POLY1305 encrypt");
out_tag.copy_from_slice(tag.as_slice())
}
pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool {
let nonce = Nonce::from_slice(nonce);
let nonce = Nonce::try_from(nonce).expect("CHACHA8_POLY1305 nonce");
let (ciphertext, in_tag) =
ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size());
let in_tag = Tag::from_slice(in_tag);
self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok()
let in_tag = match Tag::try_from(&*in_tag) {
Ok(t) => t,
Err(_) => return false,
};
self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok()
}
}
+11 -8
View File
@@ -1,6 +1,6 @@
pub use chacha20poly1305::XChaCha8Poly1305 as CryptoXChaCha8Poly1305;
use chacha20poly1305::{
aead::{generic_array::typenum::Unsigned, AeadCore, AeadInPlace, KeyInit, KeySizeUser},
aead::{array::typenum::Unsigned, AeadCore, AeadInOut, KeyInit, KeySizeUser},
Key,
Tag,
XNonce,
@@ -10,8 +10,8 @@ pub struct XChaCha8Poly1305(CryptoXChaCha8Poly1305);
impl XChaCha8Poly1305 {
pub fn new(key: &[u8]) -> XChaCha8Poly1305 {
let key = Key::from_slice(key);
XChaCha8Poly1305(CryptoXChaCha8Poly1305::new(key))
let key = Key::try_from(key).expect("XCHACHA8_POLY1305 key");
XChaCha8Poly1305(CryptoXChaCha8Poly1305::new(&key))
}
pub fn key_size() -> usize {
@@ -27,21 +27,24 @@ impl XChaCha8Poly1305 {
}
pub fn encrypt(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
let nonce = XNonce::from_slice(nonce);
let nonce = XNonce::try_from(nonce).expect("XCHACHA8_POLY1305 nonce");
let (plaintext, out_tag) =
plaintext_in_ciphertext_out.split_at_mut(plaintext_in_ciphertext_out.len() - Self::tag_size());
let tag = self
.0
.encrypt_in_place_detached(nonce, &[], plaintext)
.encrypt_inout_detached(&nonce, &[], plaintext.into())
.expect("XCHACHA8_POLY1305 encrypt");
out_tag.copy_from_slice(tag.as_slice())
}
pub fn decrypt(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool {
let nonce = XNonce::from_slice(nonce);
let nonce = XNonce::try_from(nonce).expect("XCHACHA8_POLY1305 nonce");
let (ciphertext, in_tag) =
ciphertext_in_plaintext_out.split_at_mut(ciphertext_in_plaintext_out.len() - Self::tag_size());
let in_tag = Tag::from_slice(in_tag);
self.0.decrypt_in_place_detached(nonce, &[], ciphertext, in_tag).is_ok()
let in_tag = match Tag::try_from(&*in_tag) {
Ok(t) => t,
Err(_) => return false,
};
self.0.decrypt_inout_detached(&nonce, &[], ciphertext.into(), &in_tag).is_ok()
}
}