1#![allow(non_camel_case_types)]
5
6mod jwe;
7
8use std::fmt;
9
10use crate::Result;
11use azure_core::{
12 base64,
13 json::{from_json, to_json},
14};
15use clap::ValueEnum;
16pub use jwe::{Jwe, JweEncryptor, WrapKeyResult};
17use serde::{de::DeserializeOwned, Deserialize, Serialize};
18
19pub trait Encode
20where
21 Self: Sized,
22{
23 fn decode(value: &str) -> Result<Self>;
24 fn encode(&self) -> Result<String>;
25}
26
27impl<T: DeserializeOwned + Serialize> Encode for T {
28 fn decode(value: &str) -> Result<Self> {
29 let buf = base64::decode_url_safe(value)?;
30 Ok(from_json(buf)?)
31 }
32
33 fn encode(&self) -> Result<String> {
34 let buf = to_json(self)?;
35 Ok(base64::encode_url_safe(buf))
36 }
37}
38
39#[derive(Debug, Serialize, Deserialize)]
41pub struct Header {
42 #[serde(rename = "alg")]
46 pub alg: Algorithm,
47
48 #[serde(rename = "enc", skip_serializing_if = "Option::is_none")]
50 pub enc: Option<EncryptionAlgorithm>,
51
52 #[serde(rename = "kid", skip_serializing_if = "Option::is_none")]
54 pub kid: Option<String>,
55
56 #[serde(rename = "typ")]
58 pub typ: Type,
59}
60
61#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
62#[serde(rename_all = "UPPERCASE")]
63pub enum Type {
64 JWE,
65 #[serde(untagged)]
66 Other(String),
67}
68
69impl fmt::Display for Type {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 match self {
72 Self::JWE => f.write_str("JWE"),
73 Self::Other(s) => f.write_str(s),
74 }
75 }
76}
77
78#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, ValueEnum)]
79#[serde(rename_all = "UPPERCASE")]
80pub enum Algorithm {
81 #[serde(rename = "RSA1_5")]
94 RSA1_5,
95 #[serde(rename = "RSA-OAEP")]
96 RSA_OAEP,
97 #[serde(rename = "RSA-OAEP-256")]
98 RSA_OAEP_256,
99
100 #[serde(untagged)]
101 #[value(skip)]
102 Other(String),
103}
104
105#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, ValueEnum)]
106#[serde(rename_all = "UPPERCASE")]
107pub enum EncryptionAlgorithm {
108 A128GCM,
112 A192GCM,
113 A256GCM,
114
115 #[serde(untagged)]
116 #[value(skip)]
117 Other(String),
118}
119
120impl fmt::Display for EncryptionAlgorithm {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 match self {
123 Self::A128GCM => f.write_str("A128GCM"),
124 Self::A192GCM => f.write_str("A192GCM"),
125 Self::A256GCM => f.write_str("A256GCM"),
126 Self::Other(s) => f.write_str(s),
127 }
128 }
129}
130
131#[derive(Debug)]
132#[doc(hidden)]
133pub enum Set {}
134
135#[derive(Debug)]
136#[doc(hidden)]
137pub enum Unset {}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142 use serde_json::json;
143
144 #[test]
145 fn header_encode_decode() {
146 let header = Header {
147 alg: Algorithm::RSA_OAEP_256,
148 enc: Some(EncryptionAlgorithm::A256GCM),
149 kid: Some("https://myvault.vault.azure.net/keys/mykey/1234567890abcdef".into()),
150 typ: Type::JWE,
151 };
152
153 let expected_json = json!({
154 "alg": "RSA-OAEP-256",
155 "enc": "A256GCM",
156 "kid": "https://myvault.vault.azure.net/keys/mykey/1234567890abcdef",
157 "typ": "JWE"
158 });
159 let expected_bytes = serde_json::to_vec(&expected_json).unwrap();
160 let expected_b64 = azure_core::base64::encode_url_safe(expected_bytes);
161
162 let encoded = header.encode().unwrap();
164 assert_eq!(encoded, expected_b64);
165
166 let decoded = Header::decode(&encoded).unwrap();
168 assert_eq!(decoded.alg, Algorithm::RSA_OAEP_256);
169 assert_eq!(decoded.enc, Some(EncryptionAlgorithm::A256GCM));
170 assert_eq!(
171 decoded.kid,
172 Some("https://myvault.vault.azure.net/keys/mykey/1234567890abcdef".into()),
173 );
174 assert_eq!(decoded.typ, Type::JWE);
175 }
176}