Skip to main content

saml_rs/config/
algorithms.rs

1use crate::constants::{
2    data_encryption_algorithm, digest_algorithm, key_encryption_algorithm, name_id_format,
3    signature_algorithm, transform_algorithm,
4};
5
6/// XML signature algorithm used for outgoing signed messages.
7///
8/// Custom URI values are forwarded to the configured crypto backend and can
9/// still fail at runtime when unsupported by that backend.
10#[derive(Debug, Clone, Default, PartialEq, Eq)]
11pub enum SignatureAlgorithm {
12    /// RSA with SHA-256.
13    #[default]
14    RsaSha256,
15    /// RSA with SHA-384.
16    RsaSha384,
17    /// RSA with SHA-512.
18    RsaSha512,
19    /// Backend-specific signature algorithm URI.
20    Custom(String),
21}
22
23impl SignatureAlgorithm {
24    /// Return the XML-DSig algorithm URI.
25    pub fn as_uri(&self) -> &str {
26        match self {
27            Self::RsaSha256 => signature_algorithm::RSA_SHA256,
28            Self::RsaSha384 => signature_algorithm::RSA_SHA384,
29            Self::RsaSha512 => signature_algorithm::RSA_SHA512,
30            Self::Custom(uri) => uri.as_str(),
31        }
32    }
33}
34
35/// XML digest algorithm URI used by XML-DSig profiles.
36///
37/// Custom URI values are forwarded to the configured crypto backend and can
38/// still fail at runtime when unsupported by that backend.
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub enum DigestAlgorithm {
41    /// SHA-1 digest for legacy interoperability.
42    Sha1ForCompatibility,
43    /// Deprecated alias for [`Self::Sha1ForCompatibility`].
44    #[deprecated(note = "use DigestAlgorithm::Sha1ForCompatibility")]
45    Sha1,
46    /// SHA-256 digest.
47    Sha256,
48    /// SHA-384 digest.
49    Sha384,
50    /// SHA-512 digest.
51    Sha512,
52    /// Backend-specific digest algorithm URI.
53    Custom(String),
54}
55
56impl DigestAlgorithm {
57    /// Return the XML digest algorithm URI.
58    #[expect(
59        deprecated,
60        reason = "deprecated algorithm aliases remain mapped for compatibility"
61    )]
62    pub fn as_uri(&self) -> &str {
63        match self {
64            Self::Sha1ForCompatibility | Self::Sha1 => digest_algorithm::SHA1,
65            Self::Sha256 => digest_algorithm::SHA256,
66            Self::Sha384 => digest_algorithm::SHA384,
67            Self::Sha512 => digest_algorithm::SHA512,
68            Self::Custom(uri) => uri.as_str(),
69        }
70    }
71}
72
73/// XML-Enc content encryption algorithm.
74///
75/// Custom URI values are forwarded to the configured crypto backend and can
76/// still fail at runtime when unsupported by that backend.
77#[derive(Debug, Clone, Default, PartialEq, Eq)]
78pub enum DataEncryptionAlgorithm {
79    /// AES-128-CBC.
80    Aes128,
81    /// AES-256-CBC.
82    #[default]
83    Aes256,
84    /// Triple DES CBC for legacy interoperability.
85    TripleDesForCompatibility,
86    /// Deprecated alias for [`Self::TripleDesForCompatibility`].
87    #[deprecated(note = "use DataEncryptionAlgorithm::TripleDesForCompatibility")]
88    TripleDes,
89    /// AES-128-GCM.
90    Aes128Gcm,
91    /// Backend-specific content encryption algorithm URI.
92    Custom(String),
93}
94
95impl DataEncryptionAlgorithm {
96    /// Return the XML-Enc algorithm URI.
97    #[expect(
98        deprecated,
99        reason = "deprecated algorithm aliases remain mapped for compatibility"
100    )]
101    pub fn as_uri(&self) -> &str {
102        match self {
103            Self::Aes128 => data_encryption_algorithm::AES_128,
104            Self::Aes256 => data_encryption_algorithm::AES_256,
105            Self::TripleDesForCompatibility | Self::TripleDes => {
106                data_encryption_algorithm::TRIPLE_DES
107            }
108            Self::Aes128Gcm => data_encryption_algorithm::AES_128_GCM,
109            Self::Custom(uri) => uri.as_str(),
110        }
111    }
112}
113
114/// XML-Enc key transport algorithm.
115///
116/// Custom URI values are forwarded to the configured crypto backend and can
117/// still fail at runtime when unsupported by that backend.
118#[derive(Debug, Clone, Default, PartialEq, Eq)]
119pub enum KeyEncryptionAlgorithm {
120    /// RSA-OAEP-MGF1P.
121    #[default]
122    RsaOaepMgf1p,
123    /// RSAES-PKCS1-v1_5 for legacy interoperability.
124    Rsa15ForCompatibility,
125    /// Deprecated alias for [`Self::Rsa15ForCompatibility`].
126    #[deprecated(note = "use KeyEncryptionAlgorithm::Rsa15ForCompatibility")]
127    Rsa15,
128    /// Backend-specific key transport algorithm URI.
129    Custom(String),
130}
131
132impl KeyEncryptionAlgorithm {
133    /// Return the XML-Enc key transport algorithm URI.
134    #[expect(
135        deprecated,
136        reason = "deprecated algorithm aliases remain mapped for compatibility"
137    )]
138    pub fn as_uri(&self) -> &str {
139        match self {
140            Self::RsaOaepMgf1p => key_encryption_algorithm::RSA_OAEP_MGF1P,
141            Self::Rsa15ForCompatibility | Self::Rsa15 => key_encryption_algorithm::RSA_1_5,
142            Self::Custom(uri) => uri.as_str(),
143        }
144    }
145}
146
147/// XML-DSig transform or canonicalization algorithm.
148///
149/// Custom URI values are forwarded to the configured crypto backend and can
150/// still fail at runtime when unsupported by that backend.
151#[derive(Debug, Clone, PartialEq, Eq)]
152pub enum TransformAlgorithm {
153    /// Enveloped-signature transform.
154    EnvelopedSignature,
155    /// Exclusive XML canonicalization.
156    ExclusiveCanonicalization,
157    /// Backend-specific transform algorithm URI.
158    Custom(String),
159}
160
161impl TransformAlgorithm {
162    /// Return the XML-DSig transform URI.
163    pub fn as_uri(&self) -> &str {
164        match self {
165            Self::EnvelopedSignature => transform_algorithm::ENVELOPED_SIGNATURE,
166            Self::ExclusiveCanonicalization => transform_algorithm::EXC_C14N,
167            Self::Custom(uri) => uri.as_str(),
168        }
169    }
170}
171
172/// SAML NameID format URI.
173#[derive(Debug, Clone, PartialEq, Eq)]
174pub enum NameIdFormat {
175    /// Email address format.
176    EmailAddress,
177    /// Persistent identifier format.
178    Persistent,
179    /// Transient identifier format.
180    Transient,
181    /// Entity identifier format.
182    Entity,
183    /// Unspecified format.
184    Unspecified,
185    /// Kerberos principal name format.
186    Kerberos,
187    /// Windows domain qualified name format.
188    WindowsDomainQualifiedName,
189    /// X.509 subject name format.
190    X509SubjectName,
191    /// Deployment-specific NameID format URI.
192    Custom(String),
193}
194
195impl NameIdFormat {
196    /// Return the SAML NameID format URI.
197    pub fn as_uri(&self) -> &str {
198        match self {
199            Self::EmailAddress => name_id_format::EMAIL_ADDRESS,
200            Self::Persistent => name_id_format::PERSISTENT,
201            Self::Transient => name_id_format::TRANSIENT,
202            Self::Entity => name_id_format::ENTITY,
203            Self::Unspecified => name_id_format::UNSPECIFIED,
204            Self::Kerberos => name_id_format::KERBEROS,
205            Self::WindowsDomainQualifiedName => name_id_format::WINDOWS_DOMAIN_QUALIFIED_NAME,
206            Self::X509SubjectName => name_id_format::X509_SUBJECT_NAME,
207            Self::Custom(uri) => uri.as_str(),
208        }
209    }
210}
211
212pub(super) fn name_id_format_uris(formats: &[NameIdFormat]) -> Vec<String> {
213    formats
214        .iter()
215        .map(|format| format.as_uri().to_string())
216        .collect()
217}
218
219pub(super) fn transform_algorithm_uris(algorithms: &[TransformAlgorithm]) -> Vec<String> {
220    algorithms
221        .iter()
222        .map(|algorithm| algorithm.as_uri().to_string())
223        .collect()
224}