1use quick_xml::events::{BytesStart, Event};
2use quick_xml::Reader;
3use rustauth_core::error::RustAuthError;
4use time::{Duration, OffsetDateTime};
5
6use super::xml::{local_name, validate_saml_xml};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct SamlConditions {
10 pub not_before: Option<String>,
11 pub not_on_or_after: Option<String>,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct TimestampValidationOptions {
16 pub clock_skew: Duration,
17 pub require_timestamps: bool,
18}
19
20impl Default for TimestampValidationOptions {
21 fn default() -> Self {
22 Self {
23 clock_skew: Duration::minutes(5),
24 require_timestamps: false,
25 }
26 }
27}
28
29#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
30pub enum SamlSecurityError {
31 #[error("SAML assertion missing required timestamp conditions")]
32 MissingTimestampConditions,
33 #[error("SAML assertion has invalid NotBefore timestamp")]
34 InvalidNotBefore,
35 #[error("SAML assertion has invalid NotOnOrAfter timestamp")]
36 InvalidNotOnOrAfter,
37 #[error("SAML assertion is not yet valid")]
38 NotYetValid,
39 #[error("SAML assertion has expired")]
40 Expired,
41 #[error("SAML signature algorithm not recognized: {0}")]
42 UnknownSignatureAlgorithm(String),
43 #[error("SAML digest algorithm not recognized: {0}")]
44 UnknownDigestAlgorithm(String),
45 #[error("SAML signature algorithm is deprecated: {0}")]
46 DeprecatedSignatureAlgorithm(String),
47 #[error("SAML digest algorithm is deprecated: {0}")]
48 DeprecatedDigestAlgorithm(String),
49 #[error("SAML signature algorithm not in allow-list: {0}")]
50 SignatureAlgorithmNotAllowed(String),
51 #[error("SAML digest algorithm not in allow-list: {0}")]
52 DigestAlgorithmNotAllowed(String),
53 #[error("SAML key encryption algorithm not recognized: {0}")]
54 UnknownKeyEncryptionAlgorithm(String),
55 #[error("SAML data encryption algorithm not recognized: {0}")]
56 UnknownDataEncryptionAlgorithm(String),
57 #[error("SAML key encryption algorithm is deprecated: {0}")]
58 DeprecatedKeyEncryptionAlgorithm(String),
59 #[error("SAML data encryption algorithm is deprecated: {0}")]
60 DeprecatedDataEncryptionAlgorithm(String),
61 #[error("SAML key encryption algorithm not in allow-list: {0}")]
62 KeyEncryptionAlgorithmNotAllowed(String),
63 #[error("SAML data encryption algorithm not in allow-list: {0}")]
64 DataEncryptionAlgorithmNotAllowed(String),
65}
66
67pub fn validate_saml_timestamp(
68 conditions: Option<&SamlConditions>,
69 options: TimestampValidationOptions,
70) -> Result<(), SamlSecurityError> {
71 validate_saml_timestamp_at(conditions, options, OffsetDateTime::now_utc())
72}
73
74pub fn validate_saml_timestamp_at(
75 conditions: Option<&SamlConditions>,
76 options: TimestampValidationOptions,
77 now: OffsetDateTime,
78) -> Result<(), SamlSecurityError> {
79 let has_timestamps = conditions.is_some_and(|conditions| {
80 conditions.not_before.is_some() || conditions.not_on_or_after.is_some()
81 });
82 if !has_timestamps {
83 return if options.require_timestamps {
84 Err(SamlSecurityError::MissingTimestampConditions)
85 } else {
86 Ok(())
87 };
88 }
89
90 let Some(conditions) = conditions else {
91 return if options.require_timestamps {
92 Err(SamlSecurityError::MissingTimestampConditions)
93 } else {
94 Ok(())
95 };
96 };
97
98 if let Some(not_before) = &conditions.not_before {
99 let parsed =
100 OffsetDateTime::parse(not_before, &time::format_description::well_known::Rfc3339)
101 .map_err(|_| SamlSecurityError::InvalidNotBefore)?;
102 if now < parsed - options.clock_skew {
103 return Err(SamlSecurityError::NotYetValid);
104 }
105 }
106
107 if let Some(not_on_or_after) = &conditions.not_on_or_after {
108 let parsed = OffsetDateTime::parse(
109 not_on_or_after,
110 &time::format_description::well_known::Rfc3339,
111 )
112 .map_err(|_| SamlSecurityError::InvalidNotOnOrAfter)?;
113 if now > parsed + options.clock_skew {
114 return Err(SamlSecurityError::Expired);
115 }
116 }
117
118 Ok(())
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
122#[serde(rename_all = "camelCase")]
123pub enum DeprecatedAlgorithmBehavior {
124 Reject,
125 Warn,
126 Allow,
127}
128
129#[derive(Debug, Clone, Copy, PartialEq, Eq)]
130pub enum SignatureAlgorithm {
131 RsaSha1,
132 RsaSha256,
133 RsaSha384,
134 RsaSha512,
135 EcdsaSha256,
136 EcdsaSha384,
137 EcdsaSha512,
138}
139
140impl SignatureAlgorithm {
141 pub fn as_uri(self) -> &'static str {
142 match self {
143 Self::RsaSha1 => "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
144 Self::RsaSha256 => "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
145 Self::RsaSha384 => "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
146 Self::RsaSha512 => "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
147 Self::EcdsaSha256 => "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256",
148 Self::EcdsaSha384 => "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
149 Self::EcdsaSha512 => "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512",
150 }
151 }
152}
153
154pub fn validate_saml_config_algorithms(
155 signature_algorithm: Option<&str>,
156 digest_algorithm: Option<&str>,
157) -> Result<(), SamlSecurityError> {
158 validate_saml_config_algorithms_with_policy(
159 signature_algorithm,
160 digest_algorithm,
161 DeprecatedAlgorithmBehavior::Warn,
162 None,
163 None,
164 )
165}
166
167pub fn validate_saml_config_algorithms_with_policy(
168 signature_algorithm: Option<&str>,
169 digest_algorithm: Option<&str>,
170 on_deprecated: DeprecatedAlgorithmBehavior,
171 allowed_signature_algorithms: Option<&[String]>,
172 allowed_digest_algorithms: Option<&[String]>,
173) -> Result<(), SamlSecurityError> {
174 if let Some(algorithm) = signature_algorithm {
175 let normalized = normalize_signature_algorithm(algorithm);
176 if let Some(allowed) = allowed_signature_algorithms {
177 let is_allowed = allowed
178 .iter()
179 .map(|algorithm| normalize_signature_algorithm(algorithm))
180 .any(|allowed| allowed == normalized);
181 if !is_allowed {
182 return Err(SamlSecurityError::SignatureAlgorithmNotAllowed(
183 algorithm.to_owned(),
184 ));
185 }
186 } else if is_deprecated_signature_algorithm(&normalized)
187 && on_deprecated == DeprecatedAlgorithmBehavior::Reject
188 {
189 return Err(SamlSecurityError::DeprecatedSignatureAlgorithm(
190 algorithm.to_owned(),
191 ));
192 } else if !is_known_signature_algorithm(&normalized) {
193 return Err(SamlSecurityError::UnknownSignatureAlgorithm(
194 algorithm.to_owned(),
195 ));
196 }
197 }
198 if let Some(algorithm) = digest_algorithm {
199 let normalized = normalize_digest_algorithm(algorithm);
200 if let Some(allowed) = allowed_digest_algorithms {
201 let is_allowed = allowed
202 .iter()
203 .map(|algorithm| normalize_digest_algorithm(algorithm))
204 .any(|allowed| allowed == normalized);
205 if !is_allowed {
206 return Err(SamlSecurityError::DigestAlgorithmNotAllowed(
207 algorithm.to_owned(),
208 ));
209 }
210 } else if is_deprecated_digest_algorithm(&normalized)
211 && on_deprecated == DeprecatedAlgorithmBehavior::Reject
212 {
213 return Err(SamlSecurityError::DeprecatedDigestAlgorithm(
214 algorithm.to_owned(),
215 ));
216 } else if !is_known_digest_algorithm(&normalized) {
217 return Err(SamlSecurityError::UnknownDigestAlgorithm(
218 algorithm.to_owned(),
219 ));
220 }
221 }
222 Ok(())
223}
224
225#[derive(Debug, Clone, Default, PartialEq, Eq)]
226pub struct SamlRuntimeAlgorithms {
227 pub signature_algorithms: Vec<String>,
228 pub digest_algorithms: Vec<String>,
229 pub key_encryption_algorithms: Vec<String>,
230 pub data_encryption_algorithms: Vec<String>,
231}
232
233#[derive(Debug, Clone, Copy, PartialEq, Eq)]
234pub struct SamlRuntimeAlgorithmPolicy<'a> {
235 pub on_deprecated: DeprecatedAlgorithmBehavior,
236 pub allowed_signature_algorithms: Option<&'a [String]>,
237 pub allowed_digest_algorithms: Option<&'a [String]>,
238 pub allowed_key_encryption_algorithms: Option<&'a [String]>,
239 pub allowed_data_encryption_algorithms: Option<&'a [String]>,
240}
241
242impl Default for SamlRuntimeAlgorithmPolicy<'_> {
243 fn default() -> Self {
244 Self {
245 on_deprecated: DeprecatedAlgorithmBehavior::Warn,
246 allowed_signature_algorithms: None,
247 allowed_digest_algorithms: None,
248 allowed_key_encryption_algorithms: None,
249 allowed_data_encryption_algorithms: None,
250 }
251 }
252}
253
254pub fn collect_saml_runtime_algorithms(xml: &str) -> Result<SamlRuntimeAlgorithms, RustAuthError> {
255 validate_saml_xml(xml)?;
256
257 let mut reader = Reader::from_str(xml);
258 reader.config_mut().trim_text(true);
259 let mut stack = Vec::new();
260 let mut algorithms = SamlRuntimeAlgorithms::default();
261
262 loop {
263 match reader.read_event() {
264 Ok(Event::Start(element)) => {
265 let name = local_name(element.name().as_ref())?;
266 collect_algorithm(&reader, &element, &name, &stack, &mut algorithms)?;
267 stack.push(name);
268 }
269 Ok(Event::Empty(element)) => {
270 let name = local_name(element.name().as_ref())?;
271 collect_algorithm(&reader, &element, &name, &stack, &mut algorithms)?;
272 }
273 Ok(Event::End(_)) => {
274 stack.pop();
275 }
276 Ok(Event::Eof) => break,
277 Err(error) => return Err(RustAuthError::Api(format!("Invalid SAML XML: {error}"))),
278 Ok(_) => {}
279 }
280 }
281
282 Ok(algorithms)
283}
284
285pub fn validate_saml_runtime_algorithms(
286 algorithms: &SamlRuntimeAlgorithms,
287 policy: SamlRuntimeAlgorithmPolicy<'_>,
288) -> Result<(), SamlSecurityError> {
289 for algorithm in &algorithms.signature_algorithms {
290 validate_signature_algorithm(
291 algorithm,
292 policy.on_deprecated,
293 policy.allowed_signature_algorithms,
294 )?;
295 }
296 for algorithm in &algorithms.digest_algorithms {
297 validate_digest_algorithm(
298 algorithm,
299 policy.on_deprecated,
300 policy.allowed_digest_algorithms,
301 )?;
302 }
303 for algorithm in &algorithms.key_encryption_algorithms {
304 validate_key_encryption_algorithm(
305 algorithm,
306 policy.on_deprecated,
307 policy.allowed_key_encryption_algorithms,
308 )?;
309 }
310 for algorithm in &algorithms.data_encryption_algorithms {
311 validate_data_encryption_algorithm(
312 algorithm,
313 policy.on_deprecated,
314 policy.allowed_data_encryption_algorithms,
315 )?;
316 }
317 Ok(())
318}
319
320fn collect_algorithm(
321 reader: &Reader<&[u8]>,
322 element: &BytesStart<'_>,
323 name: &str,
324 stack: &[String],
325 algorithms: &mut SamlRuntimeAlgorithms,
326) -> Result<(), RustAuthError> {
327 let Some(algorithm) = attr(reader, element, "Algorithm")? else {
328 return Ok(());
329 };
330 match name {
331 "SignatureMethod" => algorithms.signature_algorithms.push(algorithm),
332 "DigestMethod" => algorithms.digest_algorithms.push(algorithm),
333 "EncryptionMethod" if stack.iter().any(|item| item == "EncryptedKey") => {
334 algorithms.key_encryption_algorithms.push(algorithm);
335 }
336 "EncryptionMethod" if stack.iter().any(|item| item == "EncryptedData") => {
337 algorithms.data_encryption_algorithms.push(algorithm);
338 }
339 _ => {}
340 }
341 Ok(())
342}
343
344fn attr(
345 reader: &Reader<&[u8]>,
346 element: &BytesStart<'_>,
347 name: &str,
348) -> Result<Option<String>, RustAuthError> {
349 for attribute in element.attributes() {
350 let attribute = attribute.map_err(|error| RustAuthError::Api(error.to_string()))?;
351 if local_name(attribute.key.as_ref())? == name {
352 return attribute
353 .decode_and_unescape_value(reader.decoder())
354 .map(|value| Some(value.into_owned()))
355 .map_err(|error| RustAuthError::Api(error.to_string()));
356 }
357 }
358 Ok(None)
359}
360
361fn normalize_signature_algorithm(algorithm: &str) -> String {
362 match algorithm.to_ascii_lowercase().as_str() {
363 "sha1" | "rsa-sha1" => SignatureAlgorithm::RsaSha1.as_uri().to_owned(),
364 "sha256" | "rsa-sha256" => SignatureAlgorithm::RsaSha256.as_uri().to_owned(),
365 "sha384" | "rsa-sha384" => SignatureAlgorithm::RsaSha384.as_uri().to_owned(),
366 "sha512" | "rsa-sha512" => SignatureAlgorithm::RsaSha512.as_uri().to_owned(),
367 "ecdsa-sha256" => SignatureAlgorithm::EcdsaSha256.as_uri().to_owned(),
368 "ecdsa-sha384" => SignatureAlgorithm::EcdsaSha384.as_uri().to_owned(),
369 "ecdsa-sha512" => SignatureAlgorithm::EcdsaSha512.as_uri().to_owned(),
370 _ => algorithm.to_owned(),
371 }
372}
373
374fn normalize_digest_algorithm(algorithm: &str) -> String {
375 match algorithm.to_ascii_lowercase().as_str() {
376 "sha1" => DigestAlgorithm::Sha1.as_uri().to_owned(),
377 "sha256" => DigestAlgorithm::Sha256.as_uri().to_owned(),
378 "sha384" => DigestAlgorithm::Sha384.as_uri().to_owned(),
379 "sha512" => DigestAlgorithm::Sha512.as_uri().to_owned(),
380 _ => algorithm.to_owned(),
381 }
382}
383
384fn normalize_key_encryption_algorithm(algorithm: &str) -> String {
385 match algorithm.to_ascii_lowercase().as_str() {
386 "rsa-1_5" | "rsa1_5" => KeyEncryptionAlgorithm::Rsa15.as_uri().to_owned(),
387 "rsa-oaep" | "rsa-oaep-mgf1p" => KeyEncryptionAlgorithm::RsaOaep.as_uri().to_owned(),
388 "rsa-oaep-sha256" => KeyEncryptionAlgorithm::RsaOaepSha256.as_uri().to_owned(),
389 _ => algorithm.to_owned(),
390 }
391}
392
393fn normalize_data_encryption_algorithm(algorithm: &str) -> String {
394 match algorithm.to_ascii_lowercase().as_str() {
395 "tripledes-cbc" | "3des-cbc" => DataEncryptionAlgorithm::TripleDesCbc.as_uri().to_owned(),
396 "aes128-cbc" => DataEncryptionAlgorithm::Aes128Cbc.as_uri().to_owned(),
397 "aes192-cbc" => DataEncryptionAlgorithm::Aes192Cbc.as_uri().to_owned(),
398 "aes256-cbc" => DataEncryptionAlgorithm::Aes256Cbc.as_uri().to_owned(),
399 "aes128-gcm" => DataEncryptionAlgorithm::Aes128Gcm.as_uri().to_owned(),
400 "aes192-gcm" => DataEncryptionAlgorithm::Aes192Gcm.as_uri().to_owned(),
401 "aes256-gcm" => DataEncryptionAlgorithm::Aes256Gcm.as_uri().to_owned(),
402 _ => algorithm.to_owned(),
403 }
404}
405
406fn validate_signature_algorithm(
407 algorithm: &str,
408 on_deprecated: DeprecatedAlgorithmBehavior,
409 allowed: Option<&[String]>,
410) -> Result<(), SamlSecurityError> {
411 let normalized = normalize_signature_algorithm(algorithm);
412 if let Some(allowed) = allowed {
413 let is_allowed = allowed
414 .iter()
415 .map(|algorithm| normalize_signature_algorithm(algorithm))
416 .any(|allowed| allowed == normalized);
417 if !is_allowed {
418 return Err(SamlSecurityError::SignatureAlgorithmNotAllowed(
419 algorithm.to_owned(),
420 ));
421 }
422 } else if is_deprecated_signature_algorithm(&normalized)
423 && on_deprecated == DeprecatedAlgorithmBehavior::Reject
424 {
425 return Err(SamlSecurityError::DeprecatedSignatureAlgorithm(
426 algorithm.to_owned(),
427 ));
428 } else if !is_known_signature_algorithm(&normalized) {
429 return Err(SamlSecurityError::UnknownSignatureAlgorithm(
430 algorithm.to_owned(),
431 ));
432 }
433 Ok(())
434}
435
436fn validate_digest_algorithm(
437 algorithm: &str,
438 on_deprecated: DeprecatedAlgorithmBehavior,
439 allowed: Option<&[String]>,
440) -> Result<(), SamlSecurityError> {
441 let normalized = normalize_digest_algorithm(algorithm);
442 if let Some(allowed) = allowed {
443 let is_allowed = allowed
444 .iter()
445 .map(|algorithm| normalize_digest_algorithm(algorithm))
446 .any(|allowed| allowed == normalized);
447 if !is_allowed {
448 return Err(SamlSecurityError::DigestAlgorithmNotAllowed(
449 algorithm.to_owned(),
450 ));
451 }
452 } else if is_deprecated_digest_algorithm(&normalized)
453 && on_deprecated == DeprecatedAlgorithmBehavior::Reject
454 {
455 return Err(SamlSecurityError::DeprecatedDigestAlgorithm(
456 algorithm.to_owned(),
457 ));
458 } else if !is_known_digest_algorithm(&normalized) {
459 return Err(SamlSecurityError::UnknownDigestAlgorithm(
460 algorithm.to_owned(),
461 ));
462 }
463 Ok(())
464}
465
466fn is_known_signature_algorithm(algorithm: &str) -> bool {
467 [
468 SignatureAlgorithm::RsaSha1,
469 SignatureAlgorithm::RsaSha256,
470 SignatureAlgorithm::RsaSha384,
471 SignatureAlgorithm::RsaSha512,
472 SignatureAlgorithm::EcdsaSha256,
473 SignatureAlgorithm::EcdsaSha384,
474 SignatureAlgorithm::EcdsaSha512,
475 ]
476 .into_iter()
477 .any(|known| known.as_uri() == algorithm)
478}
479
480fn is_deprecated_signature_algorithm(algorithm: &str) -> bool {
481 SignatureAlgorithm::RsaSha1.as_uri() == algorithm
482}
483
484fn is_known_digest_algorithm(algorithm: &str) -> bool {
485 [
486 DigestAlgorithm::Sha1,
487 DigestAlgorithm::Sha256,
488 DigestAlgorithm::Sha384,
489 DigestAlgorithm::Sha512,
490 ]
491 .into_iter()
492 .any(|known| known.as_uri() == algorithm)
493}
494
495fn is_deprecated_digest_algorithm(algorithm: &str) -> bool {
496 DigestAlgorithm::Sha1.as_uri() == algorithm
497}
498
499fn validate_key_encryption_algorithm(
500 algorithm: &str,
501 on_deprecated: DeprecatedAlgorithmBehavior,
502 allowed: Option<&[String]>,
503) -> Result<(), SamlSecurityError> {
504 let normalized = normalize_key_encryption_algorithm(algorithm);
505 if let Some(allowed) = allowed {
506 let is_allowed = allowed
507 .iter()
508 .map(|algorithm| normalize_key_encryption_algorithm(algorithm))
509 .any(|allowed| allowed == normalized);
510 if !is_allowed {
511 return Err(SamlSecurityError::KeyEncryptionAlgorithmNotAllowed(
512 algorithm.to_owned(),
513 ));
514 }
515 } else if is_deprecated_key_encryption_algorithm(&normalized)
516 && on_deprecated == DeprecatedAlgorithmBehavior::Reject
517 {
518 return Err(SamlSecurityError::DeprecatedKeyEncryptionAlgorithm(
519 algorithm.to_owned(),
520 ));
521 } else if !is_known_key_encryption_algorithm(&normalized) {
522 return Err(SamlSecurityError::UnknownKeyEncryptionAlgorithm(
523 algorithm.to_owned(),
524 ));
525 }
526 Ok(())
527}
528
529fn validate_data_encryption_algorithm(
530 algorithm: &str,
531 on_deprecated: DeprecatedAlgorithmBehavior,
532 allowed: Option<&[String]>,
533) -> Result<(), SamlSecurityError> {
534 let normalized = normalize_data_encryption_algorithm(algorithm);
535 if let Some(allowed) = allowed {
536 let is_allowed = allowed
537 .iter()
538 .map(|algorithm| normalize_data_encryption_algorithm(algorithm))
539 .any(|allowed| allowed == normalized);
540 if !is_allowed {
541 return Err(SamlSecurityError::DataEncryptionAlgorithmNotAllowed(
542 algorithm.to_owned(),
543 ));
544 }
545 } else if is_deprecated_data_encryption_algorithm(&normalized)
546 && on_deprecated == DeprecatedAlgorithmBehavior::Reject
547 {
548 return Err(SamlSecurityError::DeprecatedDataEncryptionAlgorithm(
549 algorithm.to_owned(),
550 ));
551 } else if !is_known_data_encryption_algorithm(&normalized) {
552 return Err(SamlSecurityError::UnknownDataEncryptionAlgorithm(
553 algorithm.to_owned(),
554 ));
555 }
556 Ok(())
557}
558
559fn is_known_key_encryption_algorithm(algorithm: &str) -> bool {
560 [
561 KeyEncryptionAlgorithm::Rsa15,
562 KeyEncryptionAlgorithm::RsaOaep,
563 KeyEncryptionAlgorithm::RsaOaepSha256,
564 ]
565 .into_iter()
566 .any(|known| known.as_uri() == algorithm)
567}
568
569fn is_deprecated_key_encryption_algorithm(algorithm: &str) -> bool {
570 KeyEncryptionAlgorithm::Rsa15.as_uri() == algorithm
571}
572
573fn is_known_data_encryption_algorithm(algorithm: &str) -> bool {
574 [
575 DataEncryptionAlgorithm::TripleDesCbc,
576 DataEncryptionAlgorithm::Aes128Cbc,
577 DataEncryptionAlgorithm::Aes192Cbc,
578 DataEncryptionAlgorithm::Aes256Cbc,
579 DataEncryptionAlgorithm::Aes128Gcm,
580 DataEncryptionAlgorithm::Aes192Gcm,
581 DataEncryptionAlgorithm::Aes256Gcm,
582 ]
583 .into_iter()
584 .any(|known| known.as_uri() == algorithm)
585}
586
587fn is_deprecated_data_encryption_algorithm(algorithm: &str) -> bool {
588 DataEncryptionAlgorithm::TripleDesCbc.as_uri() == algorithm
589}
590
591#[derive(Debug, Clone, Copy, PartialEq, Eq)]
592pub enum DigestAlgorithm {
593 Sha1,
594 Sha256,
595 Sha384,
596 Sha512,
597}
598
599impl DigestAlgorithm {
600 pub fn as_uri(self) -> &'static str {
601 match self {
602 Self::Sha1 => "http://www.w3.org/2000/09/xmldsig#sha1",
603 Self::Sha256 => "http://www.w3.org/2001/04/xmlenc#sha256",
604 Self::Sha384 => "http://www.w3.org/2001/04/xmldsig-more#sha384",
605 Self::Sha512 => "http://www.w3.org/2001/04/xmlenc#sha512",
606 }
607 }
608}
609
610#[derive(Debug, Clone, Copy, PartialEq, Eq)]
611pub enum KeyEncryptionAlgorithm {
612 Rsa15,
613 RsaOaep,
614 RsaOaepSha256,
615}
616
617impl KeyEncryptionAlgorithm {
618 pub fn as_uri(self) -> &'static str {
619 match self {
620 Self::Rsa15 => "http://www.w3.org/2001/04/xmlenc#rsa-1_5",
621 Self::RsaOaep => "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p",
622 Self::RsaOaepSha256 => "http://www.w3.org/2009/xmlenc11#rsa-oaep",
623 }
624 }
625}
626
627#[derive(Debug, Clone, Copy, PartialEq, Eq)]
628pub enum DataEncryptionAlgorithm {
629 TripleDesCbc,
630 Aes128Cbc,
631 Aes192Cbc,
632 Aes256Cbc,
633 Aes128Gcm,
634 Aes192Gcm,
635 Aes256Gcm,
636}
637
638impl DataEncryptionAlgorithm {
639 pub fn as_uri(self) -> &'static str {
640 match self {
641 Self::TripleDesCbc => "http://www.w3.org/2001/04/xmlenc#tripledes-cbc",
642 Self::Aes128Cbc => "http://www.w3.org/2001/04/xmlenc#aes128-cbc",
643 Self::Aes192Cbc => "http://www.w3.org/2001/04/xmlenc#aes192-cbc",
644 Self::Aes256Cbc => "http://www.w3.org/2001/04/xmlenc#aes256-cbc",
645 Self::Aes128Gcm => "http://www.w3.org/2009/xmlenc11#aes128-gcm",
646 Self::Aes192Gcm => "http://www.w3.org/2009/xmlenc11#aes192-gcm",
647 Self::Aes256Gcm => "http://www.w3.org/2009/xmlenc11#aes256-gcm",
648 }
649 }
650}