Skip to main content

elliptic_curve/secret_key/
pkcs8.rs

1//! PKCS#8 encoding/decoding support.
2
3use super::SecretKey;
4use crate::{
5    ALGORITHM_OID, Curve, FieldBytesSize,
6    pkcs8::{AssociatedOid, der::Decode},
7    sec1::{ModulusSize, ValidatePublicKey},
8};
9use pkcs8::spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier, ObjectIdentifier};
10use sec1::EcPrivateKey;
11
12// Imports for the `EncodePrivateKey` impl
13#[cfg(all(feature = "alloc", feature = "arithmetic"))]
14use {
15    crate::{
16        AffinePoint, CurveArithmetic,
17        sec1::{FromSec1Point, ToSec1Point},
18    },
19    pkcs8::{
20        EncodePrivateKey,
21        der::{self, Encode, asn1::OctetStringRef},
22    },
23    zeroize::Zeroizing,
24};
25
26// Imports for actual PEM support
27#[cfg(feature = "pem")]
28use {
29    crate::{Result, error::Error},
30    core::str::FromStr,
31    pkcs8::DecodePrivateKey,
32};
33
34impl<C> AssociatedAlgorithmIdentifier for SecretKey<C>
35where
36    C: AssociatedOid + Curve,
37{
38    type Params = ObjectIdentifier;
39
40    const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<ObjectIdentifier> = AlgorithmIdentifier {
41        oid: ALGORITHM_OID,
42        parameters: Some(C::OID),
43    };
44}
45
46impl<C> TryFrom<pkcs8::PrivateKeyInfoRef<'_>> for SecretKey<C>
47where
48    C: AssociatedOid + Curve + ValidatePublicKey,
49    FieldBytesSize<C>: ModulusSize,
50{
51    type Error = pkcs8::Error;
52
53    fn try_from(private_key_info: pkcs8::PrivateKeyInfoRef<'_>) -> pkcs8::Result<Self> {
54        private_key_info
55            .algorithm
56            .assert_oids(ALGORITHM_OID, C::OID)?;
57
58        Ok(EcPrivateKey::from_der(private_key_info.private_key.as_bytes())?.try_into()?)
59    }
60}
61
62#[cfg(all(feature = "alloc", feature = "arithmetic"))]
63impl<C> EncodePrivateKey for SecretKey<C>
64where
65    C: AssociatedOid + CurveArithmetic,
66    AffinePoint<C>: FromSec1Point<C> + ToSec1Point<C>,
67    FieldBytesSize<C>: ModulusSize,
68{
69    fn to_pkcs8_der(&self) -> pkcs8::Result<der::SecretDocument> {
70        let algorithm_identifier = pkcs8::AlgorithmIdentifierRef {
71            oid: ALGORITHM_OID,
72            parameters: Some((&C::OID).into()),
73        };
74
75        let private_key_bytes = Zeroizing::new(self.to_bytes());
76        let public_key_bytes = self.public_key().to_sec1_point(false);
77
78        let ec_private_key = Zeroizing::new(
79            EcPrivateKey {
80                private_key: &private_key_bytes,
81                parameters: None,
82                public_key: Some(public_key_bytes.as_bytes()),
83            }
84            .to_der()?,
85        );
86
87        let pkcs8_key = pkcs8::PrivateKeyInfoRef::new(
88            algorithm_identifier,
89            OctetStringRef::new(&ec_private_key)?,
90        );
91        Ok(der::SecretDocument::encode_msg(&pkcs8_key)?)
92    }
93}
94
95#[cfg(feature = "pem")]
96impl<C> FromStr for SecretKey<C>
97where
98    C: Curve + AssociatedOid + ValidatePublicKey,
99    FieldBytesSize<C>: ModulusSize,
100{
101    type Err = Error;
102
103    fn from_str(s: &str) -> Result<Self> {
104        Self::from_pkcs8_pem(s).map_err(|_| Error)
105    }
106}