1#![allow(non_camel_case_types)]
5
6mod jwe;
9
10use std::fmt;
11
12use crate::Result;
13use azure_core::{
14 base64,
15 json::{from_json, to_json},
16};
17use clap::ValueEnum;
18pub use jwe::{Jwe, JweEncryptor, WrapKeyResult};
19use serde::{de::DeserializeOwned, Deserialize, Serialize};
20
21pub trait Encode
23where
24 Self: Sized,
25{
26 fn decode(value: &str) -> Result<Self>;
28
29 fn encode(&self) -> Result<String>;
31}
32
33impl<T: DeserializeOwned + Serialize> Encode for T {
34 fn decode(value: &str) -> Result<Self> {
35 let buf = base64::decode_url_safe(value)?;
36 Ok(from_json(buf)?)
37 }
38
39 fn encode(&self) -> Result<String> {
40 let buf = to_json(self)?;
41 Ok(base64::encode_url_safe(buf))
42 }
43}
44
45#[derive(Debug, Serialize, Deserialize)]
47pub struct Header {
48 #[serde(rename = "alg")]
52 pub alg: Algorithm,
53
54 #[serde(rename = "enc", skip_serializing_if = "Option::is_none")]
56 pub enc: Option<EncryptionAlgorithm>,
57
58 #[serde(rename = "kid", skip_serializing_if = "Option::is_none")]
60 pub kid: Option<String>,
61
62 #[serde(rename = "typ")]
64 pub typ: Type,
65}
66
67#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
69#[serde(rename_all = "UPPERCASE")]
70pub enum Type {
71 JWE,
73
74 #[serde(untagged)]
76 Other(String),
77}
78
79impl fmt::Display for Type {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 match self {
82 Self::JWE => f.write_str("JWE"),
83 Self::Other(s) => f.write_str(s),
84 }
85 }
86}
87
88#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, ValueEnum)]
90#[serde(rename_all = "UPPERCASE")]
91pub enum Algorithm {
92 #[serde(rename = "RSA1_5")]
106 RSA1_5,
107
108 #[serde(rename = "RSA-OAEP")]
110 RSA_OAEP,
111
112 #[serde(rename = "RSA-OAEP-256")]
114 RSA_OAEP_256,
115
116 #[serde(untagged)]
118 #[value(skip)]
119 Other(String),
120}
121
122#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, ValueEnum)]
124#[serde(rename_all = "UPPERCASE")]
125pub enum EncryptionAlgorithm {
126 A128GCM,
131
132 A192GCM,
134
135 A256GCM,
137
138 #[serde(untagged)]
140 #[value(skip)]
141 Other(String),
142}
143
144impl fmt::Display for EncryptionAlgorithm {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 match self {
147 Self::A128GCM => f.write_str("A128GCM"),
148 Self::A192GCM => f.write_str("A192GCM"),
149 Self::A256GCM => f.write_str("A256GCM"),
150 Self::Other(s) => f.write_str(s),
151 }
152 }
153}
154
155#[derive(Debug)]
156#[doc(hidden)]
157pub enum Set {}
158
159#[derive(Debug)]
160#[doc(hidden)]
161pub enum Unset {}
162
163#[cfg(test)]
164mod tests {
165 use super::*;
166 use serde_json::json;
167
168 #[test]
169 fn header_encode_decode() {
170 let header = Header {
171 alg: Algorithm::RSA_OAEP_256,
172 enc: Some(EncryptionAlgorithm::A256GCM),
173 kid: Some("https://myvault.vault.azure.net/keys/mykey/1234567890abcdef".into()),
174 typ: Type::JWE,
175 };
176
177 let expected_json = json!({
178 "alg": "RSA-OAEP-256",
179 "enc": "A256GCM",
180 "kid": "https://myvault.vault.azure.net/keys/mykey/1234567890abcdef",
181 "typ": "JWE"
182 });
183 let expected_bytes = serde_json::to_vec(&expected_json).unwrap();
184 let expected_b64 = azure_core::base64::encode_url_safe(expected_bytes);
185
186 let encoded = header.encode().unwrap();
188 assert_eq!(encoded, expected_b64);
189
190 let decoded = Header::decode(&encoded).unwrap();
192 assert_eq!(decoded.alg, Algorithm::RSA_OAEP_256);
193 assert_eq!(decoded.enc, Some(EncryptionAlgorithm::A256GCM));
194 assert_eq!(
195 decoded.kid,
196 Some("https://myvault.vault.azure.net/keys/mykey/1234567890abcdef".into()),
197 );
198 assert_eq!(decoded.typ, Type::JWE);
199 }
200}