Skip to main content

picky_asn1_x509/
algorithm_identifier.rs

1use crate::oids;
2use oid::ObjectIdentifier;
3use picky_asn1::tag::{Tag, TagPeeker};
4use picky_asn1::wrapper::{
5    ExplicitContextTag0, ExplicitContextTag1, ExplicitContextTag2, IntegerAsn1, ObjectIdentifierAsn1, OctetStringAsn1,
6};
7use picky_asn1_der::Asn1RawDer;
8use serde::{Deserialize, Serialize, de, ser};
9use std::cmp::Ordering;
10use std::error::Error;
11use std::fmt;
12
13/// unsupported algorithm
14#[derive(Debug)]
15pub struct UnsupportedAlgorithmError {
16    pub algorithm: String,
17}
18
19impl fmt::Display for UnsupportedAlgorithmError {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        write!(f, "unsupported algorithm:  {}", self.algorithm)
22    }
23}
24
25impl Error for UnsupportedAlgorithmError {}
26
27#[derive(Debug, PartialEq, Eq, Clone)]
28pub struct AlgorithmIdentifier {
29    algorithm: ObjectIdentifierAsn1,
30    parameters: AlgorithmIdentifierParameters,
31}
32
33impl AlgorithmIdentifier {
34    pub fn oid(&self) -> &ObjectIdentifier {
35        &self.algorithm.0
36    }
37
38    pub fn oid_asn1(&self) -> &ObjectIdentifierAsn1 {
39        &self.algorithm
40    }
41
42    pub fn parameters(&self) -> &AlgorithmIdentifierParameters {
43        &self.parameters
44    }
45
46    pub fn is_a(&self, algorithm: ObjectIdentifier) -> bool {
47        algorithm.eq(&self.algorithm.0)
48    }
49
50    pub fn is_one_of(&self, algorithms: impl IntoIterator<Item = ObjectIdentifier>) -> bool {
51        algorithms.into_iter().any(|oid| self.is_a(oid))
52    }
53
54    pub fn new_md5_with_rsa_encryption() -> Self {
55        Self {
56            algorithm: oids::md5_with_rsa_encryption().into(),
57            parameters: AlgorithmIdentifierParameters::Null,
58        }
59    }
60
61    pub fn new_sha1_with_rsa_encryption() -> Self {
62        Self {
63            algorithm: oids::sha1_with_rsa_encryption().into(),
64            parameters: AlgorithmIdentifierParameters::Null,
65        }
66    }
67
68    pub fn new_sha1() -> Self {
69        Self {
70            algorithm: oids::sha1().into(),
71            parameters: AlgorithmIdentifierParameters::Null,
72        }
73    }
74
75    pub fn new_sha224_with_rsa_encryption() -> Self {
76        Self {
77            algorithm: oids::sha224_with_rsa_encryption().into(),
78            parameters: AlgorithmIdentifierParameters::Null,
79        }
80    }
81
82    pub fn new_sha256_with_rsa_encryption() -> Self {
83        Self {
84            algorithm: oids::sha256_with_rsa_encryption().into(),
85            parameters: AlgorithmIdentifierParameters::Null,
86        }
87    }
88
89    pub fn new_sha384_with_rsa_encryption() -> Self {
90        Self {
91            algorithm: oids::sha384_with_rsa_encryption().into(),
92            parameters: AlgorithmIdentifierParameters::Null,
93        }
94    }
95
96    pub fn new_sha512_with_rsa_encryption() -> Self {
97        Self {
98            algorithm: oids::sha512_with_rsa_encryption().into(),
99            parameters: AlgorithmIdentifierParameters::Null,
100        }
101    }
102
103    pub fn new_sha3_224_with_rsa_encryption() -> Self {
104        Self {
105            algorithm: oids::id_rsassa_pkcs1_v1_5_with_sha3_224().into(),
106            parameters: AlgorithmIdentifierParameters::Null,
107        }
108    }
109
110    pub fn new_sha3_256_with_rsa_encryption() -> Self {
111        Self {
112            algorithm: oids::id_rsassa_pkcs1_v1_5_with_sha3_256().into(),
113            parameters: AlgorithmIdentifierParameters::Null,
114        }
115    }
116
117    pub fn new_sha3_384_with_rsa_encryption() -> Self {
118        Self {
119            algorithm: oids::id_rsassa_pkcs1_v1_5_with_sha3_384().into(),
120            parameters: AlgorithmIdentifierParameters::Null,
121        }
122    }
123
124    pub fn new_sha3_512_with_rsa_encryption() -> Self {
125        Self {
126            algorithm: oids::id_rsassa_pkcs1_v1_5_with_sha3_512().into(),
127            parameters: AlgorithmIdentifierParameters::Null,
128        }
129    }
130
131    pub fn new_rsassa_pss(parameters: RsassaPssParams) -> Self {
132        Self {
133            algorithm: oids::rsassa_pss().into(),
134            parameters: AlgorithmIdentifierParameters::RsassaPss(parameters),
135        }
136    }
137
138    pub fn new_rsa_encryption() -> Self {
139        Self {
140            algorithm: oids::rsa_encryption().into(),
141            parameters: AlgorithmIdentifierParameters::Null,
142        }
143    }
144
145    pub fn new_rsa_encryption_with_sha(variant: ShaVariant) -> Result<Self, UnsupportedAlgorithmError> {
146        let algorithm = match variant {
147            ShaVariant::SHA2_224 => oids::sha224_with_rsa_encryption(),
148            ShaVariant::SHA2_256 => oids::sha256_with_rsa_encryption(),
149            ShaVariant::SHA2_384 => oids::sha384_with_rsa_encryption(),
150            ShaVariant::SHA2_512 => oids::sha512_with_rsa_encryption(),
151            ShaVariant::SHA3_384 => oids::id_rsassa_pkcs1_v1_5_with_sha3_384(),
152            ShaVariant::SHA3_512 => oids::id_rsassa_pkcs1_v1_5_with_sha3_512(),
153            _ => {
154                return Err(UnsupportedAlgorithmError {
155                    algorithm: format!("{variant:?}"),
156                });
157            }
158        };
159
160        Ok(Self {
161            algorithm: algorithm.into(),
162            parameters: AlgorithmIdentifierParameters::Null,
163        })
164    }
165
166    pub fn new_dsa_with_sha1() -> Self {
167        Self {
168            algorithm: oids::dsa_with_sha1().into(),
169            parameters: AlgorithmIdentifierParameters::Null,
170        }
171    }
172
173    pub fn new_ecdsa_with_sha512() -> Self {
174        Self {
175            algorithm: oids::ecdsa_with_sha512().into(),
176            parameters: AlgorithmIdentifierParameters::None,
177        }
178    }
179
180    pub fn new_ecdsa_with_sha384() -> Self {
181        Self {
182            algorithm: oids::ecdsa_with_sha384().into(),
183            parameters: AlgorithmIdentifierParameters::None,
184        }
185    }
186
187    pub fn new_ecdsa_with_sha256() -> Self {
188        Self {
189            algorithm: oids::ecdsa_with_sha256().into(),
190            parameters: AlgorithmIdentifierParameters::None,
191        }
192    }
193
194    pub fn new_elliptic_curve(ec_params: EcParameters) -> Self {
195        Self {
196            algorithm: oids::ec_public_key().into(),
197            parameters: AlgorithmIdentifierParameters::Ec(ec_params),
198        }
199    }
200
201    /// Create new algorithm identifier without checking if the algorithm parameters are valid for
202    /// the given algorithm.
203    pub(crate) fn new_unchecked(algorithm: ObjectIdentifier, parameters: AlgorithmIdentifierParameters) -> Self {
204        Self {
205            algorithm: algorithm.into(),
206            parameters,
207        }
208    }
209
210    pub fn new_ed25519() -> Self {
211        Self {
212            algorithm: oids::ed25519().into(),
213            parameters: AlgorithmIdentifierParameters::None,
214        }
215    }
216
217    pub fn new_x25519() -> Self {
218        Self {
219            algorithm: oids::x25519().into(),
220            parameters: AlgorithmIdentifierParameters::None,
221        }
222    }
223
224    pub fn new_ed448() -> Self {
225        Self {
226            algorithm: oids::ed448().into(),
227            parameters: AlgorithmIdentifierParameters::None,
228        }
229    }
230
231    pub fn new_x448() -> Self {
232        Self {
233            algorithm: oids::x448().into(),
234            parameters: AlgorithmIdentifierParameters::None,
235        }
236    }
237
238    pub fn new_aes128(mode: AesMode, params: AesParameters) -> Self {
239        Self {
240            algorithm: mode.to_128bit_oid(),
241            parameters: AlgorithmIdentifierParameters::Aes(params),
242        }
243    }
244
245    pub fn new_aes192(mode: AesMode, params: AesParameters) -> Self {
246        Self {
247            algorithm: mode.to_192bit_oid(),
248            parameters: AlgorithmIdentifierParameters::Aes(params),
249        }
250    }
251
252    pub fn new_aes256(mode: AesMode, params: AesParameters) -> Self {
253        Self {
254            algorithm: mode.to_256bit_oid(),
255            parameters: AlgorithmIdentifierParameters::Aes(params),
256        }
257    }
258
259    pub fn new_aes256_empty(mode: AesMode) -> Self {
260        Self {
261            algorithm: mode.to_256bit_oid(),
262            parameters: AlgorithmIdentifierParameters::None,
263        }
264    }
265
266    pub fn new_sha(variant: ShaVariant) -> Self {
267        Self {
268            algorithm: variant.into(),
269            parameters: AlgorithmIdentifierParameters::Null,
270        }
271    }
272
273    pub fn new_ecdsa_with_sha3_224() -> Self {
274        Self {
275            algorithm: oids::id_ecdsa_with_sha3_224().into(),
276            parameters: AlgorithmIdentifierParameters::None,
277        }
278    }
279
280    pub fn new_ecdsa_with_sha3_256() -> Self {
281        Self {
282            algorithm: oids::id_ecdsa_with_sha3_256().into(),
283            parameters: AlgorithmIdentifierParameters::None,
284        }
285    }
286
287    pub fn new_ecdsa_with_sha3_384() -> Self {
288        Self {
289            algorithm: oids::id_ecdsa_with_sha3_384().into(),
290            parameters: AlgorithmIdentifierParameters::None,
291        }
292    }
293
294    pub fn new_ecdsa_with_sha3_512() -> Self {
295        Self {
296            algorithm: oids::id_ecdsa_with_sha3_512().into(),
297            parameters: AlgorithmIdentifierParameters::None,
298        }
299    }
300
301    pub fn new_mldsa_44() -> Self {
302        Self {
303            algorithm: oids::id_mldsa_44().into(),
304            parameters: AlgorithmIdentifierParameters::None,
305        }
306    }
307
308    pub fn new_mldsa_65() -> Self {
309        Self {
310            algorithm: oids::id_mldsa_65().into(),
311            parameters: AlgorithmIdentifierParameters::None,
312        }
313    }
314
315    pub fn new_mldsa_87() -> Self {
316        Self {
317            algorithm: oids::id_mldsa_87().into(),
318            parameters: AlgorithmIdentifierParameters::None,
319        }
320    }
321}
322
323impl ser::Serialize for AlgorithmIdentifier {
324    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
325    where
326        S: ser::Serializer,
327    {
328        use ser::SerializeSeq;
329        let mut seq = serializer.serialize_seq(Some(2))?;
330        seq.serialize_element(&self.algorithm)?;
331        match &self.parameters {
332            AlgorithmIdentifierParameters::None => {}
333            AlgorithmIdentifierParameters::Null => {
334                seq.serialize_element(&())?;
335            }
336            AlgorithmIdentifierParameters::Ec(ec_params) => {
337                seq.serialize_element(ec_params)?;
338            }
339            AlgorithmIdentifierParameters::Aes(aes_params) => {
340                seq.serialize_element(aes_params)?;
341            }
342            AlgorithmIdentifierParameters::RsassaPss(rsa_params) => {
343                seq.serialize_element(rsa_params)?;
344            }
345        }
346        seq.end()
347    }
348}
349
350impl<'de> de::Deserialize<'de> for AlgorithmIdentifier {
351    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
352    where
353        D: de::Deserializer<'de>,
354    {
355        struct Visitor;
356
357        impl<'de> de::Visitor<'de> for Visitor {
358            type Value = AlgorithmIdentifier;
359
360            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
361                formatter.write_str("a valid DER-encoded algorithm identifier")
362            }
363
364            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
365            where
366                A: de::SeqAccess<'de>,
367            {
368                let oid: ObjectIdentifierAsn1 = seq_next_element!(seq, AlgorithmIdentifier, "algorithm oid");
369
370                let args = match Into::<String>::into(&oid.0).as_str() {
371                    oids::RSA_ENCRYPTION
372                    | oids::SHA1_WITH_RSA_ENCRYPTION
373                    | oids::SHA224_WITH_RSA_ENCRYPTION
374                    | oids::SHA256_WITH_RSA_ENCRYPTION
375                    | oids::SHA384_WITH_RSA_ENCRYPTION
376                    | oids::SHA512_WITH_RSA_ENCRYPTION
377                    | oids::ID_RSASSA_PKCS1_V1_5_WITH_SHA3_224
378                    | oids::ID_RSASSA_PKCS1_V1_5_WITH_SHA3_256
379                    | oids::ID_RSASSA_PKCS1_V1_5_WITH_SHA3_384
380                    | oids::ID_RSASSA_PKCS1_V1_5_WITH_SHA3_512 => {
381                        // Try to deserialize next element in sequence.
382                        // Error is ignored because some implementations just leave no parameter at all for
383                        // RSA encryption (ie: rsa-export-0.1.1 crate) but we still want to be able
384                        // to parse their output.
385                        let _ = seq.next_element::<()>();
386                        AlgorithmIdentifierParameters::Null
387                    }
388                    oids::RSASSA_PSS => AlgorithmIdentifierParameters::RsassaPss(seq_next_element!(
389                        seq,
390                        RsassaPssParams,
391                        "RSASSA-PSS parameters"
392                    )),
393                    oids::ECDSA_WITH_SHA384
394                    | oids::ECDSA_WITH_SHA256
395                    | oids::ECDSA_WITH_SHA512
396                    | oids::ID_ECDSA_WITH_SHA3_224
397                    | oids::ID_ECDSA_WITH_SHA3_256
398                    | oids::ID_ECDSA_WITH_SHA3_384
399                    | oids::ID_ECDSA_WITH_SHA3_512
400                    | oids::ED25519
401                    | oids::ED448
402                    | oids::X25519
403                    | oids::X448
404                    | oids::ID_MLDSA_44
405                    | oids::ID_MLDSA_65
406                    | oids::ID_MLDSA_87 => AlgorithmIdentifierParameters::None,
407                    oids::DSA_WITH_SHA1 => {
408                        // A note from [RFC 3927](https://www.ietf.org/rfc/rfc3279.txt)
409                        // When the id-dsa-with-sha1 algorithm identifier appears as the
410                        // algorithm field in an AlgorithmIdentifier, the encoding SHALL omit
411                        // the parameters field.  That is, the AlgorithmIdentifier SHALL be a
412                        // SEQUENCE of one component: the OBJECT IDENTIFIER id-dsa-with-sha1.
413                        AlgorithmIdentifierParameters::None
414                    }
415                    // A note from [RFC 5480](https://tools.ietf.org/html/rfc5480#section-2.1.1)
416                    // The parameter for id-ecPublicKey is as follows and MUST always be present
417                    oids::EC_PUBLIC_KEY => AlgorithmIdentifierParameters::Ec(seq_next_element!(
418                        seq,
419                        EcParameters,
420                        AlgorithmIdentifier,
421                        "elliptic curves parameters"
422                    )),
423                    // AES
424                    x if x.starts_with("2.16.840.1.101.3.4.1.") => {
425                        if let Some(aes_parameters) = seq.next_element()? {
426                            AlgorithmIdentifierParameters::Aes(aes_parameters)
427                        } else {
428                            AlgorithmIdentifierParameters::None
429                        }
430                    }
431                    // SHA
432                    x if x.starts_with("2.16.840.1.101.3.4.2.") || x == oids::SHA1 => {
433                        type Unit = ();
434                        seq_next_element!(seq, Unit, AlgorithmIdentifier, "sha algorithm identifier");
435                        AlgorithmIdentifierParameters::Null
436                    }
437                    _ => {
438                        return Err(serde_invalid_value!(
439                            AlgorithmIdentifier,
440                            "unsupported algorithm (unknown oid)",
441                            "a supported algorithm"
442                        ));
443                    }
444                };
445
446                Ok(AlgorithmIdentifier {
447                    algorithm: oid,
448                    parameters: args,
449                })
450            }
451        }
452
453        deserializer.deserialize_seq(Visitor)
454    }
455}
456
457#[derive(Debug, PartialEq, Eq, Clone)]
458pub enum AlgorithmIdentifierParameters {
459    None,
460    Null,
461    Aes(AesParameters),
462    Ec(EcParameters),
463    RsassaPss(RsassaPssParams),
464}
465
466/// [RFC 4055 #3.1](https://www.rfc-editor.org/rfc/rfc4055#section-3.1)
467///
468/// ```not_rust
469///       RSASSA-PSS-params  ::=  SEQUENCE  {
470///           hashAlgorithm      [0] HashAlgorithm DEFAULT
471///                                     sha1Identifier,
472///           maskGenAlgorithm   [1] MaskGenAlgorithm DEFAULT
473///                                     mgf1SHA1Identifier,
474///           saltLength         [2] INTEGER DEFAULT 20,
475///           trailerField       [3] INTEGER DEFAULT 1  }
476/// ```
477///
478/// Implementations that perform signature generation MUST omit the trailerField
479/// field, indicating that the default trailer field value was used... thus the
480/// reason no trailer field is specified in this structure.
481#[derive(Clone, Debug, Eq, PartialEq)]
482pub struct RsassaPssParams {
483    pub hash_algorithm: HashAlgorithm,
484    pub mask_gen_algorithm: MaskGenAlgorithm,
485    pub salt_length: usize,
486}
487
488impl RsassaPssParams {
489    pub fn new(hash_algorithm: HashAlgorithm) -> Self {
490        Self {
491            hash_algorithm,
492            mask_gen_algorithm: MaskGenAlgorithm::new(hash_algorithm),
493            salt_length: hash_algorithm.len(),
494        }
495    }
496}
497
498impl ser::Serialize for RsassaPssParams {
499    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
500    where
501        S: ser::Serializer,
502    {
503        use ser::SerializeSeq;
504        let mut seq = serializer.serialize_seq(Some(3))?;
505        seq.serialize_element(&ExplicitContextTag0(&self.hash_algorithm))?;
506        seq.serialize_element(&ExplicitContextTag1(&self.mask_gen_algorithm))?;
507        seq.serialize_element(&ExplicitContextTag2(&IntegerAsn1::from_bytes_be_signed(
508            self.salt_length.to_be_bytes().to_vec(),
509        )))?;
510        seq.end()
511    }
512}
513
514fn usize_from_be_bytes(asn1: &IntegerAsn1) -> usize {
515    let bytes = asn1.as_unsigned_bytes_be();
516    match bytes.len().cmp(&8) {
517        Ordering::Greater => usize::MAX,
518        Ordering::Less => {
519            const USIZE_SIZE: usize = std::mem::size_of::<usize>();
520
521            let mut tmp = [0; USIZE_SIZE];
522            tmp[(USIZE_SIZE - bytes.len())..USIZE_SIZE].clone_from_slice(bytes);
523            usize::from_be_bytes(tmp)
524        }
525        // unwrap is safe since we know this is exactly 8 bytes.
526        Ordering::Equal => usize::from_be_bytes(bytes.try_into().unwrap()),
527    }
528}
529
530impl<'de> de::Deserialize<'de> for RsassaPssParams {
531    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
532    where
533        D: de::Deserializer<'de>,
534    {
535        struct Visitor;
536
537        impl<'de> de::Visitor<'de> for Visitor {
538            type Value = RsassaPssParams;
539
540            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
541                formatter.write_str("a valid DER-encoded RsassaPssParams")
542            }
543
544            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
545            where
546                A: de::SeqAccess<'de>,
547            {
548                let hash = seq_next_element!(seq, ExplicitContextTag0<HashAlgorithm>, HashAlgorithm, "cont [0]");
549                let mask_gen = seq_next_element!(
550                    seq,
551                    ExplicitContextTag1<MaskGenAlgorithm>,
552                    MaskGenAlgorithm,
553                    "maskGenAlgorithm"
554                );
555                let salt = seq_next_element!(seq, ExplicitContextTag2<IntegerAsn1>, IntegerAsn1, "saltLength");
556                Ok(RsassaPssParams {
557                    hash_algorithm: hash.0,
558                    mask_gen_algorithm: mask_gen.0,
559                    salt_length: usize_from_be_bytes(&salt.0),
560                })
561            }
562        }
563
564        deserializer.deserialize_seq(Visitor)
565    }
566}
567
568// https://www.rfc-editor.org/rfc/rfc4055#section-2.1
569#[derive(Clone, Copy, PartialEq, Eq, Debug)]
570#[allow(non_camel_case_types)]
571pub enum HashAlgorithm {
572    // Nobody should be using SHA1 in 2023, it is completely broken... and the RFC for RsassaPssParams
573    // adds needless complexity in regard to requiring the omission of parameters if SHA1 is used.
574    //SHA1,
575    SHA224,
576    SHA256,
577    SHA384,
578    SHA512,
579
580    SHA3_224,
581    SHA3_256,
582    SHA3_384,
583    SHA3_512,
584}
585
586impl HashAlgorithm {
587    pub fn len(&self) -> usize {
588        use HashAlgorithm::*;
589        match self {
590            SHA224 => 28,
591            SHA256 => 32,
592            SHA384 => 48,
593            SHA512 => 64,
594            SHA3_224 => 28,
595            SHA3_256 => 32,
596            SHA3_384 => 48,
597            SHA3_512 => 64,
598        }
599    }
600    pub fn is_empty(&self) -> bool {
601        false
602    }
603}
604impl From<&HashAlgorithm> for ObjectIdentifierAsn1 {
605    fn from(variant: &HashAlgorithm) -> Self {
606        use HashAlgorithm::*;
607        match variant {
608            //SHA1 => oids::sha1().into(),
609            SHA224 => oids::sha224().into(),
610            SHA256 => oids::sha256().into(),
611            SHA384 => oids::sha384().into(),
612            SHA512 => oids::sha512().into(),
613            SHA3_224 => oids::sha3_224().into(),
614            SHA3_256 => oids::sha3_256().into(),
615            SHA3_384 => oids::sha384().into(),
616            SHA3_512 => oids::sha512().into(),
617        }
618    }
619}
620
621impl TryFrom<ObjectIdentifierAsn1> for HashAlgorithm {
622    type Error = UnsupportedAlgorithmError;
623
624    fn try_from(oid: ObjectIdentifierAsn1) -> Result<Self, Self::Error> {
625        match Into::<String>::into(oid.0).as_str() {
626            //oids::SHA1 => Ok(HashAlgorithm::SHA1),
627            oids::SHA224 => Ok(HashAlgorithm::SHA224),
628            oids::SHA256 => Ok(HashAlgorithm::SHA256),
629            oids::SHA384 => Ok(HashAlgorithm::SHA384),
630            oids::SHA512 => Ok(HashAlgorithm::SHA512),
631            oids::SHA3_224 => Ok(HashAlgorithm::SHA3_224),
632            oids::SHA3_256 => Ok(HashAlgorithm::SHA3_256),
633            oids::SHA3_384 => Ok(HashAlgorithm::SHA3_384),
634            oids::SHA3_512 => Ok(HashAlgorithm::SHA3_512),
635            unsupported => Err(UnsupportedAlgorithmError {
636                algorithm: unsupported.to_string(),
637            }),
638        }
639    }
640}
641
642impl ser::Serialize for HashAlgorithm {
643    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
644    where
645        S: ser::Serializer,
646    {
647        use ser::SerializeSeq;
648        let mut seq = serializer.serialize_seq(Some(2))?;
649        seq.serialize_element(&ObjectIdentifierAsn1::from(self))?;
650        seq.serialize_element(&())?;
651        seq.end()
652    }
653}
654
655impl<'de> de::Deserialize<'de> for HashAlgorithm {
656    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
657    where
658        D: de::Deserializer<'de>,
659    {
660        struct Visitor;
661
662        impl<'de> de::Visitor<'de> for Visitor {
663            type Value = HashAlgorithm;
664
665            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
666                formatter.write_str("a valid DER-encoded HashAlgorithm")
667            }
668
669            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
670            where
671                A: de::SeqAccess<'de>,
672            {
673                let oid: ObjectIdentifierAsn1 = seq_next_element!(seq, ObjectIdentifierAsn1, "oid of hashAlgorithm");
674                let _: Option<()> = seq.next_element()?;
675                oid.try_into().map_err(|_| {
676                    serde_invalid_value!(
677                        HashAlgorithm,
678                        "unsupported or unknown hash algorithm",
679                        "a supported hash algorithm"
680                    )
681                })
682            }
683        }
684
685        deserializer.deserialize_seq(Visitor)
686    }
687}
688
689#[derive(Clone, Debug, Eq, PartialEq)]
690pub struct MaskGenAlgorithm {
691    pub mask_gen_algorithm: ObjectIdentifierAsn1,
692    pub hash_algorithm: HashAlgorithm,
693}
694
695impl MaskGenAlgorithm {
696    pub fn new(hash_algorithm: HashAlgorithm) -> Self {
697        Self {
698            mask_gen_algorithm: ObjectIdentifierAsn1::from(oids::id_mgf1()),
699            hash_algorithm,
700        }
701    }
702}
703
704impl ser::Serialize for MaskGenAlgorithm {
705    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
706    where
707        S: ser::Serializer,
708    {
709        use ser::SerializeSeq;
710        let mut seq = serializer.serialize_seq(Some(2))?;
711        seq.serialize_element(&self.mask_gen_algorithm)?;
712        seq.serialize_element(&self.hash_algorithm)?;
713        seq.end()
714    }
715}
716
717impl<'de> de::Deserialize<'de> for MaskGenAlgorithm {
718    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
719    where
720        D: de::Deserializer<'de>,
721    {
722        struct Visitor;
723
724        impl<'de> de::Visitor<'de> for Visitor {
725            type Value = MaskGenAlgorithm;
726
727            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
728                formatter.write_str("a valid DER-encoded MaskGenAlgorithm")
729            }
730
731            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
732            where
733                A: de::SeqAccess<'de>,
734            {
735                let mask_gen_algorithm: ObjectIdentifierAsn1 =
736                    seq_next_element!(seq, ObjectIdentifierAsn1, "oid of maskGenAlgorithm");
737                let hash_algorithm: HashAlgorithm = seq_next_element!(seq, HashAlgorithm, "hashAlgorithm");
738                Ok(MaskGenAlgorithm {
739                    mask_gen_algorithm,
740                    hash_algorithm,
741                })
742            }
743        }
744
745        deserializer.deserialize_seq(Visitor)
746    }
747}
748
749#[derive(Debug, PartialEq, Eq, Clone)]
750pub enum EcParameters {
751    NamedCurve(ObjectIdentifierAsn1),
752    // -- implicitCurve and specifiedCurve MUST NOT be used in PKIX.
753    // ImplicitCurve,
754    // SpecifiedCurve(SpecifiedECDomain)
755}
756
757impl EcParameters {
758    pub fn curve_oid(&self) -> &ObjectIdentifier {
759        match self {
760            EcParameters::NamedCurve(oid) => &oid.0,
761        }
762    }
763}
764
765impl From<ObjectIdentifierAsn1> for EcParameters {
766    fn from(oid: ObjectIdentifierAsn1) -> Self {
767        Self::NamedCurve(oid)
768    }
769}
770
771impl From<ObjectIdentifier> for EcParameters {
772    fn from(oid: ObjectIdentifier) -> Self {
773        Self::NamedCurve(oid.into())
774    }
775}
776
777impl ser::Serialize for EcParameters {
778    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
779    where
780        S: ser::Serializer,
781    {
782        match &self {
783            EcParameters::NamedCurve(oid) => oid.serialize(serializer),
784        }
785    }
786}
787
788impl<'de> de::Deserialize<'de> for EcParameters {
789    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
790    where
791        D: de::Deserializer<'de>,
792    {
793        struct Visitor;
794
795        impl<'de> de::Visitor<'de> for Visitor {
796            type Value = EcParameters;
797
798            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
799                formatter.write_str("a valid DER-encoded DirectoryString")
800            }
801
802            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
803            where
804                A: de::SeqAccess<'de>,
805            {
806                let tag_peeker: TagPeeker = seq_next_element!(seq, EcParameters, "choice tag");
807
808                let curve_oid = match tag_peeker.next_tag {
809                    Tag::OID => seq_next_element!(seq, ObjectIdentifierAsn1, "NamedCurve object identifier"),
810                    _ => {
811                        return Err(serde_invalid_value!(
812                            EcParameters,
813                            "unsupported or unknown elliptic curve parameter",
814                            "a supported elliptic curve parameter"
815                        ));
816                    }
817                };
818
819                Ok(EcParameters::NamedCurve(curve_oid))
820            }
821        }
822
823        deserializer.deserialize_enum("DirectoryString", &["NamedCurve", "ImplicitCurve"], Visitor)
824    }
825}
826
827#[derive(Clone, Copy, PartialEq, Eq, Debug)]
828pub enum AesMode {
829    Ecb,
830    Cbc,
831    Ofb,
832    Cfb,
833    Wrap,
834    Gcm,
835    Ccm,
836    WrapPad,
837}
838
839#[derive(Debug, PartialEq, Eq, Clone)]
840pub enum AesParameters {
841    Null,
842    InitializationVector(OctetStringAsn1),
843    AuthenticatedEncryptionParameters(AesAuthEncParams),
844}
845
846#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Clone)]
847pub struct AesAuthEncParams {
848    pub(crate) nonce: OctetStringAsn1,
849    pub(crate) icv_len: IntegerAsn1,
850}
851
852impl AesAuthEncParams {
853    pub fn new(nonce: Vec<u8>, icv_len: usize) -> Self {
854        Self {
855            nonce: OctetStringAsn1::from(nonce),
856            icv_len: IntegerAsn1::from(
857                icv_len
858                    .to_be_bytes()
859                    // Remove leading zeroes.
860                    .into_iter()
861                    .skip_while(|n| *n == 0)
862                    .collect::<Vec<_>>(),
863            ),
864        }
865    }
866
867    pub fn nonce(&self) -> &[u8] {
868        &self.nonce.0
869    }
870
871    pub fn icv_len(&self) -> &[u8] {
872        &self.icv_len.0
873    }
874}
875
876impl AesMode {
877    fn to_128bit_oid(self) -> ObjectIdentifierAsn1 {
878        match self {
879            AesMode::Ecb => oids::aes128_ecb().into(),
880            AesMode::Cbc => oids::aes128_cbc().into(),
881            AesMode::Ofb => oids::aes128_ofb().into(),
882            AesMode::Cfb => oids::aes128_cfb().into(),
883            AesMode::Wrap => oids::aes128_wrap().into(),
884            AesMode::Gcm => oids::aes128_gcm().into(),
885            AesMode::Ccm => oids::aes128_ccm().into(),
886            AesMode::WrapPad => oids::aes128_wrap_pad().into(),
887        }
888    }
889
890    fn to_192bit_oid(self) -> ObjectIdentifierAsn1 {
891        match self {
892            AesMode::Ecb => oids::aes192_ecb().into(),
893            AesMode::Cbc => oids::aes192_cbc().into(),
894            AesMode::Ofb => oids::aes192_ofb().into(),
895            AesMode::Cfb => oids::aes192_cfb().into(),
896            AesMode::Wrap => oids::aes192_wrap().into(),
897            AesMode::Gcm => oids::aes192_gcm().into(),
898            AesMode::Ccm => oids::aes192_ccm().into(),
899            AesMode::WrapPad => oids::aes192_wrap_pad().into(),
900        }
901    }
902
903    fn to_256bit_oid(self) -> ObjectIdentifierAsn1 {
904        match self {
905            AesMode::Ecb => oids::aes256_ecb().into(),
906            AesMode::Cbc => oids::aes256_cbc().into(),
907            AesMode::Ofb => oids::aes256_ofb().into(),
908            AesMode::Cfb => oids::aes256_cfb().into(),
909            AesMode::Wrap => oids::aes256_wrap().into(),
910            AesMode::Gcm => oids::aes256_gcm().into(),
911            AesMode::Ccm => oids::aes256_ccm().into(),
912            AesMode::WrapPad => oids::aes256_wrap_pad().into(),
913        }
914    }
915}
916
917impl ser::Serialize for AesParameters {
918    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
919    where
920        S: ser::Serializer,
921    {
922        match self {
923            AesParameters::Null => ().serialize(serializer),
924            AesParameters::InitializationVector(iv) => iv.serialize(serializer),
925            AesParameters::AuthenticatedEncryptionParameters(params) => params.serialize(serializer),
926        }
927    }
928}
929
930impl<'de> de::Deserialize<'de> for AesParameters {
931    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
932    where
933        D: de::Deserializer<'de>,
934    {
935        struct Visitor;
936
937        impl<'de> de::Visitor<'de> for Visitor {
938            type Value = AesParameters;
939
940            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
941                formatter.write_str("a valid DER-encoded DirectoryString")
942            }
943
944            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
945            where
946                A: de::SeqAccess<'de>,
947            {
948                let tag_peeker: TagPeeker = seq_next_element!(seq, AesParameters, "choice tag");
949                match tag_peeker.next_tag {
950                    Tag::OCTET_STRING => Ok(AesParameters::InitializationVector(seq_next_element!(
951                        seq,
952                        AesParameters,
953                        "Object Identifier"
954                    ))),
955                    Tag::NULL => {
956                        seq.next_element::<()>()?.expect("should not panic");
957                        Ok(AesParameters::Null)
958                    }
959                    Tag::SEQUENCE => Ok(AesParameters::AuthenticatedEncryptionParameters(seq_next_element!(
960                        seq,
961                        AesAuthEncParams,
962                        "AES Authenticated Encryption parameters"
963                    ))),
964                    _ => Err(serde_invalid_value!(
965                        AesParameters,
966                        "unsupported or unknown AES parameter",
967                        "a supported AES parameter"
968                    )),
969                }
970            }
971        }
972
973        deserializer.deserialize_enum(
974            "DirectoryString",
975            &["Null", "InitializationVector", "AuthenticatedEncryptionParameters"],
976            Visitor,
977        )
978    }
979}
980
981#[derive(Clone, Copy, PartialEq, Eq, Debug)]
982#[allow(non_camel_case_types)] // 'SHA2_512_224' is clearer than 'SHA2512224' or 'Sha2512224' imo
983pub enum ShaVariant {
984    // TODO: rename enum (breaking)
985    MD5,
986    SHA1,
987    SHA2_224,
988    SHA2_256,
989    SHA2_384,
990    SHA2_512,
991    SHA2_512_224,
992    SHA2_512_256,
993    SHA3_224,
994    SHA3_256,
995    SHA3_384,
996    SHA3_512,
997    SHAKE128,
998    SHAKE256,
999}
1000
1001impl From<ShaVariant> for ObjectIdentifierAsn1 {
1002    fn from(variant: ShaVariant) -> Self {
1003        match variant {
1004            ShaVariant::MD5 => oids::md5().into(),
1005            ShaVariant::SHA1 => oids::sha1().into(),
1006            ShaVariant::SHA2_224 => oids::sha224().into(),
1007            ShaVariant::SHA2_256 => oids::sha256().into(),
1008            ShaVariant::SHA2_384 => oids::sha384().into(),
1009            ShaVariant::SHA2_512 => oids::sha512().into(),
1010            ShaVariant::SHA2_512_224 => oids::sha512_224().into(),
1011            ShaVariant::SHA2_512_256 => oids::sha512_256().into(),
1012            ShaVariant::SHA3_224 => oids::sha3_224().into(),
1013            ShaVariant::SHA3_256 => oids::sha3_256().into(),
1014            ShaVariant::SHA3_384 => oids::sha3_384().into(),
1015            ShaVariant::SHA3_512 => oids::sha3_512().into(),
1016            ShaVariant::SHAKE128 => oids::shake128().into(),
1017            ShaVariant::SHAKE256 => oids::shake256().into(),
1018        }
1019    }
1020}
1021
1022impl TryFrom<ObjectIdentifierAsn1> for ShaVariant {
1023    type Error = UnsupportedAlgorithmError;
1024
1025    fn try_from(oid: ObjectIdentifierAsn1) -> Result<Self, Self::Error> {
1026        match Into::<String>::into(oid.0).as_str() {
1027            oids::MD5 => Ok(ShaVariant::MD5),
1028            oids::SHA1 => Ok(ShaVariant::SHA1),
1029            oids::SHA224 => Ok(ShaVariant::SHA2_224),
1030            oids::SHA256 => Ok(ShaVariant::SHA2_256),
1031            oids::SHA384 => Ok(ShaVariant::SHA2_384),
1032            oids::SHA512 => Ok(ShaVariant::SHA2_512),
1033            oids::SHA512_224 => Ok(ShaVariant::SHA2_512_224),
1034            oids::SHA512_256 => Ok(ShaVariant::SHA2_512_256),
1035            oids::SHA3_224 => Ok(ShaVariant::SHA3_224),
1036            oids::SHA3_256 => Ok(ShaVariant::SHA3_256),
1037            oids::SHA3_384 => Ok(ShaVariant::SHA3_384),
1038            oids::SHA3_512 => Ok(ShaVariant::SHA3_512),
1039            oids::SHAKE128 => Ok(ShaVariant::SHAKE128),
1040            oids::SHAKE256 => Ok(ShaVariant::SHAKE256),
1041            unsupported => Err(UnsupportedAlgorithmError {
1042                algorithm: unsupported.to_string(),
1043            }),
1044        }
1045    }
1046}
1047
1048/// [PKCS #1: RSA Cryptography Specifications Version
1049/// 2.2](https://tools.ietf.org/html/rfc8017.html#section-9.2)
1050///
1051/// # Section 9.2
1052///
1053/// The type DigestInfo has the syntax:
1054///
1055/// ```not_rust
1056///    DigestInfo ::= SEQUENCE {
1057///        digestAlgorithm AlgorithmIdentifier,
1058///        digest OCTET STRING
1059///    }
1060/// ```
1061#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
1062pub struct DigestInfo {
1063    pub oid: AlgorithmIdentifier,
1064    pub digest: OctetStringAsn1,
1065}
1066
1067/// Raw representation of `AlgorithmIdentifier` ASN.1 type to allow parsing unknown algorithms.
1068#[derive(Debug, Clone, PartialEq, Eq)]
1069pub struct RawAlgorithmIdentifier {
1070    algorithm: ObjectIdentifier,
1071    /// Parameters here are defined in X509 as follows:
1072    /// ```not_rust
1073    /// parameters ANY DEFINED BY algorithm OPTIONAL
1074    /// ```
1075    /// therefore we will parse it as raw DER and allow user to parse it later.
1076    parameters: Option<Asn1RawDer>,
1077}
1078
1079impl RawAlgorithmIdentifier {
1080    /// Create new `RawAlgorithmIdentifier` from algorithm OID and optional parameters.
1081    pub fn from_parts(algorithm: ObjectIdentifier, parameters: Option<Asn1RawDer>) -> Self {
1082        let parameters = parameters.and_then(|raw| {
1083            // `params` field is always present and set to NULL if no parameters are needed.
1084            // therefore, we need special handling to show absence of parameters in
1085            // `RawAlgorithmIdentifier` API
1086            if raw.0 == [0x05, 0x00] { None } else { Some(raw) }
1087        });
1088
1089        Self { algorithm, parameters }
1090    }
1091
1092    pub fn algorithm(&self) -> &ObjectIdentifier {
1093        &self.algorithm
1094    }
1095
1096    pub fn parameters(&self) -> Option<&Asn1RawDer> {
1097        self.parameters.as_ref()
1098    }
1099}
1100
1101impl ser::Serialize for RawAlgorithmIdentifier {
1102    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1103    where
1104        S: ser::Serializer,
1105    {
1106        use ser::SerializeSeq;
1107
1108        let mut seq = serializer.serialize_seq(Some(2))?;
1109        let oid = ObjectIdentifierAsn1(self.algorithm.clone());
1110        seq.serialize_element(&oid)?;
1111        if let Some(parameters) = &self.parameters {
1112            seq.serialize_element(parameters)?;
1113        } else {
1114            // NULL should be still serialized to AlgortihmIdentifier even if params are absent
1115            seq.serialize_element(&())?;
1116        }
1117        seq.end()
1118    }
1119}
1120
1121impl<'de> de::Deserialize<'de> for RawAlgorithmIdentifier {
1122    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1123    where
1124        D: de::Deserializer<'de>,
1125    {
1126        struct RawAlgorithmIdentifierVisitor;
1127
1128        impl<'de> de::Visitor<'de> for RawAlgorithmIdentifierVisitor {
1129            type Value = RawAlgorithmIdentifier;
1130
1131            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1132                formatter.write_str("a valid DER-encoded RawAlgorithmIdentifier")
1133            }
1134
1135            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1136            where
1137                A: de::SeqAccess<'de>,
1138            {
1139                let oid: ObjectIdentifierAsn1 = seq_next_element!(seq, RawAlgorithmIdentifier, "raw algorithm oid");
1140
1141                let algorithm = oid.0;
1142                let parameters: Option<Asn1RawDer> = seq.next_element::<Asn1RawDer>()?;
1143                Ok(RawAlgorithmIdentifier::from_parts(algorithm, parameters))
1144            }
1145        }
1146
1147        deserializer.deserialize_seq(RawAlgorithmIdentifierVisitor)
1148    }
1149}
1150
1151#[cfg(test)]
1152mod tests {
1153    use super::*;
1154    use base64::Engine as _;
1155    use base64::engine::general_purpose;
1156
1157    #[test]
1158    fn aes_null_params() {
1159        let expected = [48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 1, 1, 5, 0];
1160        let aes_id = AlgorithmIdentifier::new_aes128(AesMode::Ecb, AesParameters::Null);
1161        check_serde!(aes_id: AlgorithmIdentifier in expected);
1162    }
1163
1164    #[test]
1165    fn aes_iv_params() {
1166        let expected = [
1167            48, 25, 6, 9, 96, 134, 72, 1, 101, 3, 4, 1, 1, 4, 12, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
1168            165, 165,
1169        ];
1170        let aes_id =
1171            AlgorithmIdentifier::new_aes128(AesMode::Ecb, AesParameters::InitializationVector(vec![0xA5; 12].into()));
1172        check_serde!(aes_id: AlgorithmIdentifier in expected);
1173    }
1174
1175    #[test]
1176    fn aes_ae_params() {
1177        let expected = [
1178            48, 30, 6, 9, 96, 134, 72, 1, 101, 3, 4, 1, 1, 48, 17, 4, 12, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1179            255, 255, 255, 2, 1, 12,
1180        ];
1181        let aes_id = AlgorithmIdentifier::new_aes128(
1182            AesMode::Ecb,
1183            AesParameters::AuthenticatedEncryptionParameters(AesAuthEncParams {
1184                nonce: vec![0xff; 12].into(),
1185                icv_len: vec![12].into(),
1186            }),
1187        );
1188        check_serde!(aes_id: AlgorithmIdentifier in expected);
1189    }
1190
1191    #[test]
1192    fn sha256() {
1193        let expected = [48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0];
1194        let sha = AlgorithmIdentifier::new_sha(ShaVariant::SHA2_256);
1195        check_serde!(sha: AlgorithmIdentifier in expected);
1196    }
1197
1198    #[test]
1199    fn sha3_256() {
1200        let expected = [
1201            0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00,
1202        ];
1203        let sha = AlgorithmIdentifier::new_sha(ShaVariant::SHA3_256);
1204        check_serde!(sha: AlgorithmIdentifier in expected);
1205    }
1206
1207    #[test]
1208    fn rsa_enc_with_sha3_256() {
1209        let expected = [
1210            0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0e, 0x05, 0x00,
1211        ];
1212        let sha = AlgorithmIdentifier::new_sha3_256_with_rsa_encryption();
1213        check_serde!(sha: AlgorithmIdentifier in expected);
1214    }
1215
1216    #[test]
1217    fn ecdsa_with_sha3_512() {
1218        let expected = [
1219            0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0C,
1220        ];
1221        let sha = AlgorithmIdentifier::new_ecdsa_with_sha3_512();
1222        check_serde!(sha: AlgorithmIdentifier in expected);
1223    }
1224
1225    #[test]
1226    fn ec_params() {
1227        let expected = [
1228            48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2,
1229        ];
1230        let ec_params =
1231            AlgorithmIdentifier::new_elliptic_curve(EcParameters::NamedCurve(oids::ecdsa_with_sha256().into()));
1232        check_serde!(ec_params: AlgorithmIdentifier in expected);
1233    }
1234
1235    #[test]
1236    fn digest_info() {
1237        let digest = picky_asn1_der::to_vec(&DigestInfo {
1238            oid: AlgorithmIdentifier::new_sha(ShaVariant::SHA2_256),
1239            // Random 32 bytes generated for a SHA256 hash
1240            digest: vec![
1241                0xf4, 0x12, 0x6b, 0x55, 0xbf, 0xcf, 0x8c, 0xc4, 0xe9, 0xe0, 0xbe, 0x5a, 0x9c, 0x16, 0x88, 0x55, 0x0f,
1242                0x26, 0x00, 0x8c, 0x2c, 0xa5, 0xf6, 0xaf, 0xbd, 0xe7, 0x9c, 0x42, 0x22, 0xe9, 0x25, 0xed,
1243            ]
1244            .into(),
1245        })
1246        .unwrap();
1247
1248        let expected = vec![
1249            0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04,
1250            0x20, 0xf4, 0x12, 0x6b, 0x55, 0xbf, 0xcf, 0x8c, 0xc4, 0xe9, 0xe0, 0xbe, 0x5a, 0x9c, 0x16, 0x88, 0x55, 0x0f,
1251            0x26, 0x00, 0x8c, 0x2c, 0xa5, 0xf6, 0xaf, 0xbd, 0xe7, 0x9c, 0x42, 0x22, 0xe9, 0x25, 0xed,
1252        ];
1253
1254        assert_eq!(digest, expected);
1255    }
1256
1257    #[test]
1258    fn rsa_pss_params_sha256() {
1259        let expected = [
1260            0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
1261            0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d,
1262            0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20,
1263        ];
1264        let structure = RsassaPssParams::new(HashAlgorithm::SHA256);
1265        check_serde!(structure: RsassaPssParams in expected);
1266    }
1267
1268    #[test]
1269    fn rsa_pss_params_sha384() {
1270        let expected = [
1271            0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
1272            0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d,
1273            0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x30,
1274        ];
1275        let structure = RsassaPssParams::new(HashAlgorithm::SHA384);
1276        check_serde!(structure: RsassaPssParams in expected);
1277    }
1278
1279    #[test]
1280    fn rsa_pss_params_sha512() {
1281        let expected = [
1282            0x30, 0x34, 0xa0, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
1283            0x00, 0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d,
1284            0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x40,
1285        ];
1286        let structure = RsassaPssParams::new(HashAlgorithm::SHA512);
1287        check_serde!(structure: RsassaPssParams in expected);
1288    }
1289
1290    #[test]
1291    fn rsa_pss_encryption() {
1292        let expected = [
1293            0x30, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0A, 0x30, 0x34, 0xa0, 0x0f, 0x30,
1294            0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa1, 0x1c, 0x30, 0x1a,
1295            0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
1296            0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20,
1297        ];
1298        let structure = AlgorithmIdentifier::new_rsassa_pss(RsassaPssParams::new(HashAlgorithm::SHA256));
1299        check_serde!(structure: AlgorithmIdentifier in expected);
1300    }
1301
1302    #[test]
1303    fn rsa_encryption() {
1304        let expected = [
1305            0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00,
1306        ];
1307        let rsa_encryption = AlgorithmIdentifier::new_rsa_encryption();
1308        check_serde!(rsa_encryption: AlgorithmIdentifier in expected);
1309    }
1310
1311    #[test]
1312    fn rsa_encryption_with_missing_params() {
1313        let encoded = [
1314            0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
1315        ];
1316        let deserialized: AlgorithmIdentifier =
1317            picky_asn1_der::from_bytes(&encoded).expect("failed AlgorithmIdentifier deserialization");
1318        pretty_assertions::assert_eq!(
1319            deserialized,
1320            AlgorithmIdentifier::new_rsa_encryption(),
1321            concat!("deserialized ", stringify!($item), " doesn't match")
1322        );
1323    }
1324
1325    #[test]
1326    fn raw_algorithm_roundtrip_no_params() {
1327        let encoded = [
1328            0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x09, 0x05, 0x00,
1329        ];
1330        let decoded: RawAlgorithmIdentifier = picky_asn1_der::from_bytes(&encoded).unwrap();
1331        let expected = RawAlgorithmIdentifier::from_parts(oids::hmac_with_sha256(), None);
1332        pretty_assertions::assert_eq!(decoded, expected);
1333        check_serde!(decoded: RawAlgorithmIdentifier in encoded);
1334    }
1335
1336    #[test]
1337    fn raw_algorithm_roundtrip() {
1338        let encoded = [
1339            0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, 0x69,
1340            0x61, 0x74, 0x65, 0x5F, 0x63, 0x61,
1341        ];
1342        let decoded: RawAlgorithmIdentifier = picky_asn1_der::from_bytes(&encoded).unwrap();
1343        let oid: ObjectIdentifier = "2.5.4.3".to_string().try_into().unwrap();
1344        let params = Asn1RawDer(vec![
1345            0x0C, 0x0F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5F, 0x63, 0x61,
1346        ]);
1347        let expected = RawAlgorithmIdentifier::from_parts(oid, Some(params));
1348        pretty_assertions::assert_eq!(decoded, expected);
1349        check_serde!(decoded: RawAlgorithmIdentifier in encoded);
1350    }
1351
1352    #[test]
1353    fn mldsa_44() {
1354        let expected = [
1355            0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x11,
1356        ];
1357        let mldsa = AlgorithmIdentifier::new_mldsa_44();
1358        check_serde!(mldsa: AlgorithmIdentifier in expected);
1359    }
1360
1361    #[test]
1362    fn mldsa_65() {
1363        let expected = [
1364            0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x12,
1365        ];
1366        let mldsa = AlgorithmIdentifier::new_mldsa_65();
1367        check_serde!(mldsa: AlgorithmIdentifier in expected);
1368    }
1369
1370    #[test]
1371    fn mldsa_87() {
1372        let expected = [
1373            0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x13,
1374        ];
1375        let mldsa = AlgorithmIdentifier::new_mldsa_87();
1376        check_serde!(mldsa: AlgorithmIdentifier in expected);
1377    }
1378}