jsonwebtoken/pem/
decoder.rs1use crate::errors::{ErrorKind, Result};
2
3#[derive(Debug, PartialEq)]
5enum PemType {
6 EcPublic,
7 EcPrivate,
8 RsaPublic,
9 RsaPrivate,
10 EdPublic,
11 EdPrivate,
12}
13
14#[derive(Debug, PartialEq)]
15enum Standard {
16 Pkcs1,
18 Pkcs8,
20}
21
22#[derive(Debug, PartialEq)]
23enum Classification {
24 Ec,
25 Ed,
26 Rsa,
27}
28
29#[derive(Debug)]
44pub(crate) struct PemEncodedKey {
45 content: Vec<u8>,
46 asn1: Vec<simple_asn1::ASN1Block>,
47 pem_type: PemType,
48 standard: Standard,
49}
50
51impl PemEncodedKey {
52 pub fn new(input: &[u8]) -> Result<PemEncodedKey> {
54 match pem::parse(input) {
55 Ok(content) => {
56 let pem_contents = content.contents;
57 let asn1_content = match simple_asn1::from_der(pem_contents.as_slice()) {
58 Ok(asn1) => asn1,
59 Err(_) => return Err(ErrorKind::InvalidKeyFormat.into()),
60 };
61
62 match content.tag.as_ref() {
63 "RSA PRIVATE KEY" => Ok(PemEncodedKey {
65 content: pem_contents,
66 asn1: asn1_content,
67 pem_type: PemType::RsaPrivate,
68 standard: Standard::Pkcs1,
69 }),
70 "RSA PUBLIC KEY" => Ok(PemEncodedKey {
71 content: pem_contents,
72 asn1: asn1_content,
73 pem_type: PemType::RsaPublic,
74 standard: Standard::Pkcs1,
75 }),
76
77 tag @ "PRIVATE KEY" | tag @ "PUBLIC KEY" | tag @ "CERTIFICATE" => {
83 match classify_pem(&asn1_content) {
84 Some(c) => {
85 let is_private = tag == "PRIVATE KEY";
86 let pem_type = match c {
87 Classification::Ec => {
88 if is_private {
89 PemType::EcPrivate
90 } else {
91 PemType::EcPublic
92 }
93 }
94 Classification::Ed => {
95 if is_private {
96 PemType::EdPrivate
97 } else {
98 PemType::EdPublic
99 }
100 }
101 Classification::Rsa => {
102 if is_private {
103 PemType::RsaPrivate
104 } else {
105 PemType::RsaPublic
106 }
107 }
108 };
109 Ok(PemEncodedKey {
110 content: pem_contents,
111 asn1: asn1_content,
112 pem_type,
113 standard: Standard::Pkcs8,
114 })
115 }
116 None => Err(ErrorKind::InvalidKeyFormat.into()),
117 }
118 }
119
120 _ => Err(ErrorKind::InvalidKeyFormat.into()),
122 }
123 }
124 Err(_) => Err(ErrorKind::InvalidKeyFormat.into()),
125 }
126 }
127
128 pub fn as_ec_private_key(&self) -> Result<&[u8]> {
130 match self.standard {
131 Standard::Pkcs1 => Err(ErrorKind::InvalidKeyFormat.into()),
132 Standard::Pkcs8 => match self.pem_type {
133 PemType::EcPrivate => Ok(self.content.as_slice()),
134 _ => Err(ErrorKind::InvalidKeyFormat.into()),
135 },
136 }
137 }
138
139 pub fn as_ec_public_key(&self) -> Result<&[u8]> {
141 match self.standard {
142 Standard::Pkcs1 => Err(ErrorKind::InvalidKeyFormat.into()),
143 Standard::Pkcs8 => match self.pem_type {
144 PemType::EcPublic => extract_first_bitstring(&self.asn1),
145 _ => Err(ErrorKind::InvalidKeyFormat.into()),
146 },
147 }
148 }
149
150 pub fn as_ed_private_key(&self) -> Result<&[u8]> {
152 match self.standard {
153 Standard::Pkcs1 => Err(ErrorKind::InvalidKeyFormat.into()),
154 Standard::Pkcs8 => match self.pem_type {
155 PemType::EdPrivate => Ok(self.content.as_slice()),
156 _ => Err(ErrorKind::InvalidKeyFormat.into()),
157 },
158 }
159 }
160
161 pub fn as_ed_public_key(&self) -> Result<&[u8]> {
163 match self.standard {
164 Standard::Pkcs1 => Err(ErrorKind::InvalidKeyFormat.into()),
165 Standard::Pkcs8 => match self.pem_type {
166 PemType::EdPublic => extract_first_bitstring(&self.asn1),
167 _ => Err(ErrorKind::InvalidKeyFormat.into()),
168 },
169 }
170 }
171
172 pub fn as_rsa_key(&self) -> Result<&[u8]> {
174 match self.standard {
175 Standard::Pkcs1 => Ok(self.content.as_slice()),
176 Standard::Pkcs8 => match self.pem_type {
177 PemType::RsaPrivate => extract_first_bitstring(&self.asn1),
178 PemType::RsaPublic => extract_first_bitstring(&self.asn1),
179 _ => Err(ErrorKind::InvalidKeyFormat.into()),
180 },
181 }
182 }
183}
184
185fn extract_first_bitstring(asn1: &[simple_asn1::ASN1Block]) -> Result<&[u8]> {
191 for asn1_entry in asn1.iter() {
192 match asn1_entry {
193 simple_asn1::ASN1Block::Sequence(_, entries) => {
194 if let Ok(result) = extract_first_bitstring(entries) {
195 return Ok(result);
196 }
197 }
198 simple_asn1::ASN1Block::BitString(_, _, value) => {
199 return Ok(value.as_ref());
200 }
201 simple_asn1::ASN1Block::OctetString(_, value) => {
202 return Ok(value.as_ref());
203 }
204 _ => (),
205 }
206 }
207
208 Err(ErrorKind::InvalidEcdsaKey.into())
209}
210
211fn classify_pem(asn1: &[simple_asn1::ASN1Block]) -> Option<Classification> {
213 let ec_public_key_oid = simple_asn1::oid!(1, 2, 840, 10_045, 2, 1);
216 let rsa_public_key_oid = simple_asn1::oid!(1, 2, 840, 113_549, 1, 1, 1);
217 let ed25519_oid = simple_asn1::oid!(1, 3, 101, 112);
218
219 for asn1_entry in asn1.iter() {
220 match asn1_entry {
221 simple_asn1::ASN1Block::Sequence(_, entries) => {
222 if let Some(classification) = classify_pem(entries) {
223 return Some(classification);
224 }
225 }
226 simple_asn1::ASN1Block::ObjectIdentifier(_, oid) => {
227 if oid == ec_public_key_oid {
228 return Some(Classification::Ec);
229 }
230 if oid == rsa_public_key_oid {
231 return Some(Classification::Rsa);
232 }
233 if oid == ed25519_oid {
234 return Some(Classification::Ed);
235 }
236 }
237 _ => {}
238 }
239 }
240 None
241}