diff --git a/__crypto/jose-test/src/jose.rs b/__crypto/jose-test/src/jose.rs index 907afaf..410abf4 100644 --- a/__crypto/jose-test/src/jose.rs +++ b/__crypto/jose-test/src/jose.rs @@ -1,4 +1,4 @@ -use aes_gcm_stream::Aes256GcmStreamEncryptor; +use aes_gcm_stream::{Aes256GcmStreamDecryptor, Aes256GcmStreamEncryptor}; use aes_kw::Kek; use base64::engine::general_purpose::URL_SAFE_NO_PAD; use base64::Engine; @@ -12,7 +12,7 @@ use rand::random; use rand::rngs::OsRng; use rsa::RsaPrivateKey; use rust_util::XResult; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use serde_json::Value; const LOCAL_KMS_PREFIX: &str = "LKMS:"; @@ -88,8 +88,8 @@ pub fn deserialize_jwe_rsa(jwe: &str, jwk: &Jwk) -> XResult<(Vec, JweHeader) // // https://security.stackexchange.com/questions/80966/what-is-the-point-of-aes-key-wrap-with-json-web-encryption -#[derive(Serialize)] -struct JweHeader2 { +#[derive(Debug, Serialize, Deserialize)] +pub struct JweHeader2 { pub enc: String, pub alg: String, pub vendor: String, @@ -139,11 +139,50 @@ pub fn serialize_jwe_aes(payload: &[u8], key: &[u8]) -> XResult { Ok(format!("{}{}", LOCAL_KMS_PREFIX, jwe::serialize_compact(payload, &header, &encrypter)?)) } +pub fn deserialize_jwe_aes_2(jwe: &str, key: [u8; 32]) -> XResult<(Vec, JweHeader2)> { + let jwe_parts = jwe.split(".").collect::>(); + if jwe_parts.len() != 5 { + panic!("Invalid jwe"); + } + let header_bytes = URL_SAFE_NO_PAD.decode(jwe_parts[0].as_bytes()).unwrap(); + let header: JweHeader2 = serde_json::from_slice(&header_bytes).unwrap(); + println!("{:?}", jwe_parts); + println!("{:?}", header); + let key_wrap = URL_SAFE_NO_PAD.decode(jwe_parts[1].as_bytes()).unwrap(); + let nonce = URL_SAFE_NO_PAD.decode(jwe_parts[2].as_bytes()).unwrap(); + let ciphertext = URL_SAFE_NO_PAD.decode(jwe_parts[3].as_bytes()).unwrap(); + let tag = URL_SAFE_NO_PAD.decode(jwe_parts[4].as_bytes()).unwrap(); + + let kek = Kek::from(key); + let data_key = kek.unwrap_vec(&key_wrap).unwrap(); + let data_key_b32 = bytes_to_32(&data_key); + + let mut decryptor = Aes256GcmStreamDecryptor::new(data_key_b32, &nonce); + decryptor.init_adata(jwe_parts[0].as_bytes()); + let mut p1 = decryptor.update(&ciphertext); + let p2 = decryptor.update(&tag); + let pf = decryptor.finalize().unwrap(); + p1.extend_from_slice(&p2); + p1.extend_from_slice(&pf); + Ok((p1, header)) +} + pub fn deserialize_jwe_aes(jwe: &str, key: &[u8]) -> XResult<(Vec, JweHeader)> { let decrypter = AeskwJweAlgorithm::A256kw.decrypter_from_bytes(key)?; Ok(jwe::deserialize_compact(&get_jwe(jwe), &decrypter)?) } +fn bytes_to_32(bytes: &[u8]) -> [u8; 32] { + if bytes.len() != 32 { + panic!("Invalid bytes"); + } + let mut ret = [0; 32]; + for i in 0..32 { + ret[i] = bytes[i]; + } + ret +} + fn get_jwe(jwe: &str) -> String { if jwe.starts_with(LOCAL_KMS_PREFIX) { jwe.chars().skip(LOCAL_KMS_PREFIX.len()).collect() diff --git a/__crypto/jose-test/src/main.rs b/__crypto/jose-test/src/main.rs index eb9c290..276af0d 100644 --- a/__crypto/jose-test/src/main.rs +++ b/__crypto/jose-test/src/main.rs @@ -1,6 +1,6 @@ mod jose; -use crate::jose::{deserialize_jwe_aes, serialize_jwe_aes_2}; +use crate::jose::{deserialize_jwe_aes, deserialize_jwe_aes_2, serialize_jwe_aes_2}; use base64::engine::general_purpose::STANDARD; use base64::Engine; use jose_jwk::{Jwk, Key, Rsa}; @@ -21,6 +21,10 @@ fn main() { println!("{:?}", d); println!("{:?}", h); + let (d2, h2) = deserialize_jwe_aes_2(&e, key).unwrap(); + println!("{:?}", d2); + println!("{:?}", h2); + let rsa_key = jose::generate_rsa_key_2(2048).unwrap(); let rsa_public_key = rsa_key.as_ref(); let public_rsa: Rsa = rsa_public_key.into();