use std::borrow::Cow;
use std::fmt::{self, Write};
use std::marker::PhantomData;
use std::str::FromStr;
use base64ct::Encoding;
use serde::de::{self, DeserializeOwned};
use serde::{self, Deserialize, Deserializer, Serialize, Serializer};
use crate::errors::{DecodeError, Error, ValidationError};
use crate::jwa::cea::EncryptionResult;
use crate::jwa::{self, cea, kma};
use crate::{FromCompactPart, ToCompactPart};
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum CompressionAlgorithm {
Deflate,
Other(String),
}
impl Serialize for CompressionAlgorithm {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let string = match *self {
CompressionAlgorithm::Deflate => "DEF",
CompressionAlgorithm::Other(ref other) => other,
};
serializer.serialize_str(string)
}
}
impl<'de> Deserialize<'de> for CompressionAlgorithm {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct CompressionAlgorithmVisitor;
impl<'de> de::Visitor<'de> for CompressionAlgorithmVisitor {
type Value = CompressionAlgorithm;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "a string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(match v {
"DEF" => CompressionAlgorithm::Deflate,
other => CompressionAlgorithm::Other(other.to_string()),
})
}
}
deserializer.deserialize_string(CompressionAlgorithmVisitor)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct RegisteredHeader {
#[serde(rename = "alg")]
pub cek_algorithm: kma::Algorithm,
#[serde(rename = "enc")]
pub enc_algorithm: cea::Algorithm,
#[serde(rename = "zip", skip_serializing_if = "Option::is_none")]
pub compression_algorithm: Option<CompressionAlgorithm>,
#[serde(rename = "typ", skip_serializing_if = "Option::is_none")]
pub media_type: Option<String>,
#[serde(rename = "cty", skip_serializing_if = "Option::is_none")]
pub content_type: Option<String>,
#[serde(rename = "jku", skip_serializing_if = "Option::is_none")]
pub web_key_url: Option<String>,
#[serde(rename = "jwk", skip_serializing_if = "Option::is_none")]
pub web_key: Option<String>,
#[serde(rename = "kid", skip_serializing_if = "Option::is_none")]
pub key_id: Option<String>,
#[serde(rename = "x5u", skip_serializing_if = "Option::is_none")]
pub x509_url: Option<String>,
#[serde(rename = "x5c", skip_serializing_if = "Option::is_none")]
pub x509_chain: Option<Vec<String>>,
#[serde(rename = "x5t", skip_serializing_if = "Option::is_none")]
pub x509_fingerprint: Option<String>,
#[serde(rename = "crit", skip_serializing_if = "Option::is_none")]
pub critical: Option<Vec<String>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct CekAlgorithmHeader {
#[serde(rename = "iv", skip_serializing_if = "Option::is_none")]
pub nonce: Option<Vec<u8>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tag: Option<Vec<u8>>,
#[serde(rename = "p2c", skip_serializing_if = "Option::is_none")]
pub count: Option<u32>,
#[serde(rename = "p2s", skip_serializing_if = "Option::is_none")]
pub salt: Option<String>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Serialize, Deserialize)]
pub struct Header<KmaHeader, T = ()> {
#[serde(flatten)]
pub registered: RegisteredHeader,
#[serde(flatten)]
pub kma: KmaHeader,
#[serde(flatten)]
pub private: T,
}
impl<KmaHeader, T> FromCompactPart for Header<KmaHeader, T>
where
KmaHeader: DeserializeOwned,
T: DeserializeOwned,
{
fn from_bytes(b: &[u8]) -> Result<Self, Error> {
Ok(serde_json::from_slice(b)?)
}
}
impl<KmaHeader, T> ToCompactPart for Header<KmaHeader, T>
where
KmaHeader: Serialize,
T: Serialize,
{
fn to_bytes(&self) -> Result<Cow<'_, [u8]>, Error> {
Ok(serde_json::to_vec(&self)?.into())
}
}
impl Header<()> {
pub fn from_registered_header(registered: RegisteredHeader) -> Self {
Self {
registered,
..Default::default()
}
}
}
impl From<RegisteredHeader> for Header<(), ()> {
fn from(registered: RegisteredHeader) -> Self {
Self::from_registered_header(registered)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Encrypted<KMA: kma::KMA, H = ()> {
header: Header<KMA::Header, H>,
res: EncryptionResult,
encrypted_cek: Vec<u8>,
}
impl<KMA, H> FromCompactPart for Encrypted<KMA, H>
where
KMA: kma::KMA,
H: DeserializeOwned,
{
fn from_bytes(b: &[u8]) -> Result<Self, Error> {
std::str::from_utf8(b)?.parse()
}
}
impl<KMA, H> ToCompactPart for Encrypted<KMA, H>
where
KMA: kma::KMA,
{
fn to_bytes(&self) -> Result<Cow<'_, [u8]>, Error> {
Ok(self.to_string().into_bytes().into())
}
}
impl<KMA: kma::KMA, H: Serialize> Serialize for Encrypted<KMA, H> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(self)
}
}
impl<'de, KMA: kma::KMA, H: DeserializeOwned> Deserialize<'de> for Encrypted<KMA, H> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct EncryptedVisitor<KMA, H>(PhantomData<(KMA, H)>);
impl<'de, KMA: kma::KMA, H: DeserializeOwned> de::Visitor<'de> for EncryptedVisitor<KMA, H> {
type Value = Encrypted<KMA, H>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a string containing a compact JOSE representation of a JWE")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
value.parse().map_err(E::custom)
}
}
deserializer.deserialize_str(EncryptedVisitor(PhantomData))
}
}
impl<KMA: kma::KMA, H> fmt::Display for Encrypted<KMA, H> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let [aad, iv, payload, tag] = self.res.split();
let s = unsafe { std::str::from_utf8_unchecked(aad) };
f.write_str(s)?;
let mut buf = [0; 1024];
let parts = [&self.encrypted_cek, iv, payload, tag];
for part in parts {
f.write_char('.')?;
for chunk in part.chunks(1024 / 4 * 3) {
f.write_str(crate::B64::encode(chunk, &mut buf).unwrap())?;
}
}
Ok(())
}
}
impl<KMA, H> FromStr for Encrypted<KMA, H>
where
KMA: kma::KMA,
H: DeserializeOwned,
{
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
fn decode(output: &mut [u8], input: &str, n: usize) -> Result<usize, base64ct::Error> {
Ok(crate::B64::decode(input, &mut output[n..])?.len() + n)
}
let sections: arrayvec::ArrayVec<_, 5> = s.splitn(5, '.').collect();
let [headerb64, cek, iv, payload, tag] = match sections.into_inner() {
Ok(s) => s,
Err(a) => {
return Err(Error::DecodeError(DecodeError::PartsLengthError {
expected: 5,
actual: a.len(),
}))
}
};
let len = headerb64.len() + (iv.len() + payload.len() + tag.len() + 9) * 3 / 4;
let len = len.max((headerb64.len() + 3) * 3 / 4);
let mut data = vec![0; len];
let n = decode(&mut data, headerb64, 0)?;
let header = serde_json::from_slice(&data[..n])?;
data[..headerb64.len()].copy_from_slice(headerb64.as_bytes());
let nonce = headerb64.len();
let p_idx = decode(&mut data, iv, nonce)?;
let tag_idx = decode(&mut data, payload, p_idx)?;
let len = decode(&mut data, tag, tag_idx)?;
data.truncate(len);
let res = EncryptionResult::from_raw(data, [nonce, p_idx, tag_idx, len]);
Ok(Self {
header,
encrypted_cek: crate::B64::decode_vec(cek)?,
res,
})
}
}
impl<KMA, H> Encrypted<KMA, H>
where
KMA: kma::KMA,
H: Serialize + DeserializeOwned,
{
pub fn decrypt<T, CEA>(self, key: &KMA::Key) -> Result<Decrypted<T, H>, Error>
where
CEA: jwa::cea::CEA,
T: FromCompactPart,
{
let Self {
header,
mut encrypted_cek,
mut res,
} = self;
if header.registered.cek_algorithm != KMA::ALG
|| header.registered.enc_algorithm != CEA::ENC
{
Err(Error::ValidationError(
ValidationError::WrongAlgorithmHeader,
))?;
}
let cek = KMA::unwrap(&mut encrypted_cek, key, header.kma)?;
let payload = CEA::decrypt(cek, &mut res)?;
if header.registered.compression_algorithm.is_some() {
return Err(Error::UnsupportedOperation);
}
let payload = T::from_bytes(payload)?;
Ok(Decrypted::new_with_header(payload, header.private))
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Decrypted<T, H = ()> {
pub header: H,
pub payload: T,
}
impl<T> Decrypted<T> {
pub fn new(payload: T) -> Self {
Self::new_with_header(payload, ())
}
}
impl<T> Decrypted<crate::Json<T>> {
pub fn new_json(payload: T) -> Self {
Self::new(crate::Json(payload))
}
}
impl<T, H> Decrypted<T, H> {
pub fn new_with_header(payload: T, header: H) -> Self {
Self { header, payload }
}
}
impl<T, H> Decrypted<T, H>
where
T: ToCompactPart,
H: Serialize + DeserializeOwned,
{
pub fn encrypt<CEA, KMA>(
self,
key: &KMA::Key,
key_settings: KMA::WrapSettings,
) -> Result<Encrypted<KMA, H>, Error>
where
CEA: jwa::cea::CEA,
KMA: jwa::kma::KMA,
{
let cek = KMA::generate_key::<CEA>(key);
let (encrypted_cek, cea_header) = KMA::wrap(&cek, key, key_settings)?;
let iv = CEA::generate_iv();
let payload = self.payload.to_bytes()?;
let header = Header {
kma: cea_header,
registered: RegisteredHeader {
cek_algorithm: KMA::ALG,
enc_algorithm: CEA::ENC,
..Default::default()
},
private: self.header,
};
let encoded_protected_header = crate::B64::encode_string(&header.to_bytes()?);
let res = CEA::encrypt(&cek, &payload, iv, encoded_protected_header.as_bytes())?;
Ok(Encrypted {
header,
res,
encrypted_cek,
})
}
}
impl<P, H> Decrypted<crate::ClaimsSet<P>, H>
where
crate::ClaimsSet<P>: Serialize + DeserializeOwned,
H: Serialize + DeserializeOwned + Clone,
{
pub fn validate(&self, options: crate::ValidationOptions) -> Result<(), Error> {
self.payload.registered.validate(options)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use serde_test::{assert_tokens, Token};
use super::*;
use crate::jwa::{cea, sign};
use crate::jwk::OctetKey;
use crate::test::{assert_serde_json, random_array, random_vec};
use crate::{jwk, jws, Json};
pub fn nonce() -> [u8; 12] {
random_array()
}
fn cek_oct_key(len: usize) -> OctetKey {
jwk::OctetKey::new(random_vec(len))
}
#[test]
fn compression_algorithm_serde_token() {
#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)]
struct Test {
test: CompressionAlgorithm,
}
let test_value = Test {
test: CompressionAlgorithm::Deflate,
};
assert_tokens(
&test_value,
&[
Token::Struct {
name: "Test",
len: 1,
},
Token::Str("test"),
Token::Str("DEF"),
Token::StructEnd,
],
);
let test_value = Test {
test: CompressionAlgorithm::Other("xxx".to_string()),
};
assert_tokens(
&test_value,
&[
Token::Struct {
name: "Test",
len: 1,
},
Token::Str("test"),
Token::Str("xxx"),
Token::StructEnd,
],
);
}
#[test]
fn compression_algorithm_json_serde() {
#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)]
struct Test {
test: CompressionAlgorithm,
}
let test_json = r#"{"test": "DEF"}"#;
assert_serde_json(
&Test {
test: CompressionAlgorithm::Deflate,
},
Some(test_json),
);
let test_json = r#"{"test": "xxx"}"#;
assert_serde_json(
&Test {
test: CompressionAlgorithm::Other("xxx".to_string()),
},
Some(test_json),
);
}
#[test]
fn jwe_interoperability_check() {
let external_token = "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..fHhEyBZ9S4CsGi1Y.gnTZjScRZu22rvk.F8SJn0TUAus8w_TaItsOJw";
let key_json = r#"{"k":"-wcjSeVOJ0V43ij5uDBeFlOR1w2T40jqIfICQb8-sUw","kty":"oct"}"#;
let key: jwk::JWK<()> = serde_json::from_str(key_json).unwrap();
let key = key.specified.octet_key().unwrap();
let token: Encrypted<kma::DirectEncryption> = external_token.parse().unwrap();
let decrypted_jwe = token.decrypt::<Json<String>, cea::A256GCM>(key).unwrap();
let decrypted_payload = decrypted_jwe.payload;
assert_eq!(decrypted_payload.0, "Encrypted");
}
#[test]
fn jwe_header_round_trips() {
let test_value: Header<()> = From::from(RegisteredHeader {
cek_algorithm: kma::Algorithm::RSA_OAEP,
enc_algorithm: cea::Algorithm::A256GCM,
..Default::default()
});
let test_json = r#"{"alg":"RSA-OAEP","enc":"A256GCM"}"#;
assert_serde_json(&test_value, Some(test_json));
let test_value: Header<()> = From::from(RegisteredHeader {
cek_algorithm: kma::Algorithm::RSA1_5,
enc_algorithm: cea::Algorithm::A128CBC_HS256,
..Default::default()
});
let test_json = r#"{"alg":"RSA1_5","enc":"A128CBC-HS256"}"#;
assert_serde_json(&test_value, Some(test_json));
let test_value: Header<()> = From::from(RegisteredHeader {
cek_algorithm: kma::Algorithm::A128KW,
enc_algorithm: cea::Algorithm::A128CBC_HS256,
..Default::default()
});
let test_json = r#"{"alg":"A128KW","enc":"A128CBC-HS256"}"#;
assert_serde_json(&test_value, Some(test_json));
}
#[test]
fn custom_jwe_header_round_trip() {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
struct CustomHeader {
something: String,
}
let test_value = Header {
registered: RegisteredHeader {
cek_algorithm: kma::Algorithm::RSA_OAEP,
enc_algorithm: cea::Algorithm::A256GCM,
..Default::default()
},
kma: (),
private: CustomHeader {
something: "foobar".to_string(),
},
};
let test_json = r#"{"alg":"RSA-OAEP","enc":"A256GCM","something":"foobar"}"#;
assert_serde_json(&test_value, Some(test_json));
}
#[test]
fn jwe_a256gcmkw_a256gcm_string_round_trip() {
let key = cek_oct_key(256 / 8);
let payload =
String::from("The true sign of intelligence is not knowledge but imagination.");
let jwe = Decrypted::new(Json(payload.clone()));
let cek_nonce = nonce();
let encrypted_jwe = jwe
.encrypt::<cea::A256GCM, kma::A256GCMKW>(&key, cek_nonce)
.unwrap();
assert_eq!(256 / 8, encrypted_jwe.encrypted_cek.len());
let json = serde_json::to_string(&encrypted_jwe).unwrap();
let deserialized_json: Encrypted<kma::A256GCMKW> = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized_json, encrypted_jwe);
let decrypted_jwe = encrypted_jwe
.decrypt::<Json<String>, cea::A256GCM>(&key)
.unwrap();
assert_eq!(payload, decrypted_jwe.payload.0);
}
#[test]
fn jwe_a256gcmkw_a256gcm_jws_round_trip() {
let claims = crate::ClaimsSet::<()> {
registered: crate::RegisteredClaims {
issuer: Some("https://www.acme.com".into()),
subject: Some("John Doe".into()),
audience: Some("htts://acme-customer.com".into()),
not_before: Some(1234.try_into().unwrap()),
..Default::default()
},
private: Default::default(),
};
let key = OctetKey::new("secret".to_string().into_bytes());
let jws = jws::Verified::new(claims);
let jws = jws.encode::<sign::HS256>(&key).unwrap();
let key = cek_oct_key(256 / 8);
let jwe = Decrypted::new(jws.clone());
let cek_nonce = nonce();
let encrypted_jwe = jwe
.encrypt::<cea::A256GCM, kma::A256GCMKW>(&key, cek_nonce)
.unwrap();
assert_eq!(256 / 8, encrypted_jwe.encrypted_cek.len());
let json = serde_json::to_string(&encrypted_jwe).unwrap();
let deserialized_json: Encrypted<kma::A256GCMKW> = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized_json, encrypted_jwe);
let decrypted_jwe = encrypted_jwe.decrypt::<_, cea::A256GCM>(&key).unwrap();
assert_eq!(jws, decrypted_jwe.payload);
}
#[test]
fn jwe_dir_aes256gcm_jws_round_trip() {
let claims = crate::ClaimsSet::<()> {
registered: crate::RegisteredClaims {
issuer: Some("https://www.acme.com".into()),
subject: Some("John Doe".into()),
audience: Some("htts://acme-customer.com".into()),
not_before: Some(1234.try_into().unwrap()),
..Default::default()
},
private: Default::default(),
};
let key = OctetKey::new("secret".to_string().into_bytes());
let jws = jws::Verified::new(claims);
let jws = jws.encode::<sign::HS256>(&key).unwrap();
let key = cek_oct_key(256 / 8);
let jwe = Decrypted::new(jws.clone());
let encrypted_jwe = jwe
.encrypt::<cea::A256GCM, kma::DirectEncryption>(&key, ())
.unwrap();
assert!(encrypted_jwe.encrypted_cek.is_empty());
let json = serde_json::to_string(&encrypted_jwe).unwrap();
let deserialized_json: Encrypted<kma::DirectEncryption> =
serde_json::from_str(&json).unwrap();
assert_eq!(deserialized_json, encrypted_jwe);
let decrypted_jwe = encrypted_jwe.decrypt::<_, cea::A256GCM>(&key).unwrap();
assert_eq!(jws, decrypted_jwe.payload);
}
#[test]
#[should_panic(expected = "WrongAlgorithmHeader")]
fn decrypt_with_mismatch_cek_algorithm() {
let key = cek_oct_key(256 / 8);
let payload = "The true sign of intelligence is not knowledge but imagination.";
let jwe = Decrypted::new(payload.as_bytes().to_vec());
let cek_nonce = nonce();
let encrypted_jwe = jwe
.encrypt::<cea::A256GCM, kma::A256GCMKW>(&key, cek_nonce)
.unwrap();
let encrypted_jwe: Encrypted<kma::A128GCMKW> = encrypted_jwe.to_string().parse().unwrap();
encrypted_jwe
.decrypt::<Vec<u8>, cea::A256GCM>(&key)
.unwrap();
}
#[test]
#[should_panic(expected = "WrongAlgorithmHeader")]
fn decrypt_with_mismatch_enc_algorithm() {
let key = cek_oct_key(256 / 8);
let payload = "The true sign of intelligence is not knowledge but imagination.";
let jwe = Decrypted::new(payload.as_bytes().to_vec());
let cek_nonce = nonce();
let encrypted_jwe = jwe
.encrypt::<cea::A256GCM, kma::A256GCMKW>(&key, cek_nonce)
.unwrap();
encrypted_jwe
.decrypt::<Vec<u8>, cea::A128GCM>(&key)
.unwrap();
}
#[test]
#[should_panic(expected = "PartsLengthError")]
fn decrypt_with_incorrect_length() {
let _token: Encrypted<kma::DirectEncryption> = "INVALID".parse().unwrap();
}
#[test]
#[should_panic(expected = "UnspecifiedCryptographicError")]
fn invalid_nonce_for_aes256gcmkw() {
let key = cek_oct_key(256 / 8);
let payload = "The true sign of intelligence is not knowledge but imagination.";
let jwe = Decrypted::new(payload.as_bytes().to_vec());
let cek_nonce = nonce();
let mut encrypted_jwe = jwe
.encrypt::<cea::A256GCM, kma::A256GCMKW>(&key, cek_nonce)
.unwrap();
let [_, iv, payload, tag] = encrypted_jwe.res.split();
encrypted_jwe.header.kma.iv = [0; 96 / 8];
encrypted_jwe.res = EncryptionResult::from([
crate::B64::encode_string(&encrypted_jwe.header.to_bytes().unwrap()).as_bytes(),
iv,
payload,
tag,
]);
encrypted_jwe
.decrypt::<Vec<u8>, cea::A256GCM>(&key)
.unwrap();
}
#[test]
#[should_panic(expected = "UnspecifiedCryptographicError")]
fn invalid_tag_for_aes256gcmkw() {
let key = cek_oct_key(256 / 8);
let payload = "The true sign of intelligence is not knowledge but imagination.";
let jwe = Decrypted::new(payload.as_bytes().to_vec());
let cek_nonce = nonce();
let mut encrypted_jwe = jwe
.encrypt::<cea::A256GCM, kma::A256GCMKW>(&key, cek_nonce)
.unwrap();
let [_, iv, payload, tag] = encrypted_jwe.res.split();
encrypted_jwe.header.kma.tag = [0; 16];
encrypted_jwe.res = EncryptionResult::from([
crate::B64::encode_string(&encrypted_jwe.header.to_bytes().unwrap()).as_bytes(),
iv,
payload,
tag,
]);
let _token: Decrypted<Vec<u8>, ()> =
encrypted_jwe.decrypt::<_, cea::A256GCM>(&key).unwrap();
}
#[test]
#[should_panic(expected = "UnspecifiedCryptographicError")]
fn invalid_tag_for_aes256gcm() {
let key = cek_oct_key(256 / 8);
let payload = "The true sign of intelligence is not knowledge but imagination.";
let jwe = Decrypted::new(payload.as_bytes().to_vec());
let cek_nonce = nonce();
let mut encrypted_jwe = jwe
.encrypt::<cea::A256GCM, kma::A256GCMKW>(&key, cek_nonce)
.unwrap();
let [header, iv, payload, _] = encrypted_jwe.res.split();
encrypted_jwe.res = EncryptionResult::from([header, iv, payload, &[0]]);
let _token: Decrypted<Vec<u8>, ()> =
encrypted_jwe.decrypt::<_, cea::A256GCM>(&key).unwrap();
}
#[test]
#[should_panic(expected = "UnspecifiedCryptographicError")]
fn invalid_modified_header_for_aes256gcm() {
let key = cek_oct_key(256 / 8);
let payload = "The true sign of intelligence is not knowledge but imagination.";
let jwe = Decrypted::new(payload.as_bytes().to_vec());
let cek_nonce = nonce();
let mut encrypted_jwe = jwe
.encrypt::<cea::A256GCM, kma::A256GCMKW>(&key, cek_nonce)
.unwrap();
let [_, iv, payload, tag] = encrypted_jwe.res.split();
encrypted_jwe.header.registered.media_type = Some("JOSE+JSON".to_string());
encrypted_jwe.res = EncryptionResult::from([
crate::B64::encode_string(&encrypted_jwe.header.to_bytes().unwrap()).as_bytes(),
iv,
payload,
tag,
]);
let _token: Decrypted<Vec<u8>, ()> =
encrypted_jwe.decrypt::<_, cea::A256GCM>(&key).unwrap();
}
#[test]
#[should_panic(expected = "UnspecifiedCryptographicError")]
fn invalid_modified_encrypted_cek_for_aes256gcm() {
let key = cek_oct_key(256 / 8);
let payload = "The true sign of intelligence is not knowledge but imagination.";
let jwe = Decrypted::new(payload.as_bytes().to_vec());
let cek_nonce = nonce();
let mut encrypted_jwe = jwe
.encrypt::<cea::A256GCM, kma::A256GCMKW>(&key, cek_nonce)
.unwrap();
encrypted_jwe.encrypted_cek = vec![0u8; 256 / 8];
let _token: Decrypted<Vec<u8>, ()> =
encrypted_jwe.decrypt::<_, cea::A256GCM>(&key).unwrap();
}
#[test]
#[should_panic(expected = "UnspecifiedCryptographicError")]
fn invalid_modified_encrypted_payload_for_aes256gcm() {
let key = cek_oct_key(256 / 8);
let payload = "The true sign of intelligence is not knowledge but imagination.";
let jwe = Decrypted::new(payload.as_bytes().to_vec());
let cek_nonce = nonce();
let mut encrypted_jwe = jwe
.encrypt::<cea::A256GCM, kma::A256GCMKW>(&key, cek_nonce)
.unwrap();
let [header, iv, _, tag] = encrypted_jwe.res.split();
encrypted_jwe.res = EncryptionResult::from([header, iv, &[0; 32], tag]);
let _token: Decrypted<Vec<u8>, ()> =
encrypted_jwe.decrypt::<_, cea::A256GCM>(&key).unwrap();
}
#[test]
#[should_panic(expected = "UnspecifiedCryptographicError")]
fn invalid_modified_encrypted_nonce_for_aes256gcm() {
let key = cek_oct_key(256 / 8);
let payload = "The true sign of intelligence is not knowledge but imagination.";
let jwe = Decrypted::new(payload.as_bytes().to_vec());
let cek_nonce = nonce();
let mut encrypted_jwe = jwe
.encrypt::<cea::A256GCM, kma::A256GCMKW>(&key, cek_nonce)
.unwrap();
let [header, _, payload, tag] = encrypted_jwe.res.split();
encrypted_jwe.res = EncryptionResult::from([header, &[0; 96 / 8], payload, tag]);
let _token: Decrypted<Vec<u8>, ()> =
encrypted_jwe.decrypt::<_, cea::A256GCM>(&key).unwrap();
}
}