feat: update jose-test
This commit is contained in:
@@ -9,9 +9,9 @@ use josekit::jwe::JweHeader;
|
||||
use josekit::jwk::alg::rsa::RsaKeyPair;
|
||||
use josekit::jwk::Jwk;
|
||||
use rand::random;
|
||||
use rand::rngs::OsRng;
|
||||
use rsa::{Oaep, RsaPrivateKey};
|
||||
use rust_util::XResult;
|
||||
use rand::rngs::{OsRng, ThreadRng};
|
||||
use rsa::{Oaep, RsaPrivateKey, RsaPublicKey};
|
||||
use rust_util::{opt_result, simple_error, XResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use sha1::Sha1;
|
||||
@@ -48,59 +48,6 @@ const LOCAL_KMS_PREFIX: &str = "LKMS:";
|
||||
// A256GCM Advanced Encryption Standard (AES) using 256 bit keys in Galois/Counter Mode, as defined in [FIPS‑197] and [NIST‑800‑38D]
|
||||
// A256KW Advanced Encryption Standard (AES) Key Wrap Algorithm using 256 bit keys, as defined in RFC 3394 [RFC3394]
|
||||
|
||||
pub fn generate_rsa_key_2(bits: u32) -> XResult<RsaPrivateKey> {
|
||||
let mut rng = OsRng::default();
|
||||
Ok(RsaPrivateKey::new(&mut rng, bits as usize)?)
|
||||
}
|
||||
|
||||
pub fn generate_rsa_key(bits: u32) -> XResult<RsaKeyPair> {
|
||||
Ok(RsaKeyPair::generate(bits)?)
|
||||
}
|
||||
|
||||
pub fn serialize_jwe_rsa_2(payload: &[u8], jwk: &Jwk) {
|
||||
// TODO ...
|
||||
}
|
||||
|
||||
pub fn serialize_jwe_rsa(payload: &[u8], jwk: &Jwk) -> XResult<String> {
|
||||
let mut header = JweHeader::new();
|
||||
header.set_content_encryption("A256GCM");
|
||||
header.set_claim("vendor", Some(Value::String("local-mini-kms".to_string())))?;
|
||||
let encrypter = RsaesJweAlgorithm::RsaOaep.encrypter_from_jwk(jwk)?;
|
||||
Ok(format!("{}{}", LOCAL_KMS_PREFIX, jwe::serialize_compact(payload, &header, &encrypter)?))
|
||||
}
|
||||
|
||||
pub fn deserialize_jwe_rsa_2(jwe: &str, rsa: &RsaPrivateKey) -> XResult<(Vec<u8>, JweHeader2)> {
|
||||
let jwe_parts = jwe.split(".").collect::<Vec<&str>>();
|
||||
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 data_key = rsa.decrypt(Oaep::new::<Sha1>(), &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_rsa(jwe: &str, jwk: &Jwk) -> XResult<(Vec<u8>, JweHeader)> {
|
||||
let decrypter = RsaesJweAlgorithm::RsaOaep.decrypter_from_jwk(jwk)?;
|
||||
Ok(jwe::deserialize_compact(&get_jwe(jwe), &decrypter)?)
|
||||
}
|
||||
|
||||
// JWE Header: {"alg":"dir","enc":"A256GCM"}
|
||||
// Encrypted key (CEK): (blank)
|
||||
// IV: Vlf_WdLm-spHbfJe
|
||||
@@ -115,6 +62,46 @@ pub fn deserialize_jwe_rsa(jwe: &str, jwk: &Jwk) -> XResult<(Vec<u8>, JweHeader)
|
||||
//
|
||||
// https://security.stackexchange.com/questions/80966/what-is-the-point-of-aes-key-wrap-with-json-web-encryption
|
||||
|
||||
pub fn generate_rsa_key_2(bits: u32) -> XResult<RsaPrivateKey> {
|
||||
let mut rng = OsRng::default();
|
||||
Ok(RsaPrivateKey::new(&mut rng, bits as usize)?)
|
||||
}
|
||||
|
||||
pub fn generate_rsa_key(bits: u32) -> XResult<RsaKeyPair> {
|
||||
Ok(RsaKeyPair::generate(bits)?)
|
||||
}
|
||||
|
||||
pub fn serialize_jwe_rsa_2(payload: &[u8], rsa_public_key: &RsaPublicKey) -> XResult<String> {
|
||||
let header = JweHeader2 {
|
||||
enc: "A256GCM".to_string(),
|
||||
alg: "RSA-OAEP".to_string(),
|
||||
vendor: "local-mini-kms".to_string(),
|
||||
};
|
||||
serialize_jwe_fn(&header, payload, |data_key| -> XResult<Vec<u8>> {
|
||||
let mut r = ThreadRng::default();
|
||||
Ok(opt_result!(rsa_public_key.encrypt(&mut r, Oaep::new::<Sha1>(), data_key), "Wrap key failed: {}"))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn serialize_jwe_rsa(payload: &[u8], jwk: &Jwk) -> XResult<String> {
|
||||
let mut header = JweHeader::new();
|
||||
header.set_content_encryption("A256GCM");
|
||||
header.set_claim("vendor", Some(Value::String("local-mini-kms".to_string())))?;
|
||||
let encrypter = RsaesJweAlgorithm::RsaOaep.encrypter_from_jwk(jwk)?;
|
||||
Ok(format!("{}{}", LOCAL_KMS_PREFIX, jwe::serialize_compact(payload, &header, &encrypter)?))
|
||||
}
|
||||
|
||||
pub fn deserialize_jwe_rsa_2(jwe: &str, rsa: &RsaPrivateKey) -> XResult<(Vec<u8>, JweHeader2)> {
|
||||
deserialize_jwe_fn(jwe, |key_wrap| -> XResult<(Vec<u8>)> {
|
||||
Ok(opt_result!(rsa.decrypt(Oaep::new::<Sha1>(), &key_wrap), "Unwrap key failed: {}"))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn deserialize_jwe_rsa(jwe: &str, jwk: &Jwk) -> XResult<(Vec<u8>, JweHeader)> {
|
||||
let decrypter = RsaesJweAlgorithm::RsaOaep.decrypter_from_jwk(jwk)?;
|
||||
Ok(jwe::deserialize_compact(&get_jwe(jwe), &decrypter)?)
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct JweHeader2 {
|
||||
pub enc: String,
|
||||
@@ -128,9 +115,39 @@ pub fn serialize_jwe_aes_2(payload: &[u8], key: [u8; 32]) -> XResult<String> {
|
||||
alg: "A256KW".to_string(),
|
||||
vendor: "local-mini-kms".to_string(),
|
||||
};
|
||||
serialize_jwe_fn(&header, payload, |data_key| -> XResult<Vec<u8>> {
|
||||
let kek = Kek::from(key);
|
||||
Ok(opt_result!(kek.wrap_vec(&data_key[..]), "Wrap key failed: {}"))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn serialize_jwe_aes(payload: &[u8], key: &[u8]) -> XResult<String> {
|
||||
let mut header = JweHeader::new();
|
||||
header.set_content_encryption("A256GCM");
|
||||
header.set_claim("vendor", Some(Value::String("local-mini-kms".to_string())))?;
|
||||
// header.set_claim("version", Some(Value::String(get_master_key_checksum(key))))?;
|
||||
let encrypter = AeskwJweAlgorithm::A256kw.encrypter_from_bytes(key)?;
|
||||
Ok(format!("{}{}", LOCAL_KMS_PREFIX, jwe::serialize_compact(payload, &header, &encrypter)?))
|
||||
}
|
||||
|
||||
pub fn deserialize_jwe_aes_2(jwe: &str, key: [u8; 32]) -> XResult<(Vec<u8>, JweHeader2)> {
|
||||
deserialize_jwe_fn(jwe, |key_wrap| -> XResult<(Vec<u8>)> {
|
||||
let kek = Kek::from(key);
|
||||
Ok(opt_result!(kek.unwrap_vec(&key_wrap), "Unwrap key failed: {}"))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn deserialize_jwe_aes(jwe: &str, key: &[u8]) -> XResult<(Vec<u8>, JweHeader)> {
|
||||
let decrypter = AeskwJweAlgorithm::A256kw.decrypter_from_bytes(key)?;
|
||||
Ok(jwe::deserialize_compact(&get_jwe(jwe), &decrypter)?)
|
||||
}
|
||||
|
||||
fn serialize_jwe_fn<F>(header: &JweHeader2, payload: &[u8], key_wrap_fn: F) -> XResult<String>
|
||||
where
|
||||
F: Fn(&[u8]) -> XResult<Vec<u8>>,
|
||||
{
|
||||
let header_str = serde_json::to_string(&header).unwrap();
|
||||
let header_b64 = URL_SAFE_NO_PAD.encode(header_str.as_bytes());
|
||||
// let key: [u8; 32] = key.into();
|
||||
|
||||
let data_key: [u8; 32] = random();
|
||||
let nonce: [u8; 12] = random();
|
||||
@@ -140,8 +157,7 @@ pub fn serialize_jwe_aes_2(payload: &[u8], key: [u8; 32]) -> XResult<String> {
|
||||
let (f, t) = encryptor.finalize();
|
||||
e.extend_from_slice(&f);
|
||||
|
||||
let kek = Kek::from(key);
|
||||
let wrap_key = kek.wrap_vec(&data_key[..]).unwrap();
|
||||
let wrap_key = key_wrap_fn(&data_key)?;
|
||||
|
||||
let mut jwe = String::new();
|
||||
jwe.push_str(&header_b64);
|
||||
@@ -157,59 +173,52 @@ pub fn serialize_jwe_aes_2(payload: &[u8], key: [u8; 32]) -> XResult<String> {
|
||||
Ok(jwe)
|
||||
}
|
||||
|
||||
pub fn serialize_jwe_aes(payload: &[u8], key: &[u8]) -> XResult<String> {
|
||||
let mut header = JweHeader::new();
|
||||
header.set_content_encryption("A256GCM");
|
||||
header.set_claim("vendor", Some(Value::String("local-mini-kms".to_string())))?;
|
||||
// header.set_claim("version", Some(Value::String(get_master_key_checksum(key))))?;
|
||||
let encrypter = AeskwJweAlgorithm::A256kw.encrypter_from_bytes(key)?;
|
||||
Ok(format!("{}{}", LOCAL_KMS_PREFIX, jwe::serialize_compact(payload, &header, &encrypter)?))
|
||||
}
|
||||
|
||||
pub fn deserialize_jwe_aes_2(jwe: &str, key: [u8; 32]) -> XResult<(Vec<u8>, JweHeader2)> {
|
||||
fn deserialize_jwe_fn<F>(jwe: &str, key_unwrap_fn: F) -> XResult<(Vec<u8>, JweHeader2)>
|
||||
where
|
||||
F: Fn(&[u8]) -> XResult<Vec<u8>>,
|
||||
{
|
||||
let jwe_parts = jwe.split(".").collect::<Vec<&str>>();
|
||||
if jwe_parts.len() != 5 {
|
||||
panic!("Invalid jwe");
|
||||
return simple_error!("Invalid JWE: {}", 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 header_bytes = opt_result!(decode_url_safe_no_pad(jwe_parts[0]), "Invalid JWE header: {}, JWE: {}", jwe);
|
||||
let header: JweHeader2 = opt_result!(serde_json::from_slice(&header_bytes), "Invalid JWE header: {}, JWE: {}", jwe);
|
||||
let cek = opt_result!(decode_url_safe_no_pad(jwe_parts[1]), "Invalid JWE CEK: {}, JWE: {}", jwe);
|
||||
let iv = opt_result!(decode_url_safe_no_pad(jwe_parts[2]), "Invalid JWE IV: {}, JWE: {}", jwe);
|
||||
let ciphertext = opt_result!(decode_url_safe_no_pad(jwe_parts[3]), "Invalid JWE ciphertext: {}, JWE: {}", jwe);
|
||||
let tag = opt_result!(decode_url_safe_no_pad(jwe_parts[4]), "Invalid JWE tag: {}, JWE: {}", jwe);
|
||||
|
||||
let kek = Kek::from(key);
|
||||
let data_key = kek.unwrap_vec(&key_wrap).unwrap();
|
||||
let data_key_b32 = bytes_to_32(&data_key);
|
||||
let data_key = key_unwrap_fn(&cek)?;
|
||||
let data_key_b32 = opt_result!(to_bytes32(&data_key), "Invalid JWE CEK: {}, JWE: {}", jwe);
|
||||
|
||||
let mut decryptor = Aes256GcmStreamDecryptor::new(data_key_b32, &nonce);
|
||||
let mut decryptor = Aes256GcmStreamDecryptor::new(data_key_b32, &iv);
|
||||
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))
|
||||
let mut plaintext = decryptor.update(&ciphertext);
|
||||
let plaintext_2 = decryptor.update(&tag);
|
||||
let plaintext_final = opt_result!(decryptor.finalize(), "Invalid JWE: {}, JWE: {}", jwe);
|
||||
plaintext.extend_from_slice(&plaintext_2);
|
||||
plaintext.extend_from_slice(&plaintext_final);
|
||||
Ok((plaintext, header))
|
||||
}
|
||||
|
||||
pub fn deserialize_jwe_aes(jwe: &str, key: &[u8]) -> XResult<(Vec<u8>, JweHeader)> {
|
||||
let decrypter = AeskwJweAlgorithm::A256kw.decrypter_from_bytes(key)?;
|
||||
Ok(jwe::deserialize_compact(&get_jwe(jwe), &decrypter)?)
|
||||
#[inline]
|
||||
fn decode_url_safe_no_pad(s: &str) -> XResult<Vec<u8>> {
|
||||
Ok(URL_SAFE_NO_PAD.decode(s.as_bytes())?)
|
||||
}
|
||||
|
||||
fn bytes_to_32(bytes: &[u8]) -> [u8; 32] {
|
||||
#[inline]
|
||||
fn to_bytes32(bytes: &[u8]) -> XResult<[u8; 32]> {
|
||||
if bytes.len() != 32 {
|
||||
panic!("Invalid bytes");
|
||||
return simple_error!("Not valid 32 bytes");
|
||||
}
|
||||
let mut ret = [0; 32];
|
||||
for i in 0..32 {
|
||||
ret[i] = bytes[i];
|
||||
}
|
||||
ret
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_jwe(jwe: &str) -> String {
|
||||
if jwe.starts_with(LOCAL_KMS_PREFIX) {
|
||||
jwe.chars().skip(LOCAL_KMS_PREFIX.len()).collect()
|
||||
|
||||
Reference in New Issue
Block a user