已解决
背景
各位大拿,我是Rust自学小白,我将一些java项目翻译成Rust进行学习,发现用到了AES加密、解密算法。Rust的加解密算法发展很快,目前还未找到Rust实现方法。比如Ring库或者Cripto库,我都没看到具体的AES128 加解密方案,网上的样例都是老版本的,最新版本都没找大。Ring v0.17.8有哪位大拿帮我看看这个。
非常感谢。
Java采用的算法是AES128 SHA1PRNG
1
共 6 条评论, 1 页
评论区
写评论解决了
昨晚上折腾到9点,调通了,今天又重新重构了一下。为了方便理解,合并了几个方法。 各位大神一眼就看出来代码的问题,给你们点赞!多谢引导我这个小白进一步前进。这个AES折腾几天了。哈哈哈哈,Rust ring的这个封装的真实没那么方便。以下是通过版本
use base64::{engine::general_purpose::STANDARD_NO_PAD, Engine as _}; use ring::aead::{self, Aad, BoundKey, Nonce, OpeningKey, SealingKey, UnboundKey, AES_128_GCM}; use base64; use crate::err::biz_err::BizErr; use super::constants::AES_KEY; pub(crate) fn aes_encrypt(raw: &str, key: &str) -> Result<String, BizErr> { let mut secret = vec![0u8; AES_128_GCM.key_len()]; secret[..key.len()].copy_from_slice(key.as_bytes()); let n: Nonce = match Nonce::try_assume_unique_for_key(NONCE) { Ok(n) => n, Err(e) => { return Err(BizErr::InvalidNonceErr { val: e.to_string() }); } }; let ukey = UnboundKey::new(&AES_128_GCM, &secret) .map_err(|e| BizErr::InvalidNonceErr { val: e.to_string() }) .unwrap(); let nonce_sequence = OneNonceSequence::new(n); let mut s_key: SealingKey<OneNonceSequence> = SealingKey::new(ukey, nonce_sequence); let aes_key = &AES_KEY.as_bytes(); let aad = Aad::from(aes_key); let mut in_out = raw.as_bytes().to_owned(); let ret = s_key.seal_in_place_append_tag(aad, &mut in_out); match ret { Ok(_v) => Ok(STANDARD_NO_PAD.encode(in_out)), Err(e) => { return Err(BizErr::EncryptErr { val: e.to_string() }); } } } pub(crate) fn aes_decrypt(data: &str, key: &str) -> Result<String, BizErr> { println!("aes_decrypt data: {data}, key: {key}"); let mut in_out = match STANDARD_NO_PAD.decode(data) { Ok(r) => r, Err(e) => { return Err(BizErr::Base64DecodeErr { val: e.to_string() }); } }; let mut secret = vec![0u8; AES_128_GCM.key_len()]; secret[..key.len()].copy_from_slice(key.as_bytes()); let n = match Nonce::try_assume_unique_for_key(NONCE) { Ok(n) => n, Err(e) => { return Err(BizErr::InvalidNonceErr { val: e.to_string() }); } }; let ukey = UnboundKey::new(&AES_128_GCM, &secret) .map_err(|e| BizErr::InvalidNonceErr { val: e.to_string() }) .unwrap(); let nonce_sequence = OneNonceSequence::new(n); let mut o_key: OpeningKey<OneNonceSequence> = OpeningKey::new(ukey, nonce_sequence); let aes_key = &AES_KEY.as_bytes(); let aad = Aad::from(aes_key); let ciphertext_and_tag = std::ops::RangeFrom { start: 0 }; let ret = o_key.open_within(aad, &mut in_out, ciphertext_and_tag); // let ret = o_key.open_in_place(aad, &mut in_out); let text = match ret { Ok(v) => String::from_utf8_lossy(v).to_string(), Err(e) => { return Err(BizErr::DecryptErr { val: e.to_string() }); } }; Ok(text) } struct OneNonceSequence(Option<aead::Nonce>); static NONCE: &[u8] = &[0; 12]; impl OneNonceSequence { fn new(nonce: aead::Nonce) -> Self { Self(Some(nonce)) } } impl aead::NonceSequence for OneNonceSequence { fn advance(&mut self) -> Result<aead::Nonce, ring::error::Unspecified> { self.0.take().ok_or(ring::error::Unspecified) } } mod test { use crate::utils::{ crypto::{aes_decrypt, aes_encrypt, md5_hex}, time_tools, }; #[test] fn test_encrypt_and_decrypt() { let raw = "abc"; let key = "def"; let mut val = "".to_string(); match aes_encrypt(&raw, &key) { Ok(v) => { println!("encrypt_text: {}", v); match aes_decrypt(&v, &key) { Ok(text) => { println!("decrypt_text: {}", text); val = text; } Err(e) => println!("decrypt_err: {e}"), } } Err(e) => { println!("encrypt_err: {e}"); } } assert_eq!(val, raw); } }
aes-gcm 算法的,直接用这个库吧 https://docs.rs/aes-gcm/latest/aes_gcm/
示例如下: use aes_gcm::{ aead::{Aead, AeadCore, KeyInit, OsRng}, Aes256Gcm, Nonce, Key // Or
Aes128Gcm
};// The encryption key can be generated randomly: let key = Aes256Gcm::generate_key(OsRng);
// Transformed from a byte array: let key: &[u8; 32] = &[42; 32]; let key: &Key = key.into();
// Note that you can get byte array from slice using the
TryInto
trait: let key: &[u8] = &[42; 32]; let key: [u8; 32] = key.try_into()?;// Alternatively, the key can be transformed directly from a byte slice // (panicks on length mismatch): let key = Key::::from_slice(key);
let cipher = Aes256Gcm::new(&key); let nonce = Aes256Gcm::generate_nonce(&mut OsRng); // 96-bits; unique per message let ciphertext = cipher.encrypt(&nonce, b"plaintext message".as_ref())?; let plaintext = cipher.decrypt(&nonce, ciphertext.as_ref())?; assert_eq!(&plaintext, b"plaintext message");
看文档,
open_in_place
和open_within
会返回不带 tag 的 plaintext,文档中给了例子:let plaintext = key.open_within(aad, in_out, cipertext_and_tag)?;
方案二 encrypt_and_encode 的 key 完全没有给到 secret,相当于加密密钥一直都是全 0!这就是开变量未使用 warning 的好处了。
第一个乱码有补码,用库带的去掉补码
--
👇
ppluck: gpt和文新一言知识不够新,错误一大推,解决不了了。
我网上找到了两种方法,改了改,但是加密后,解密后半部分不对。
以下是多方寻找以及源码阅读,写的demo,并未严格做好错误处理。等调通了再做各种处理
方案1:
/// 生成一个随机的 96 位 nonce static NONCE: OnceLock<[u8; 12]> = OnceLock::new(); fn init() { NONCE.get_or_init(|| { let rng = SystemRandom::new(); let mut nonce_data = [0u8; NONCE_LEN]; // 96bit nonc rng.fill(&mut nonce_data) .expect("Failed to generate random nonce"); nonce_data // Nonce::assume_unique_for_key(nonce_data) // Nonce::try_assume_unique_for_key(&nonce_data).unwrap() }); } fn ed2() { init(); let mac = "c8:16:bd:50:26:6a"; let self_id = "1428"; let aes_key = "abc"; let time = time_tools::unixtime_now(); let mac2 = mac.to_lowercase().replace(":", ""); let key = format!("{}{}", aes_key, self_id); let input = format!("{}_{}_{}", time, self_id, mac2); let binding = NONCE.get().unwrap().to_vec().clone(); let n = binding.as_slice(); let n2 = binding.as_slice(); let nonce = Nonce::try_assume_unique_for_key(n).unwrap(); let nonce2 = Nonce::try_assume_unique_for_key(n2).unwrap(); let mut secret = vec![0u8; AES_128_GCM.key_len()]; secret[..key.len()].copy_from_slice(key.as_bytes()); let key = LessSafeKey::new(UnboundKey::new(&AES_128_GCM, &secret).unwrap()); let mut payload = Vec::from(String::from("Test")); let aad = Aad::from(AES_KEY); println!("{:?}", secret); println!("{:?}", aad); println!("{:?}", payload); println!("{}", String::from_utf8_lossy(&payload).to_string()); key.seal_in_place_append_tag(nonce, aad, &mut payload) .unwrap(); println!("{:?}", secret); println!("{:?}", aad); println!("{:?}", payload); println!("{}", STANDARD_NO_PAD.encode(&payload)); // let key2 = LessSafeKey::new(UnboundKey::new(&AES_128_GCM, &secret).unwrap()); key.open_in_place(nonce2, aad, &mut payload).unwrap(); //Panics here println!("{:?}", secret); println!("{:?}", aad); println!("{:?}", payload); println!("{}", String::from_utf8_lossy(&payload).to_string()); }
以上执行结果,解密最后面老是有一段乱码:
[97, 98, 99, 49, 52, 50, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0] Aad("i71") [84, 101, 115, 116] Test [97, 98, 99, 49, 52, 50, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0] Aad("i71") [120, 57, 78, 68, 78, 74, 201, 166, 74, 141, 75, 38, 6, 150, 161, 183, 82, 111, 162, 197] eDlORE5KyaZKjUsmBpaht1JvosU [97, 98, 99, 49, 52, 50, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0] Aad("i71") [84, 101, 115, 116, 78, 74, 201, 166, 74, 141, 75, 38, 6, 150, 161, 183, 82, 111, 162, 197] TestNJɦJ�K&���Ro��
方案2:
/// 生成一个随机的 96 位 nonce static NONCE: OnceLock<[u8; 12]> = OnceLock::new(); fn init() { NONCE.get_or_init(|| { let rng = SystemRandom::new(); let mut nonce_data = [0u8; NONCE_LEN]; // 96bit nonc rng.fill(&mut nonce_data) .expect("Failed to generate random nonce"); nonce_data // Nonce::assume_unique_for_key(nonce_data) // Nonce::try_assume_unique_for_key(&nonce_data).unwrap() }); } struct OneNonceSequence(Option<aead::Nonce>); impl OneNonceSequence { /// Constructs the sequence allowing `advance()` to be called /// `allowed_invocations` times. fn new(nonce: aead::Nonce) -> Self { Self(Some(nonce)) } } impl aead::NonceSequence for OneNonceSequence { fn advance(&mut self) -> Result<aead::Nonce, ring::error::Unspecified> { self.0.take().ok_or(ring::error::Unspecified) } } fn seal_with_key( algorithm: &'static aead::Algorithm, key: &[u8], nonce: aead::Nonce, aad: aead::Aad<&[u8]>, in_out: &mut Vec<u8>, ) -> Result<(), ring::error::Unspecified> { let key = aead::UnboundKey::new(algorithm, key).unwrap(); let nonce_sequence = OneNonceSequence::new(nonce); let mut s_key: SealingKey<OneNonceSequence> = SealingKey::new(key, nonce_sequence); s_key.seal_in_place_append_tag(aad, in_out) } fn open_with_key<'a>( algorithm: &'static aead::Algorithm, key: &[u8], nonce: aead::Nonce, aad: aead::Aad<&[u8]>, in_out: &'a mut [u8], ciphertext_and_tag: std::ops::RangeFrom<usize>, ) -> Result<&'a mut [u8], ring::error::Unspecified> { let key = aead::UnboundKey::new(algorithm, key).unwrap(); let nonce_sequence = OneNonceSequence::new(nonce); let mut o_key: OpeningKey<OneNonceSequence> = OpeningKey::new(key, nonce_sequence); o_key.open_within(aad, in_out, ciphertext_and_tag) } pub fn encrypt_and_encode( algorithm: &'static aead::Algorithm, input: String, key: &[u8], nonce: &Vec<u8>, ) -> Result<String, Unspecified> { // attempt to convert the nonce vector into an aead::Nonce let n = match aead::Nonce::try_assume_unique_for_key(nonce) { Ok(n) => n, Err(e) => { error!("Could not use nonce {}", e); return Err(e); } }; let mut raw = input.as_bytes().to_owned(); let secret = vec![0u8; AES_128_GCM.key_len()]; match seal_with_key( algorithm, &secret, n, ring::aead::Aad::from(&AES_KEY.as_bytes()), &mut raw, ) { Ok(_v) => _v, Err(e) => { error!("Could not encrypt value {}", e); return Err(e); } } return Ok(STANDARD_NO_PAD.encode(raw)); } pub fn decrypt_and_decode( algorithm: &'static aead::Algorithm, input: String, key: &[u8], nonce: &Vec<u8>, ) -> Result<String, BizErr> { let mut raw = match STANDARD_NO_PAD.decode(input) { Ok(r) => r, Err(e) => { error!("Could not decode msg {}", e); return Err(BizErr::Base64DecodeErr { val: e.to_string() }); } }; // attempt to convert the nonce vector into an aead::Nonce let n = match aead::Nonce::try_assume_unique_for_key(nonce) { Ok(n) => n, Err(e) => { error!("Could not use nonce {}", e); return Err(BizErr::InvalidNonceErr { val: e.to_string() }); } }; // decrypt the oauth values let res = match open_with_key( algorithm, &key, n, ring::aead::Aad::from(&AES_KEY.as_bytes()), &mut raw, std::ops::RangeFrom { start: 0 }, ) { Ok(v) => v, Err(e) => { error!("Could not decrypt value {}", e); return Err(BizErr::DecryptErr { val: e.to_string() }); } }; let res = match String::from_utf8(res.to_vec()) { Ok(value) => value, Err(e) => { error!("Could not from utf8 for value {}", e); let msg = String::from_utf8_lossy(&res).to_string(); return Err(BizErr::FromUtf8Err { val: msg }); } }; Ok(res) } #[test] fn test_encrypt_and_decrypt() { let nonce = NONCE.get_or_init(|| { let rng = SystemRandom::new(); let mut nonce_data = [0u8; NONCE_LEN]; // 96bit nonc rng.fill(&mut nonce_data) .expect("Failed to generate random nonce"); nonce_data }); let mac = "c8:16:bd:50:26:6a"; let self_id = "1428"; let aes_key = "abc"; let time = time_tools::unixtime_now(); let mac2 = mac.to_lowercase().replace(":", ""); let key = format!("{}{}", aes_key, self_id); let mut secret = vec![0u8; AES_128_GCM.key_len()]; secret[..key.len()].copy_from_slice(key.as_bytes()); let input = format!("{}_{}_{}", time, self_id, mac2); let text = encrypt_and_encode(&AES_128_GCM, input.clone(), &secret, nonce.to_vec().as_ref()) .unwrap_or_default(); println!("sec: {text}"); let src = decrypt_and_decode(&AES_128_GCM, text, &secret, nonce.to_vec().as_ref()).unwrap_or_default(); println!("src: {src}"); assert!(src == input); }
也不对,打印出来,解密报错了,待进一步一点一点分析: sec: COLIo8+YS1tui+oKOESv6bns6T28i4Fvc6Pr2GH0xHLZV/ONGrSLIkQuPxE src:
这个是基于对称加密的随机数生成,这个暂时可能需要自己写 prng 可以在ai上试下
求助AI