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::{IntegerAsn1, ObjectIdentifierAsn1, OctetStringAsn1};
5use serde::{de, ser, Deserialize, Serialize};
6use std::error::Error;
7use std::fmt;
8
9/// unsupported algorithm
10#[derive(Debug)]
11pub struct UnsupportedAlgorithmError {
12    pub algorithm: String,
13}
14
15impl fmt::Display for UnsupportedAlgorithmError {
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17        write!(f, "unsupported algorithm:  {}", self.algorithm)
18    }
19}
20
21impl Error for UnsupportedAlgorithmError {}
22
23#[derive(Debug, PartialEq, Clone)]
24pub struct AlgorithmIdentifier {
25    algorithm: ObjectIdentifierAsn1,
26    parameters: AlgorithmIdentifierParameters,
27}
28
29impl AlgorithmIdentifier {
30    pub fn oid(&self) -> &ObjectIdentifier {
31        &self.algorithm.0
32    }
33
34    pub fn parameters(&self) -> &AlgorithmIdentifierParameters {
35        &self.parameters
36    }
37
38    pub fn is_a(&self, algorithm: ObjectIdentifier) -> bool {
39        algorithm.eq(&self.algorithm.0)
40    }
41
42    pub fn new_sha1_with_rsa_encryption() -> Self {
43        Self {
44            algorithm: oids::sha1_with_rsa_encryption().into(),
45            parameters: AlgorithmIdentifierParameters::Null,
46        }
47    }
48
49    pub fn new_sha224_with_rsa_encryption() -> Self {
50        Self {
51            algorithm: oids::sha224_with_rsa_encryption().into(),
52            parameters: AlgorithmIdentifierParameters::Null,
53        }
54    }
55
56    pub fn new_sha256_with_rsa_encryption() -> Self {
57        Self {
58            algorithm: oids::sha256_with_rsa_encryption().into(),
59            parameters: AlgorithmIdentifierParameters::Null,
60        }
61    }
62
63    pub fn new_sha384_with_rsa_encryption() -> Self {
64        Self {
65            algorithm: oids::sha384_with_rsa_encryption().into(),
66            parameters: AlgorithmIdentifierParameters::Null,
67        }
68    }
69
70    pub fn new_sha512_with_rsa_encryption() -> Self {
71        Self {
72            algorithm: oids::sha512_with_rsa_encryption().into(),
73            parameters: AlgorithmIdentifierParameters::Null,
74        }
75    }
76
77    pub fn new_sha3_384_with_rsa_encryption() -> Self {
78        Self {
79            algorithm: oids::id_rsassa_pkcs1_v1_5_with_sha3_384().into(),
80            parameters: AlgorithmIdentifierParameters::Null,
81        }
82    }
83
84    pub fn new_sha3_512_with_rsa_encryption() -> Self {
85        Self {
86            algorithm: oids::id_rsassa_pkcs1_v1_5_with_sha3_512().into(),
87            parameters: AlgorithmIdentifierParameters::Null,
88        }
89    }
90
91    pub fn new_rsa_encryption() -> Self {
92        Self {
93            algorithm: oids::rsa_encryption().into(),
94            parameters: AlgorithmIdentifierParameters::Null,
95        }
96    }
97
98    pub fn new_rsa_encryption_with_sha(variant: ShaVariant) -> Result<Self, UnsupportedAlgorithmError> {
99        let algorithm = match variant {
100            ShaVariant::SHA2_224 => oids::sha224_with_rsa_encryption(),
101            ShaVariant::SHA2_256 => oids::sha256_with_rsa_encryption(),
102            ShaVariant::SHA2_384 => oids::sha384_with_rsa_encryption(),
103            ShaVariant::SHA2_512 => oids::sha512_with_rsa_encryption(),
104            ShaVariant::SHA3_384 => oids::id_rsassa_pkcs1_v1_5_with_sha3_384(),
105            ShaVariant::SHA3_512 => oids::id_rsassa_pkcs1_v1_5_with_sha3_512(),
106            _ => {
107                return Err(UnsupportedAlgorithmError {
108                    algorithm: format!("{:?}", variant),
109                })
110            }
111        };
112
113        Ok(Self {
114            algorithm: algorithm.into(),
115            parameters: AlgorithmIdentifierParameters::Null,
116        })
117    }
118
119    pub fn new_ecdsa_with_sha384() -> Self {
120        Self {
121            algorithm: oids::ecdsa_with_sha384().into(),
122            parameters: AlgorithmIdentifierParameters::None,
123        }
124    }
125
126    pub fn new_ecdsa_with_sha256() -> Self {
127        Self {
128            algorithm: oids::ecdsa_with_sha256().into(),
129            parameters: AlgorithmIdentifierParameters::None,
130        }
131    }
132
133    pub fn new_elliptic_curve<P: Into<EcParameters>>(ec_params: P) -> Self {
134        Self {
135            algorithm: oids::ec_public_key().into(),
136            parameters: AlgorithmIdentifierParameters::Ec(ec_params.into()),
137        }
138    }
139
140    pub fn new_ed25519() -> Self {
141        Self {
142            algorithm: oids::ed25519().into(),
143            parameters: AlgorithmIdentifierParameters::None,
144        }
145    }
146
147    pub fn new_aes128(mode: AesMode, params: AesParameters) -> Self {
148        Self {
149            algorithm: mode.to_128bit_oid(),
150            parameters: AlgorithmIdentifierParameters::Aes(params),
151        }
152    }
153
154    pub fn new_aes192(mode: AesMode, params: AesParameters) -> Self {
155        Self {
156            algorithm: mode.to_192bit_oid(),
157            parameters: AlgorithmIdentifierParameters::Aes(params),
158        }
159    }
160
161    pub fn new_aes256(mode: AesMode, params: AesParameters) -> Self {
162        Self {
163            algorithm: mode.to_256bit_oid(),
164            parameters: AlgorithmIdentifierParameters::Aes(params),
165        }
166    }
167
168    pub fn new_sha(variant: ShaVariant) -> Self {
169        Self {
170            algorithm: variant.into(),
171            parameters: AlgorithmIdentifierParameters::Null,
172        }
173    }
174}
175
176impl ser::Serialize for AlgorithmIdentifier {
177    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
178    where
179        S: ser::Serializer,
180    {
181        use ser::SerializeSeq;
182        let mut seq = serializer.serialize_seq(Some(2))?;
183        seq.serialize_element(&self.algorithm)?;
184        match &self.parameters {
185            AlgorithmIdentifierParameters::None => {}
186            AlgorithmIdentifierParameters::Null => {
187                seq.serialize_element(&())?;
188            }
189            AlgorithmIdentifierParameters::Ec(ec_params) => {
190                seq.serialize_element(ec_params)?;
191            }
192            AlgorithmIdentifierParameters::Aes(aes_params) => {
193                seq.serialize_element(aes_params)?;
194            }
195        }
196        seq.end()
197    }
198}
199
200impl<'de> de::Deserialize<'de> for AlgorithmIdentifier {
201    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
202    where
203        D: de::Deserializer<'de>,
204    {
205        struct Visitor;
206
207        impl<'de> de::Visitor<'de> for Visitor {
208            type Value = AlgorithmIdentifier;
209
210            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
211                formatter.write_str("a valid DER-encoded algorithm identifier")
212            }
213
214            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
215            where
216                A: de::SeqAccess<'de>,
217            {
218                let oid: ObjectIdentifierAsn1 = seq_next_element!(seq, AlgorithmIdentifier, "algorithm oid");
219
220                let args = match Into::<String>::into(&oid.0).as_str() {
221                    oids::RSA_ENCRYPTION
222                    | oids::SHA1_WITH_RSA_ENCRYPTION
223                    | oids::SHA224_WITH_RSA_ENCRYPTION
224                    | oids::SHA256_WITH_RSA_ENCRYPTION
225                    | oids::SHA384_WITH_RSA_ENCRYPTION
226                    | oids::SHA512_WITH_RSA_ENCRYPTION => {
227                        // Try to deserialize next element in sequence.
228                        // Error is ignored because some implementations just leave no parameter at all for
229                        // RSA encryption (ie: rsa-export-0.1.1 crate) but we still want to be able
230                        // to parse their output.
231                        let _ = seq.next_element::<()>();
232                        AlgorithmIdentifierParameters::Null
233                    }
234                    oids::ECDSA_WITH_SHA384 | oids::ECDSA_WITH_SHA256 | oids::ED25519 => {
235                        AlgorithmIdentifierParameters::None
236                    }
237                    oids::EC_PUBLIC_KEY => AlgorithmIdentifierParameters::Ec(seq_next_element!(
238                        seq,
239                        AlgorithmIdentifier,
240                        "elliptic curves parameters"
241                    )),
242                    // AES
243                    x if x.starts_with("2.16.840.1.101.3.4.1.") => AlgorithmIdentifierParameters::Aes(
244                        seq_next_element!(seq, AlgorithmIdentifier, "aes algorithm identifier"),
245                    ),
246                    // SHA
247                    x if x.starts_with("2.16.840.1.101.3.4.2.") => {
248                        type Unit = ();
249                        seq_next_element!(seq, Unit, AlgorithmIdentifier, "sha algorithm identifier");
250                        AlgorithmIdentifierParameters::Null
251                    }
252                    _ => {
253                        return Err(serde_invalid_value!(
254                            AlgorithmIdentifier,
255                            "unsupported algorithm (unknown oid)",
256                            "a supported algorithm"
257                        ));
258                    }
259                };
260
261                Ok(AlgorithmIdentifier {
262                    algorithm: oid,
263                    parameters: args,
264                })
265            }
266        }
267
268        deserializer.deserialize_seq(Visitor)
269    }
270}
271
272#[derive(Debug, PartialEq, Clone)]
273pub enum AlgorithmIdentifierParameters {
274    None,
275    Null,
276    Aes(AesParameters),
277    Ec(EcParameters),
278}
279
280#[derive(Debug, PartialEq, Clone)]
281pub enum EcParameters {
282    NamedCurve(ObjectIdentifierAsn1),
283    // -- implicitCurve and specifiedCurve MUST NOT be used in PKIX.
284    //ImplicitCurve,
285    //SpecifiedCurve(SpecifiedECDomain)
286}
287
288impl From<ObjectIdentifierAsn1> for EcParameters {
289    fn from(oid: ObjectIdentifierAsn1) -> Self {
290        Self::NamedCurve(oid)
291    }
292}
293
294impl From<ObjectIdentifier> for EcParameters {
295    fn from(oid: ObjectIdentifier) -> Self {
296        Self::NamedCurve(oid.into())
297    }
298}
299
300impl ser::Serialize for EcParameters {
301    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
302    where
303        S: ser::Serializer,
304    {
305        match &self {
306            EcParameters::NamedCurve(oid) => oid.serialize(serializer),
307        }
308    }
309}
310
311impl<'de> de::Deserialize<'de> for EcParameters {
312    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
313    where
314        D: de::Deserializer<'de>,
315    {
316        struct Visitor;
317
318        impl<'de> de::Visitor<'de> for Visitor {
319            type Value = EcParameters;
320
321            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
322                formatter.write_str("a valid DER-encoded DirectoryString")
323            }
324
325            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
326            where
327                A: de::SeqAccess<'de>,
328            {
329                let tag_peeker: TagPeeker = seq_next_element!(seq, EcParameters, "choice tag");
330                match tag_peeker.next_tag {
331                    Tag::OID => Ok(EcParameters::NamedCurve(seq_next_element!(
332                        seq,
333                        EcParameters,
334                        "Object Identifier"
335                    ))),
336                    _ => Err(serde_invalid_value!(
337                        EcParameters,
338                        "unsupported or unknown elliptic curve parameter",
339                        "a supported elliptic curve parameter"
340                    )),
341                }
342            }
343        }
344
345        deserializer.deserialize_enum("DirectoryString", &["NamedCurve", "ImplicitCurve"], Visitor)
346    }
347}
348
349#[derive(Clone, Copy, PartialEq, Debug)]
350pub enum AesMode {
351    Ecb,
352    Cbc,
353    Ofb,
354    Cfb,
355    Wrap,
356    Gcm,
357    Ccm,
358    WrapPad,
359}
360
361#[derive(Debug, PartialEq, Clone)]
362pub enum AesParameters {
363    Null,
364    InitializationVector(OctetStringAsn1),
365    AuthenticatedEncryptionParameters(AesAuthEncParams),
366}
367
368#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
369pub struct AesAuthEncParams {
370    nonce: OctetStringAsn1,
371    icv_len: IntegerAsn1,
372}
373
374impl AesMode {
375    fn to_128bit_oid(self) -> ObjectIdentifierAsn1 {
376        match self {
377            AesMode::Ecb => oids::aes128_ecb().into(),
378            AesMode::Cbc => oids::aes128_cbc().into(),
379            AesMode::Ofb => oids::aes128_ofb().into(),
380            AesMode::Cfb => oids::aes128_cfb().into(),
381            AesMode::Wrap => oids::aes128_wrap().into(),
382            AesMode::Gcm => oids::aes128_gcm().into(),
383            AesMode::Ccm => oids::aes128_ccm().into(),
384            AesMode::WrapPad => oids::aes128_wrap_pad().into(),
385        }
386    }
387
388    fn to_192bit_oid(self) -> ObjectIdentifierAsn1 {
389        match self {
390            AesMode::Ecb => oids::aes192_ecb().into(),
391            AesMode::Cbc => oids::aes192_cbc().into(),
392            AesMode::Ofb => oids::aes192_ofb().into(),
393            AesMode::Cfb => oids::aes192_cfb().into(),
394            AesMode::Wrap => oids::aes192_wrap().into(),
395            AesMode::Gcm => oids::aes192_gcm().into(),
396            AesMode::Ccm => oids::aes192_ccm().into(),
397            AesMode::WrapPad => oids::aes192_wrap_pad().into(),
398        }
399    }
400
401    fn to_256bit_oid(self) -> ObjectIdentifierAsn1 {
402        match self {
403            AesMode::Ecb => oids::aes256_ecb().into(),
404            AesMode::Cbc => oids::aes256_cbc().into(),
405            AesMode::Ofb => oids::aes256_ofb().into(),
406            AesMode::Cfb => oids::aes256_cfb().into(),
407            AesMode::Wrap => oids::aes256_wrap().into(),
408            AesMode::Gcm => oids::aes256_gcm().into(),
409            AesMode::Ccm => oids::aes256_ccm().into(),
410            AesMode::WrapPad => oids::aes256_wrap_pad().into(),
411        }
412    }
413}
414
415impl ser::Serialize for AesParameters {
416    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
417    where
418        S: ser::Serializer,
419    {
420        match self {
421            AesParameters::Null => ().serialize(serializer),
422            AesParameters::InitializationVector(iv) => iv.serialize(serializer),
423            AesParameters::AuthenticatedEncryptionParameters(params) => params.serialize(serializer),
424        }
425    }
426}
427
428impl<'de> de::Deserialize<'de> for AesParameters {
429    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
430    where
431        D: de::Deserializer<'de>,
432    {
433        struct Visitor;
434
435        impl<'de> de::Visitor<'de> for Visitor {
436            type Value = AesParameters;
437
438            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
439                formatter.write_str("a valid DER-encoded DirectoryString")
440            }
441
442            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
443            where
444                A: de::SeqAccess<'de>,
445            {
446                let tag_peeker: TagPeeker = seq_next_element!(seq, AesParameters, "choice tag");
447                match tag_peeker.next_tag {
448                    Tag::OCTET_STRING => Ok(AesParameters::InitializationVector(seq_next_element!(
449                        seq,
450                        AesParameters,
451                        "Object Identifier"
452                    ))),
453                    Tag::NULL => {
454                        seq.next_element::<()>()?.expect("should not panic");
455                        Ok(AesParameters::Null)
456                    }
457                    Tag::SEQUENCE => Ok(AesParameters::AuthenticatedEncryptionParameters(seq_next_element!(
458                        seq,
459                        AesAuthEncParams,
460                        "AES Authenticated Encryption parameters"
461                    ))),
462                    _ => Err(serde_invalid_value!(
463                        AesParameters,
464                        "unsupported or unknown AES parameter",
465                        "a supported AES parameter"
466                    )),
467                }
468            }
469        }
470
471        deserializer.deserialize_enum(
472            "DirectoryString",
473            &["Null", "InitializationVector", "AuthenticatedEncryptionParameters"],
474            Visitor,
475        )
476    }
477}
478
479#[derive(Clone, Copy, PartialEq, Debug)]
480#[allow(non_camel_case_types)] // 'SHA2_512_224' is clearer than 'SHA2512224' or 'Sha2512224' imo
481pub enum ShaVariant {
482    SHA2_224,
483    SHA2_256,
484    SHA2_384,
485    SHA2_512,
486    SHA2_512_224,
487    SHA2_512_256,
488    SHA3_224,
489    SHA3_256,
490    SHA3_384,
491    SHA3_512,
492    SHAKE128,
493    SHAKE256,
494}
495
496impl From<ShaVariant> for ObjectIdentifierAsn1 {
497    fn from(variant: ShaVariant) -> Self {
498        match variant {
499            ShaVariant::SHA2_224 => oids::sha224().into(),
500            ShaVariant::SHA2_256 => oids::sha256().into(),
501            ShaVariant::SHA2_384 => oids::sha384().into(),
502            ShaVariant::SHA2_512 => oids::sha512().into(),
503            ShaVariant::SHA2_512_224 => oids::sha512_224().into(),
504            ShaVariant::SHA2_512_256 => oids::sha512_256().into(),
505            ShaVariant::SHA3_224 => oids::sha3_224().into(),
506            ShaVariant::SHA3_256 => oids::sha3_256().into(),
507            ShaVariant::SHA3_384 => oids::sha3_384().into(),
508            ShaVariant::SHA3_512 => oids::sha3_512().into(),
509            ShaVariant::SHAKE128 => oids::shake128().into(),
510            ShaVariant::SHAKE256 => oids::shake256().into(),
511        }
512    }
513}
514
515/// [PKCS #1: RSA Cryptography Specifications Version
516/// 2.2](https://tools.ietf.org/html/rfc8017.html#section-9.2)
517///
518/// # Section 9.2
519///
520/// The type DigestInfo has the syntax:
521///
522/// ```not_rust
523///    DigestInfo ::= SEQUENCE {
524///        digestAlgorithm AlgorithmIdentifier,
525///        digest OCTET STRING
526///    }
527/// ```
528#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
529pub struct DigestInfo {
530    pub oid: AlgorithmIdentifier,
531    pub digest: OctetStringAsn1,
532}
533
534#[cfg(test)]
535mod tests {
536    use super::*;
537
538    #[test]
539    fn aes_null_params() {
540        let expected = [48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 1, 1, 5, 0];
541        let aes_id = AlgorithmIdentifier::new_aes128(AesMode::Ecb, AesParameters::Null);
542        check_serde!(aes_id: AlgorithmIdentifier in expected);
543    }
544
545    #[test]
546    fn aes_iv_params() {
547        let expected = [
548            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,
549            165, 165,
550        ];
551        let aes_id =
552            AlgorithmIdentifier::new_aes128(AesMode::Ecb, AesParameters::InitializationVector(vec![0xA5; 12].into()));
553        check_serde!(aes_id: AlgorithmIdentifier in expected);
554    }
555
556    #[test]
557    fn aes_ae_params() {
558        let expected = [
559            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,
560            255, 255, 255, 2, 1, 12,
561        ];
562        let aes_id = AlgorithmIdentifier::new_aes128(
563            AesMode::Ecb,
564            AesParameters::AuthenticatedEncryptionParameters(AesAuthEncParams {
565                nonce: vec![0xff; 12].into(),
566                icv_len: vec![12].into(),
567            }),
568        );
569        check_serde!(aes_id: AlgorithmIdentifier in expected);
570    }
571
572    #[test]
573    fn sha256() {
574        let expected = [48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0];
575        let sha = AlgorithmIdentifier::new_sha(ShaVariant::SHA2_256);
576        check_serde!(sha: AlgorithmIdentifier in expected);
577    }
578
579    #[test]
580    fn ec_params() {
581        let expected = [
582            48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2,
583        ];
584        let ec_params =
585            AlgorithmIdentifier::new_elliptic_curve(EcParameters::NamedCurve(oids::ecdsa_with_sha256().into()));
586        check_serde!(ec_params: AlgorithmIdentifier in expected);
587    }
588
589    #[test]
590    fn digest_info() {
591        let digest = picky_asn1_der::to_vec(&DigestInfo {
592            oid: AlgorithmIdentifier::new_sha(ShaVariant::SHA2_256),
593            // Random 32 bytes generated for a SHA256 hash
594            digest: vec![
595                0xf4, 0x12, 0x6b, 0x55, 0xbf, 0xcf, 0x8c, 0xc4, 0xe9, 0xe0, 0xbe, 0x5a, 0x9c, 0x16, 0x88, 0x55, 0x0f,
596                0x26, 0x00, 0x8c, 0x2c, 0xa5, 0xf6, 0xaf, 0xbd, 0xe7, 0x9c, 0x42, 0x22, 0xe9, 0x25, 0xed,
597            ]
598            .into(),
599        })
600        .unwrap();
601
602        let expected = vec![
603            0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04,
604            0x20, 0xf4, 0x12, 0x6b, 0x55, 0xbf, 0xcf, 0x8c, 0xc4, 0xe9, 0xe0, 0xbe, 0x5a, 0x9c, 0x16, 0x88, 0x55, 0x0f,
605            0x26, 0x00, 0x8c, 0x2c, 0xa5, 0xf6, 0xaf, 0xbd, 0xe7, 0x9c, 0x42, 0x22, 0xe9, 0x25, 0xed,
606        ];
607
608        assert_eq!(digest, expected);
609    }
610
611    #[test]
612    fn rsa_encryption() {
613        let expected = [
614            0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00,
615        ];
616        let rsa_encryption = AlgorithmIdentifier::new_rsa_encryption();
617        check_serde!(rsa_encryption: AlgorithmIdentifier in expected);
618    }
619
620    #[test]
621    fn rsa_encryption_with_missing_params() {
622        let encoded = [
623            0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
624        ];
625        let deserialized: AlgorithmIdentifier =
626            picky_asn1_der::from_bytes(&encoded).expect("failed AlgorithmIdentifier deserialization");
627        pretty_assertions::assert_eq!(
628            deserialized,
629            AlgorithmIdentifier::new_rsa_encryption(),
630            concat!("deserialized ", stringify!($item), " doesn't match")
631        );
632    }
633}