1use crate::Result;
4
5#[cfg(feature = "alloc")]
6use der::SecretDocument;
7
8#[cfg(feature = "pem")]
9use {crate::LineEnding, alloc::string::String, der::pem::PemLabel};
10
11#[cfg(feature = "pkcs8")]
12use {
13 crate::{EcPrivateKey, ALGORITHM_OID},
14 der::Decode,
15};
16
17#[cfg(feature = "std")]
18use std::path::Path;
19
20#[cfg(feature = "pem")]
21use zeroize::Zeroizing;
22
23pub trait DecodeEcPrivateKey: Sized {
25 fn from_sec1_der(bytes: &[u8]) -> Result<Self>;
28
29 #[cfg(feature = "pem")]
37 fn from_sec1_pem(s: &str) -> Result<Self> {
38 let (label, doc) = SecretDocument::from_pem(s)?;
39 EcPrivateKey::validate_pem_label(label)?;
40 Self::from_sec1_der(doc.as_bytes())
41 }
42
43 #[cfg(feature = "std")]
46 fn read_sec1_der_file(path: impl AsRef<Path>) -> Result<Self> {
47 Self::from_sec1_der(SecretDocument::read_der_file(path)?.as_bytes())
48 }
49
50 #[cfg(all(feature = "pem", feature = "std"))]
52 fn read_sec1_pem_file(path: impl AsRef<Path>) -> Result<Self> {
53 let (label, doc) = SecretDocument::read_pem_file(path)?;
54 EcPrivateKey::validate_pem_label(&label)?;
55 Self::from_sec1_der(doc.as_bytes())
56 }
57}
58
59#[cfg(feature = "alloc")]
61pub trait EncodeEcPrivateKey {
62 fn to_sec1_der(&self) -> Result<SecretDocument>;
64
65 #[cfg(feature = "pem")]
69 fn to_sec1_pem(&self, line_ending: LineEnding) -> Result<Zeroizing<String>> {
70 let doc = self.to_sec1_der()?;
71 Ok(doc.to_pem(EcPrivateKey::PEM_LABEL, line_ending)?)
72 }
73
74 #[cfg(feature = "std")]
76 fn write_sec1_der_file(&self, path: impl AsRef<Path>) -> Result<()> {
77 Ok(self.to_sec1_der()?.write_der_file(path)?)
78 }
79
80 #[cfg(all(feature = "pem", feature = "std"))]
82 fn write_sec1_pem_file(&self, path: impl AsRef<Path>, line_ending: LineEnding) -> Result<()> {
83 let doc = self.to_sec1_der()?;
84 Ok(doc.write_pem_file(path, EcPrivateKey::PEM_LABEL, line_ending)?)
85 }
86}
87
88#[cfg(feature = "pkcs8")]
89impl<T> DecodeEcPrivateKey for T
90where
91 T: for<'a> TryFrom<pkcs8::PrivateKeyInfo<'a>, Error = pkcs8::Error>,
92{
93 fn from_sec1_der(private_key: &[u8]) -> Result<Self> {
94 let params_oid = EcPrivateKey::from_der(private_key)?
95 .parameters
96 .and_then(|params| params.named_curve());
97
98 let algorithm = pkcs8::AlgorithmIdentifierRef {
99 oid: ALGORITHM_OID,
100 parameters: params_oid.as_ref().map(Into::into),
101 };
102
103 Ok(Self::try_from(pkcs8::PrivateKeyInfo {
104 algorithm,
105 private_key,
106 public_key: None,
107 })?)
108 }
109}
110
111#[cfg(all(feature = "alloc", feature = "pkcs8"))]
112impl<T: pkcs8::EncodePrivateKey> EncodeEcPrivateKey for T {
113 fn to_sec1_der(&self) -> Result<SecretDocument> {
114 let doc = self.to_pkcs8_der()?;
115 let pkcs8_key = pkcs8::PrivateKeyInfo::from_der(doc.as_bytes())?;
116 pkcs8_key.algorithm.assert_algorithm_oid(ALGORITHM_OID)?;
117
118 let mut pkcs1_key = EcPrivateKey::from_der(pkcs8_key.private_key)?;
119 pkcs1_key.parameters = Some(pkcs8_key.algorithm.parameters_oid()?.into());
120 pkcs1_key.try_into()
121 }
122}