x509_certificate/
rfc5958.rs1use {
8 crate::{rfc5280::AlgorithmIdentifier, rfc5652::Attribute, rfc5915::EcPrivateKey},
9 bcder::{
10 decode::{Constructed, DecodeError, IntoSource, Source},
11 encode::{self, PrimitiveContent, Values},
12 BitString, Integer, Mode, OctetString, Tag,
13 },
14 std::ops::{Deref, DerefMut},
15};
16
17#[derive(Clone, Debug, Eq, PartialEq)]
31pub struct OneAsymmetricKey {
32 pub version: Version,
33 pub private_key_algorithm: PrivateKeyAlgorithmIdentifier,
34 pub private_key: PrivateKey,
35 pub attributes: Option<Attributes>,
36 pub public_key: Option<PublicKey>,
37}
38
39impl OneAsymmetricKey {
40 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
41 cons.take_sequence(|cons| {
42 let version = Version::take_from(cons)?;
43 let private_key_algorithm = PrivateKeyAlgorithmIdentifier::take_from(cons)?;
44 let private_key = PrivateKey::take_from(cons)?;
45 let attributes = cons.take_opt_constructed_if(Tag::CTX_0, |cons| {
46 let mut attributes = Attributes::default();
47
48 while let Some(attribute) = Attribute::take_opt_from(cons)? {
49 attributes.push(attribute);
50 }
51
52 Ok(attributes)
53 })?;
54
55 let public_key = cons.take_opt_value_if(Tag::CTX_1, |c| BitString::from_content(c))?;
59
60 Ok(Self {
61 version,
62 private_key_algorithm,
63 private_key,
64 attributes,
65 public_key,
66 })
67 })
68 }
69
70 pub fn encode_ref(&self) -> impl Values + '_ {
71 encode::sequence((
72 self.version.encode(),
73 &self.private_key_algorithm,
74 self.private_key.encode_ref(),
75 self.attributes
76 .as_ref()
77 .map(|attrs| attrs.encode_ref_as(Tag::CTX_0)),
78 self.public_key
79 .as_ref()
80 .map(|public_key| public_key.encode_ref()),
81 ))
82 }
83}
84
85#[derive(Clone, Copy, Debug, Eq, PartialEq)]
91pub enum Version {
92 V1 = 0,
93 V2 = 1,
94}
95
96impl Version {
97 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
98 match cons.take_primitive_if(Tag::INTEGER, Integer::i8_from_primitive)? {
99 0 => Ok(Self::V1),
100 1 => Ok(Self::V2),
101 _ => Err(cons.content_err("unexpected Version value")),
102 }
103 }
104
105 pub fn encode(self) -> impl Values {
106 u8::from(self).encode()
107 }
108}
109
110impl From<Version> for u8 {
111 fn from(v: Version) -> u8 {
112 match v {
113 Version::V1 => 0,
114 Version::V2 => 1,
115 }
116 }
117}
118
119pub type PrivateKey = OctetString;
123
124impl TryFrom<&PrivateKey> for EcPrivateKey {
125 type Error = DecodeError<std::convert::Infallible>;
126
127 fn try_from(v: &PrivateKey) -> Result<Self, Self::Error> {
128 let source = v.clone().into_source();
129
130 Constructed::decode(
131 v.as_slice()
132 .ok_or_else(|| source.content_err("missing private key data"))?,
133 Mode::Der,
134 EcPrivateKey::take_from,
135 )
136 }
137}
138
139pub type PublicKey = BitString;
141
142pub type PrivateKeyAlgorithmIdentifier = AlgorithmIdentifier;
144
145#[derive(Clone, Debug, Default, Eq, PartialEq)]
151pub struct Attributes(Vec<Attribute>);
152
153impl Deref for Attributes {
154 type Target = Vec<Attribute>;
155
156 fn deref(&self) -> &Self::Target {
157 &self.0
158 }
159}
160
161impl DerefMut for Attributes {
162 fn deref_mut(&mut self) -> &mut Self::Target {
163 &mut self.0
164 }
165}
166
167impl Attributes {
168 pub fn encode_ref_as(&self, tag: Tag) -> impl Values + '_ {
169 encode::set_as(tag, encode::slice(&self.0, |x| x.clone().encode()))
170 }
171}
172
173#[cfg(test)]
174mod test {
175 use {super::*, bcder::Mode};
176
177 #[test]
178 fn parse_generated_cert() {
179 let rng = ring::rand::SystemRandom::new();
180
181 let doc = ring::signature::EcdsaKeyPair::generate_pkcs8(
182 &ring::signature::ECDSA_P256_SHA256_ASN1_SIGNING,
183 &rng,
184 )
185 .unwrap();
186
187 ring::signature::EcdsaKeyPair::from_pkcs8(
188 &ring::signature::ECDSA_P256_SHA256_ASN1_SIGNING,
189 doc.as_ref(),
190 &ring::rand::SystemRandom::new(),
191 )
192 .unwrap();
193
194 let key = Constructed::decode(doc.as_ref(), Mode::Der, |cons| {
195 OneAsymmetricKey::take_from(cons)
196 })
197 .unwrap();
198
199 let private_key = EcPrivateKey::try_from(&key.private_key).unwrap();
200 assert_eq!(private_key.version, Integer::from(1));
201 assert!(private_key.parameters.is_none());
202 }
203}