picky_asn1_x509/
private_key_info.rs

1use crate::{oids, AlgorithmIdentifier, AlgorithmIdentifierParameters, EcParameters, EncapsulatedEcPoint};
2
3use picky_asn1::tag::TagPeeker;
4use picky_asn1::wrapper::{
5    BitStringAsn1, ExplicitContextTag0, ExplicitContextTag1, IntegerAsn1, ObjectIdentifierAsn1, OctetStringAsn1,
6    OctetStringAsn1Container, Optional,
7};
8#[cfg(not(feature = "legacy"))]
9use serde::Deserialize;
10use serde::{de, ser, Serialize};
11#[cfg(feature = "zeroize")]
12use zeroize::Zeroize;
13
14use oid::ObjectIdentifier;
15use picky_asn1::bit_string::BitString;
16use picky_asn1::Asn1Type;
17use std::fmt;
18
19/// When `PrivateKeyInfo` have this version specified, it should not have `public_key` field set.
20/// This version of `PrivateKeyInfo` mostly used to represent RSA and EC private keys.
21pub const PRIVATE_KEY_INFO_VERSION_1: u8 = 0;
22/// When `PrivateKeyInfo` have this version specified, it should have `public_key` field set.
23/// This version of `PrivateKeyInfo` mostly used to represent Ed25519 and Ed448 private keys and
24/// defined as `OneAsymmetricKey` in [RFC5958](https://tools.ietf.org/html/rfc5958#section-2).
25pub const PRIVATE_KEY_INFO_VERSION_2: u8 = 1;
26
27pub type EncapsulatedEcSecret = OctetStringAsn1;
28
29/// [Public-Key Cryptography Standards (PKCS) #8](https://tools.ietf.org/html/rfc5208#section-5)
30/// [Asymmetric Key Packages](https://tools.ietf.org/html/rfc5958#section-2)
31///
32/// # Section 5
33///
34/// Private-key information shall have ASN.1 type `OneAsymmetricKey` (Backwards-compatible with
35/// `PrivateKeyInfo` from RFC5208):
36///
37/// ```not_rust
38/// OneAsymmetricKey ::= SEQUENCE {
39///      version                   Version,
40///      privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
41///      privateKey                PrivateKey,
42///      attributes           [0]  IMPLICIT Attributes OPTIONAL,
43///      ...,
44///      [[2: publicKey       [1] PublicKey OPTIONAL ]],
45///      ...
46/// }
47///
48///   Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2)
49///
50///   PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
51///
52///   PrivateKey ::= OCTET STRING
53///
54///   PublicKey ::= BIT STRING
55///
56///   Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } }
57/// ```
58///
59/// The fields of type `OneAsymmetricKey` have the following meanings:
60///
61/// `version` identifies the version of OneAsymmetricKey.  If publicKey
62/// is present, then version is set to v2(1) else version is set to v1(0).
63///
64/// `privateKeyAlgorithm` identifies the private-key algorithm.  One
65/// example of a private-key algorithm is PKCS #1's rsaEncryption.
66///
67/// `privateKey` is an octet string whose contents are the value of the
68/// private key.  The interpretation of the contents is defined in the
69/// registration of the private-key algorithm.  For an RSA private
70/// key, for example, the contents are a BER encoding of a value of
71/// type RSAPrivateKey.
72///
73/// `publicKey` is OPTIONAL. When present, it contains the public key
74/// encoded in a BIT STRING. The structure within the BIT STRING, if
75/// any, depends on the `privateKeyAlgorithm`
76///
77/// `attributes` is a set of attributes.  These are the extended
78/// information that is encrypted along with the private-key
79/// information.
80#[derive(Serialize, Debug, Clone, PartialEq, Eq)]
81pub struct PrivateKeyInfo {
82    pub version: u8,
83    pub private_key_algorithm: AlgorithmIdentifier,
84    pub private_key: PrivateKeyValue,
85    // -- attributes (not supported)
86    pub public_key: Option<ExplicitContextTag1<Optional<BitStringAsn1>>>,
87}
88
89impl PrivateKeyInfo {
90    pub fn new_rsa_encryption(
91        modulus: IntegerAsn1,
92        public_exponent: IntegerAsn1,
93        private_exponent: IntegerAsn1,
94        primes: (IntegerAsn1, IntegerAsn1),
95        exponents: (IntegerAsn1, IntegerAsn1),
96        coefficient: IntegerAsn1,
97    ) -> Self {
98        let private_key = PrivateKeyValue::Rsa(
99            RsaPrivateKey {
100                version: vec![0].into(),
101                modulus,
102                public_exponent,
103                private_exponent,
104                prime_1: primes.0,
105                prime_2: primes.1,
106                exponent_1: exponents.0,
107                exponent_2: exponents.1,
108                coefficient,
109            }
110            .into(),
111        );
112
113        Self {
114            version: PRIVATE_KEY_INFO_VERSION_1,
115            private_key_algorithm: AlgorithmIdentifier::new_rsa_encryption(),
116            private_key,
117            public_key: None,
118        }
119    }
120
121    /// Creates a new `PrivateKeyInfo` with the given `curve_oid` and `secret`.
122    ///
123    /// If `skip_optional_params` is `true`, the `parameters` field will be omitted from internal
124    /// `ECPrivateKey` ASN.1 structure, reducing duplication. This information is still present in
125    /// the `private_key_algorithm` field.
126    pub fn new_ec_encryption(
127        curve_oid: ObjectIdentifier,
128        secret: impl Into<OctetStringAsn1>,
129        public_point: Option<BitString>,
130        skip_optional_params: bool,
131    ) -> Self {
132        let curve_oid: ObjectIdentifierAsn1 = curve_oid.into();
133        let secret: OctetStringAsn1 = secret.into();
134        let point: Option<BitStringAsn1> = public_point.map(Into::into);
135
136        let parameters: ExplicitContextTag0<Option<EcParameters>> =
137            (!skip_optional_params).then(|| curve_oid.clone().into()).into();
138        let public_point: ExplicitContextTag1<Option<BitStringAsn1>> = point.into();
139
140        let private_key = PrivateKeyValue::EC(
141            ECPrivateKey {
142                version: vec![1].into(),
143                private_key: secret,
144                parameters: parameters.into(),
145                public_key: public_point.into(),
146            }
147            .into(),
148        );
149
150        Self {
151            version: PRIVATE_KEY_INFO_VERSION_1,
152            private_key_algorithm: AlgorithmIdentifier::new_elliptic_curve(curve_oid.into()),
153            private_key,
154            public_key: None,
155        }
156    }
157
158    pub fn new_ed_encryption(
159        algorithm: ObjectIdentifier,
160        secret: impl Into<OctetStringAsn1>,
161        public_key: Option<BitString>,
162    ) -> Self {
163        let secret: OctetStringAsn1 = secret.into();
164
165        let (version, public_key) = if let Some(public_key) = public_key {
166            // If the public key is present, the version MUST be set to v2(1)
167            (
168                PRIVATE_KEY_INFO_VERSION_2,
169                Some(ExplicitContextTag1(Optional(public_key.into()))),
170            )
171        } else {
172            (PRIVATE_KEY_INFO_VERSION_1, None)
173        };
174
175        Self {
176            version,
177            private_key_algorithm: AlgorithmIdentifier::new_unchecked(algorithm, AlgorithmIdentifierParameters::None),
178            private_key: PrivateKeyValue::ED(secret.into()),
179            public_key,
180        }
181    }
182}
183
184impl<'de> de::Deserialize<'de> for PrivateKeyInfo {
185    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
186    where
187        D: de::Deserializer<'de>,
188    {
189        struct Visitor;
190
191        impl<'de> de::Visitor<'de> for Visitor {
192            type Value = PrivateKeyInfo;
193
194            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
195                formatter.write_str("a valid DER-encoded PrivateKeyInfo (pkcs8)")
196            }
197
198            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
199            where
200                A: de::SeqAccess<'de>,
201            {
202                let version = seq_next_element!(seq, PrivateKeyInfo, "version");
203                if version != 0 && version != 1 {
204                    return Err(serde_invalid_value!(
205                        PrivateKeyInfo,
206                        "unsupported version (valid versions: [v1(0), v2(1)])",
207                        "a supported PrivateKeyInfo"
208                    ));
209                }
210
211                let private_key_algorithm: AlgorithmIdentifier =
212                    seq_next_element!(seq, PrivateKeyInfo, "private key algorithm");
213
214                let private_key = if private_key_algorithm.is_a(oids::rsa_encryption()) {
215                    PrivateKeyValue::Rsa(seq_next_element!(seq, PrivateKeyInfo, "rsa oid"))
216                } else if matches!(private_key_algorithm.parameters(), AlgorithmIdentifierParameters::Ec(_)) {
217                    PrivateKeyValue::EC(seq_next_element!(seq, PrivateKeyInfo, "ec private key"))
218                } else if private_key_algorithm.is_one_of([oids::ed25519(), oids::x25519()]) {
219                    PrivateKeyValue::ED(seq_next_element!(seq, PrivateKeyInfo, "curve25519 private key"))
220                } else if private_key_algorithm.is_one_of([oids::ed448(), oids::x448()]) {
221                    PrivateKeyValue::ED(seq_next_element!(seq, PrivateKeyInfo, "curve448 private key"))
222                } else {
223                    return Err(serde_invalid_value!(
224                        PrivateKeyInfo,
225                        "unsupported algorithm",
226                        "a supported algorithm"
227                    ));
228                };
229
230                let mut last_tag = seq.next_element::<TagPeeker>()?;
231
232                if let Some(tag) = &last_tag {
233                    if tag.next_tag != ExplicitContextTag1::<BitStringAsn1>::TAG {
234                        // We found attributes, we don't support them yet so skip them
235                        last_tag = seq.next_element::<TagPeeker>()?;
236                    }
237                }
238
239                // OneAssymmetricKey has a public key field, but it's optional
240                let public_key = match last_tag {
241                    Some(tag) if tag.next_tag == ExplicitContextTag1::<BitStringAsn1>::TAG => {
242                        let public_key =
243                            seq_next_element!(seq, ExplicitContextTag1<BitStringAsn1>, PrivateKeyInfo, "BitStringAsn1");
244
245                        Some(ExplicitContextTag1(Optional(public_key.0)))
246                    }
247                    _ => None,
248                };
249
250                Ok(PrivateKeyInfo {
251                    version,
252                    private_key_algorithm,
253                    private_key,
254                    public_key,
255                })
256            }
257        }
258
259        deserializer.deserialize_seq(Visitor)
260    }
261}
262
263#[derive(Debug, PartialEq, Eq, Clone)]
264pub enum PrivateKeyValue {
265    Rsa(OctetStringAsn1Container<RsaPrivateKey>),
266    EC(OctetStringAsn1Container<ECPrivateKey>),
267    // Used by Ed25519, Ed448, X25519, and X448 keys
268    ED(OctetStringAsn1Container<OctetStringAsn1>),
269}
270
271impl ser::Serialize for PrivateKeyValue {
272    fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
273    where
274        S: ser::Serializer,
275    {
276        match self {
277            PrivateKeyValue::Rsa(rsa) => rsa.serialize(serializer),
278            PrivateKeyValue::EC(ec) => ec.serialize(serializer),
279            PrivateKeyValue::ED(ed) => ed.serialize(serializer),
280        }
281    }
282}
283
284#[cfg(feature = "zeroize")]
285impl Drop for PrivateKeyValue {
286    fn drop(&mut self) {
287        if let PrivateKeyValue::ED(ed) = self {
288            ed.0 .0.zeroize()
289        }
290    }
291}
292
293/// [PKCS #1: RSA Cryptography Specifications Version 2.2](https://tools.ietf.org/html/rfc8017.html#appendix-A.1.2)
294///
295/// # Section A.1.2
296///
297/// An RSA private key should be represented with the ASN.1 type RSAPrivateKey:
298///
299/// ```not_rust
300///      RSAPrivateKey ::= SEQUENCE {
301///          version           Version,
302///          modulus           INTEGER,  -- n
303///          publicExponent    INTEGER,  -- e
304///          privateExponent   INTEGER,  -- d
305///          prime1            INTEGER,  -- p
306///          prime2            INTEGER,  -- q
307///          exponent1         INTEGER,  -- d mod (p-1)
308///          exponent2         INTEGER,  -- d mod (q-1)
309///          coefficient       INTEGER,  -- (inverse of q) mod p
310///          otherPrimeInfos   OtherPrimeInfos OPTIONAL
311///      }
312/// ```
313#[derive(Serialize, Debug, Clone, PartialEq, Eq)]
314#[cfg_attr(not(feature = "legacy"), derive(Deserialize))]
315pub struct RsaPrivateKey {
316    pub version: IntegerAsn1,
317    pub modulus: IntegerAsn1,
318    pub public_exponent: IntegerAsn1,
319    pub private_exponent: IntegerAsn1,
320    pub prime_1: IntegerAsn1,
321    pub prime_2: IntegerAsn1,
322    pub exponent_1: IntegerAsn1,
323    pub exponent_2: IntegerAsn1,
324    pub coefficient: IntegerAsn1,
325}
326
327#[cfg(feature = "zeroize")]
328impl Drop for RsaPrivateKey {
329    fn drop(&mut self) {
330        self.private_exponent.zeroize();
331    }
332}
333
334#[cfg(feature = "legacy")]
335impl<'de> de::Deserialize<'de> for RsaPrivateKey {
336    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
337    where
338        D: de::Deserializer<'de>,
339    {
340        struct Visitor;
341
342        impl<'de> de::Visitor<'de> for Visitor {
343            type Value = RsaPrivateKey;
344
345            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
346                formatter.write_str("struct RSAPrivateKey with 6 or 9 elements")
347            }
348
349            fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
350            where
351                V: de::SeqAccess<'de>,
352            {
353                let version: IntegerAsn1 = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(0, &self))?;
354                let modulus: IntegerAsn1 = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(1, &self))?;
355                let public_exponent: IntegerAsn1 =
356                    seq.next_element()?.ok_or_else(|| de::Error::invalid_length(2, &self))?;
357                let private_exponent: IntegerAsn1 =
358                    seq.next_element()?.ok_or_else(|| de::Error::invalid_length(3, &self))?;
359                let prime_1: IntegerAsn1 = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(4, &self))?;
360                let prime_2: IntegerAsn1 = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(5, &self))?;
361
362                let (exponent_1, exponent_2, coefficient) = if let Some(exponent_1) = seq.next_element()? {
363                    let exponent_2 = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(7, &self))?;
364                    let coefficient = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(8, &self))?;
365                    (exponent_1, exponent_2, coefficient)
366                } else {
367                    use num_bigint_dig::{BigUint, ModInverse};
368
369                    // conversion to num_bigint_dig format BigUint
370                    let private_exponent = BigUint::from_bytes_be(private_exponent.as_unsigned_bytes_be());
371                    let prime_1 = BigUint::from_bytes_be(prime_1.as_unsigned_bytes_be());
372                    let prime_2 = BigUint::from_bytes_be(prime_2.as_unsigned_bytes_be());
373
374                    let exponent_1 = &private_exponent % (&prime_1 - 1u8);
375                    let exponent_2 = &private_exponent % (&prime_2 - 1u8);
376
377                    let coefficient = prime_2
378                        .mod_inverse(prime_1)
379                        .ok_or_else(|| {
380                            de::Error::invalid_value(
381                                de::Unexpected::Other("[RSAPrivateKey] no modular inverse for prime 1"),
382                                &"an invertible prime 1 value",
383                            )
384                        })?
385                        .to_biguint()
386                        .ok_or_else(|| {
387                            de::Error::invalid_value(
388                                de::Unexpected::Other("[RSAPrivateKey] BigUint conversion failed"),
389                                &"a valid prime 1 value",
390                            )
391                        })?;
392
393                    // conversion to IntegerAsn1
394                    let exponent_1 = IntegerAsn1::from_bytes_be_unsigned(exponent_1.to_bytes_be());
395                    let exponent_2 = IntegerAsn1::from_bytes_be_unsigned(exponent_2.to_bytes_be());
396                    let coefficient = IntegerAsn1::from_bytes_be_unsigned(coefficient.to_bytes_be());
397
398                    (exponent_1, exponent_2, coefficient)
399                };
400
401                Ok(RsaPrivateKey {
402                    version,
403                    modulus,
404                    public_exponent,
405                    private_exponent,
406                    prime_1,
407                    prime_2,
408                    exponent_1,
409                    exponent_2,
410                    coefficient,
411                })
412            }
413        }
414
415        deserializer.deserialize_seq(Visitor)
416    }
417}
418
419impl RsaPrivateKey {
420    #[deprecated(note = "field is now public")]
421    pub fn modulus(&self) -> &IntegerAsn1 {
422        &self.modulus
423    }
424
425    #[deprecated(note = "field is now public")]
426    pub fn public_exponent(&self) -> &IntegerAsn1 {
427        &self.public_exponent
428    }
429
430    #[deprecated(note = "field is now public")]
431    pub fn private_exponent(&self) -> &IntegerAsn1 {
432        &self.private_exponent
433    }
434
435    #[deprecated(note = "field is now public")]
436    pub fn prime_1(&self) -> &IntegerAsn1 {
437        &self.prime_1
438    }
439
440    #[deprecated(note = "field is now public")]
441    pub fn prime_2(&self) -> &IntegerAsn1 {
442        &self.prime_2
443    }
444
445    #[deprecated(note = "field is now public")]
446    pub fn primes(&self) -> (&IntegerAsn1, &IntegerAsn1) {
447        (&self.prime_1, &self.prime_2)
448    }
449
450    #[deprecated(note = "field is now public")]
451    pub fn exponent_1(&self) -> &IntegerAsn1 {
452        &self.exponent_1
453    }
454
455    #[deprecated(note = "field is now public")]
456    pub fn exponent_2(&self) -> &IntegerAsn1 {
457        &self.exponent_2
458    }
459
460    #[deprecated(note = "field is now public")]
461    pub fn exponents(&self) -> (&IntegerAsn1, &IntegerAsn1) {
462        (&self.exponent_1, &self.exponent_2)
463    }
464
465    #[deprecated(note = "field is now public")]
466    pub fn coefficient(&self) -> &IntegerAsn1 {
467        &self.coefficient
468    }
469
470    #[deprecated(note = "field is now public")]
471    pub fn into_public_components(mut self) -> (IntegerAsn1, IntegerAsn1) {
472        (
473            std::mem::take(&mut self.modulus),
474            std::mem::take(&mut self.public_exponent),
475        )
476    }
477}
478
479/// [Elliptic Curve Private Key Structure](https://datatracker.ietf.org/doc/html/rfc5915#section-3)
480///
481/// EC private key information SHALL have ASN.1 type ECPrivateKey:
482///
483/// ```not_rust
484/// ECPrivateKey ::= SEQUENCE {
485///      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
486///      privateKey     OCTET STRING,
487///      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
488///      publicKey  [1] BIT STRING OPTIONAL
489///    }
490/// ```
491#[derive(Serialize, Debug, Clone, PartialEq, Eq)]
492pub struct ECPrivateKey {
493    pub version: IntegerAsn1,
494    pub private_key: EncapsulatedEcSecret,
495    #[serde(skip_serializing_if = "Optional::is_default")]
496    pub parameters: Optional<ExplicitContextTag0<Option<EcParameters>>>,
497    #[serde(skip_serializing_if = "Optional::is_default")]
498    pub public_key: Optional<ExplicitContextTag1<Option<EncapsulatedEcPoint>>>,
499}
500
501impl<'de> serde::Deserialize<'de> for ECPrivateKey {
502    fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
503    where
504        D: de::Deserializer<'de>,
505    {
506        struct Visitor;
507
508        impl<'de> de::Visitor<'de> for Visitor {
509            type Value = ECPrivateKey;
510
511            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
512                formatter.write_str("a valid DER-encoded PrivateKeyInfo (pkcs8)")
513            }
514
515            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
516            where
517                A: de::SeqAccess<'de>,
518            {
519                let version: IntegerAsn1 = seq_next_element!(seq, IntegerAsn1, "IntegerAsn1");
520                if version.0 != [1] {
521                    return Err(serde_invalid_value!(
522                        ECPrivateKey,
523                        "ECPrivateKey's version is not 1",
524                        "ECPrivateKey's version equals to 1"
525                    ));
526                }
527
528                let private_key = seq_next_element!(seq, OctetStringAsn1, "OctetStringAsn1");
529
530                let mut ec_private_key = ECPrivateKey {
531                    version,
532                    private_key,
533                    parameters: Optional::default(),
534                    public_key: Optional::default(),
535                };
536
537                let mut last_tag = seq.next_element::<TagPeeker>()?;
538
539                if let Some(tag) = &last_tag {
540                    if tag.next_tag == ExplicitContextTag0::<EcParameters>::TAG {
541                        let parameters =
542                            seq_next_element!(seq, ExplicitContextTag0<EcParameters>, ECPrivateKey, "EcParameters");
543
544                        ec_private_key.parameters = Optional(ExplicitContextTag0(Some(parameters.0)));
545
546                        // Query next tag, as we still could encounter public key tag
547                        last_tag = seq.next_element::<TagPeeker>()?;
548                    }
549                }
550
551                if let Some(tag) = last_tag {
552                    if tag.next_tag == ExplicitContextTag1::<BitStringAsn1>::TAG {
553                        let public_key =
554                            seq_next_element!(seq, ExplicitContextTag1<BitStringAsn1>, ECPrivateKey, "BitStringAsn1");
555
556                        ec_private_key.public_key = Optional(ExplicitContextTag1(Some(public_key.0)));
557                    }
558                }
559
560                Ok(ec_private_key)
561            }
562        }
563
564        deserializer.deserialize_seq(Visitor)
565    }
566}
567
568#[cfg(feature = "zeroize")]
569impl Drop for ECPrivateKey {
570    fn drop(&mut self) {
571        self.private_key.zeroize();
572    }
573}
574
575#[cfg(test)]
576mod tests {
577    use super::*;
578    use base64::{engine::general_purpose, Engine as _};
579    use picky_asn1::bit_string::BitString;
580
581    #[test]
582    fn pkcs_8_private_key() {
583        let encoded = general_purpose::STANDARD
584            .decode(
585                "MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEAq7BFUpkGp3+LQmlQ\
586             Yx2eqzDV+xeG8kx/sQFV18S5JhzGeIJNA72wSeukEPojtqUyX2J0CciPBh7eqclQ\
587             2zpAswIDAQABAkAgisq4+zRdrzkwH1ITV1vpytnkO/NiHcnePQiOW0VUybPyHoGM\
588             /jf75C5xET7ZQpBe5kx5VHsPZj0CBb3b+wSRAiEA2mPWCBytosIU/ODRfq6EiV04\
589             lt6waE7I2uSPqIC20LcCIQDJQYIHQII+3YaPqyhGgqMexuuuGx+lDKD6/Fu/JwPb\
590             5QIhAKthiYcYKlL9h8bjDsQhZDUACPasjzdsDEdq8inDyLOFAiEAmCr/tZwA3qeA\
591             ZoBzI10DGPIuoKXBd3nk/eBxPkaxlEECIQCNymjsoI7GldtujVnr1qT+3yedLfHK\
592             srDVjIT3LsvTqw==",
593            )
594            .expect("invalid base64");
595
596        let modulus = IntegerAsn1::from(encoded[35..100].to_vec());
597        let public_exponent = IntegerAsn1::from(encoded[102..105].to_vec());
598        let private_exponent = IntegerAsn1::from(encoded[107..171].to_vec());
599        let prime_1 = IntegerAsn1::from(encoded[173..206].to_vec());
600        let prime_2 = IntegerAsn1::from(encoded[208..241].to_vec());
601        let exponent_1 = IntegerAsn1::from(encoded[243..276].to_vec());
602        let exponent_2 = IntegerAsn1::from(encoded[278..311].to_vec());
603        let coefficient = IntegerAsn1::from(encoded[313..346].to_vec());
604
605        let private_key = PrivateKeyInfo::new_rsa_encryption(
606            modulus,
607            public_exponent,
608            private_exponent,
609            (prime_1, prime_2),
610            (exponent_1, exponent_2),
611            coefficient,
612        );
613        check_serde!(private_key: PrivateKeyInfo in encoded);
614    }
615
616    #[test]
617    #[cfg(feature = "legacy")]
618    fn old_broken_key_legacy_support() {
619        // Version previous to picky-asn1-x509 6.0.0 could generate weird keys with negative values
620        // https://github.com/Devolutions/picky-rs/issues/53
621        // We want to support these for now.
622
623        let encoded = general_purpose::STANDARD
624            .decode(
625                "MIIDMAIBADANBgkqhkiG9w0BAQEFAASCAxowggMWAgEAAoIBAOB9jOJvCkMHOc98Q\
626             GPFikxAvBKANkme5f/nNuNnEnbefoKDFkS6ElfqASAAkIHxUREnRvBTTa6b+qba/0\
627             DhBuXsYGCl8VF0pUE4JGujv1HIi5aRCar0WmY66s7DJ4uR3Nk9Jy0WeRiH4yyzEIG\
628             8+6QDu4d/U6slWTmE8eZtQEE7rz4FGpQU9OhrGM3xJOIIbLX/xU2SFt83Xs3JREEt\
629             bfrXQpSxAHmtwvlBKpeZacrcobm6eQKsoI2MIg3LFvoHs0+40dadm14ngpgwx4qqk\
630             bG34jvWH13OhHRweFGNkQpcg99rlzZYkCM13e9EcmirQ9XYHuB5pHS31eznolZKbx\
631             cCAwEAAQKCAQCrPFlopxaGxk48jCR5dkbln0NWQWInigMazf06PHcDIPgTCXbE+cH\
632             gOWieRo/z7mTN1s3vpztMA0KQX9/wVzVx0Ho7fpiyb21WcEKnsIHRGk4PjZZ4Rmdm\
633             L27IRGg3uA1jz5fAdrHsGksY34Wp0MOJ+ibjViY2GAkVLOlvwMoQds6eNIGO88T5O\
634             fcmvutjK43ObU1vgx2ptTaLNAVczEE5VHqcLx4GZPv6k71afOQfIDQerIpsGb4gvr\
635             1JdwYKb4z02z2SaNIA3Vly0q5s4r8uU36eg9z65utu93M7zI7f8/MX2byZ2Jz4b3T\
636             nH10FURmbPoNQH/O2T0TbtT4M1y0xAoGA72JW0IcFxze7j7PPaP6cQN1IXvFDZUFF\
637             dZHqFI8+4VPcv3EKTs+iQflM7pqtRuEWtwonIn3f7CGOx317uKwpVsZvfnDhXCUPJ\
638             Q3pns7KgaROGXyruFFQ9gl6XsXGK02Wop9nX0/iRK3ruwZ4uJwDioEYcvGw+ocqAc\
639             yOdodNnpUCgYDwEo/sPJNaPOzc7fpaQr2PUUJ3ksL0ncGRO2h1JGYgDtWe5u1srSI\
640             DlpM2NdYSZyT04ebOF2SqNUBwY3LB1tPOFnjYwCutp4c75OYhOor7TodZHlzt3GeQ\
641             ntUw6XbHX0ohTgs4u2NXwOTq5yKeW4VYzuevN5ksF8GoW2noalpn+w==",
642            )
643            .unwrap();
644
645        picky_asn1_der::from_bytes::<PrivateKeyInfo>(&encoded).unwrap();
646    }
647
648    #[test]
649    fn decode_ec_key() {
650        let decoded = general_purpose::STANDARD
651            .decode(
652                "\
653        MIHcAgEBBEIBhqphIGu2PmlcEb6xADhhSCpgPUulB0s4L2qOgolRgaBx4fNgINFE\
654        mBsSyHJncsWG8WFEuUzAYy/YKz2lP0Qx6Z2gBwYFK4EEACOhgYkDgYYABABwBevJ\
655        w/+Xh6I98ruzoTX3MNTsbgnc+glenJRCbEJkjbJrObFhbfgqP52r1lAy2RxuShGi\
656        NYJJzNPT6vR1abS32QFtvTH7YbYa6OWk9dtGNY/cYxgx1nQyhUuofdW7qbbfu/Ww\
657        TP2oFsPXRAavZCh4AbWUn8bAHmzNRyuJonQBKlQlVQ==",
658            )
659            .unwrap();
660
661        let ec_key = ECPrivateKey {
662            version: IntegerAsn1([1].into()),
663            private_key: OctetStringAsn1::from(decoded[8..74].to_vec()),
664            parameters: ExplicitContextTag0(Some(EcParameters::NamedCurve(oids::secp521r1().into()))).into(),
665            public_key: Optional(ExplicitContextTag1(Some(
666                BitString::with_bytes(decoded[90..].to_vec()).into(),
667            ))),
668        };
669
670        check_serde!(ec_key: ECPrivateKey in decoded);
671    }
672
673    #[test]
674    fn decode_pkcs8_ec_key() {
675        let decoded = general_purpose::STANDARD.decode("MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgKZqrmOg/cDZ4tPCn\
676                                                            4LROs145nxx+ssufvflL8cROxFmhRANCAARmU90fCSTsncefY7hVeKw1WIg/YQmT\
677                                                            4DGJ7nJPZ+WXAd/xxp4c0bHGlIOju/U95ITPN9dAmro7OUTDJpz+rzGW").unwrap();
678        let expected_pkcs8_ec_key = PrivateKeyInfo {
679            version: 0,
680            private_key_algorithm: AlgorithmIdentifier::new_elliptic_curve(EcParameters::NamedCurve(
681                oids::secp256r1().into(),
682            )),
683            private_key: PrivateKeyValue::EC(OctetStringAsn1Container(ECPrivateKey {
684                version: IntegerAsn1([1].into()),
685                private_key: OctetStringAsn1(decoded[36..68].to_vec()),
686                parameters: Optional(Default::default()),
687                public_key: Optional(ExplicitContextTag1(Some(
688                    BitString::with_bytes(decoded[73..].to_vec()).into(),
689                ))),
690            })),
691            public_key: None,
692        };
693
694        check_serde!(expected_pkcs8_ec_key: PrivateKeyInfo in decoded);
695    }
696}