sec1/
private_key.rs
1use crate::{EcParameters, Error, Result};
9use core::fmt;
10use der::{
11 asn1::{BitStringRef, ContextSpecific, OctetStringRef},
12 Decode, DecodeValue, Encode, Header, Reader, Sequence, Tag, TagMode, TagNumber,
13};
14
15#[cfg(feature = "alloc")]
16use der::SecretDocument;
17
18#[cfg(feature = "pem")]
19use der::pem::PemLabel;
20
21const VERSION: u8 = 1;
31
32const EC_PARAMETERS_TAG: TagNumber = TagNumber::new(0);
34
35const PUBLIC_KEY_TAG: TagNumber = TagNumber::new(1);
37
38#[derive(Clone)]
61#[cfg_attr(docsrs, doc(cfg(feature = "der")))]
62pub struct EcPrivateKey<'a> {
63 pub private_key: &'a [u8],
65
66 pub parameters: Option<EcParameters>,
68
69 pub public_key: Option<&'a [u8]>,
71}
72
73impl<'a> DecodeValue<'a> for EcPrivateKey<'a> {
74 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
75 reader.read_nested(header.length, |reader| {
76 if u8::decode(reader)? != VERSION {
77 return Err(der::Tag::Integer.value_error());
78 }
79
80 let private_key = OctetStringRef::decode(reader)?.as_bytes();
81 let parameters = reader.context_specific(EC_PARAMETERS_TAG, TagMode::Explicit)?;
82 let public_key = reader
83 .context_specific::<BitStringRef<'_>>(PUBLIC_KEY_TAG, TagMode::Explicit)?
84 .map(|bs| bs.as_bytes().ok_or_else(|| Tag::BitString.value_error()))
85 .transpose()?;
86
87 Ok(EcPrivateKey {
88 private_key,
89 parameters,
90 public_key,
91 })
92 })
93 }
94}
95
96impl<'a> Sequence<'a> for EcPrivateKey<'a> {
97 fn fields<F, T>(&self, f: F) -> der::Result<T>
98 where
99 F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
100 {
101 f(&[
102 &VERSION,
103 &OctetStringRef::new(self.private_key)?,
104 &self.parameters.as_ref().map(|params| ContextSpecific {
105 tag_number: EC_PARAMETERS_TAG,
106 tag_mode: TagMode::Explicit,
107 value: *params,
108 }),
109 &self
110 .public_key
111 .map(|pk| {
112 BitStringRef::from_bytes(pk).map(|value| ContextSpecific {
113 tag_number: PUBLIC_KEY_TAG,
114 tag_mode: TagMode::Explicit,
115 value,
116 })
117 })
118 .transpose()?,
119 ])
120 }
121}
122
123impl<'a> TryFrom<&'a [u8]> for EcPrivateKey<'a> {
124 type Error = Error;
125
126 fn try_from(bytes: &'a [u8]) -> Result<EcPrivateKey<'a>> {
127 Ok(Self::from_der(bytes)?)
128 }
129}
130
131impl<'a> fmt::Debug for EcPrivateKey<'a> {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 f.debug_struct("EcPrivateKey")
134 .field("parameters", &self.parameters)
135 .field("public_key", &self.public_key)
136 .finish_non_exhaustive()
137 }
138}
139
140#[cfg(feature = "alloc")]
141#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
142impl TryFrom<EcPrivateKey<'_>> for SecretDocument {
143 type Error = Error;
144
145 fn try_from(private_key: EcPrivateKey<'_>) -> Result<Self> {
146 SecretDocument::try_from(&private_key)
147 }
148}
149
150#[cfg(feature = "alloc")]
151#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
152impl TryFrom<&EcPrivateKey<'_>> for SecretDocument {
153 type Error = Error;
154
155 fn try_from(private_key: &EcPrivateKey<'_>) -> Result<Self> {
156 Ok(Self::encode_msg(private_key)?)
157 }
158}
159
160#[cfg(feature = "pem")]
161#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
162impl PemLabel for EcPrivateKey<'_> {
163 const PEM_LABEL: &'static str = "EC PRIVATE KEY";
164}