jsonwebtoken/pem/
decoder.rs
1use 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 asn1_content = match simple_asn1::from_der(content.contents()) {
57 Ok(asn1) => asn1,
58 Err(_) => return Err(ErrorKind::InvalidKeyFormat.into()),
59 };
60
61 match content.tag() {
62 "RSA PRIVATE KEY" => Ok(PemEncodedKey {
64 content: content.into_contents(),
65 asn1: asn1_content,
66 pem_type: PemType::RsaPrivate,
67 standard: Standard::Pkcs1,
68 }),
69 "RSA PUBLIC KEY" => Ok(PemEncodedKey {
70 content: content.into_contents(),
71 asn1: asn1_content,
72 pem_type: PemType::RsaPublic,
73 standard: Standard::Pkcs1,
74 }),
75
76 tag @ "PRIVATE KEY" | tag @ "PUBLIC KEY" | tag @ "CERTIFICATE" => {
82 match classify_pem(&asn1_content) {
83 Some(c) => {
84 let is_private = tag == "PRIVATE KEY";
85 let pem_type = match c {
86 Classification::Ec => {
87 if is_private {
88 PemType::EcPrivate
89 } else {
90 PemType::EcPublic
91 }
92 }
93 Classification::Ed => {
94 if is_private {
95 PemType::EdPrivate
96 } else {
97 PemType::EdPublic
98 }
99 }
100 Classification::Rsa => {
101 if is_private {
102 PemType::RsaPrivate
103 } else {
104 PemType::RsaPublic
105 }
106 }
107 };
108 Ok(PemEncodedKey {
109 content: content.into_contents(),
110 asn1: asn1_content,
111 pem_type,
112 standard: Standard::Pkcs8,
113 })
114 }
115 None => Err(ErrorKind::InvalidKeyFormat.into()),
116 }
117 }
118
119 _ => Err(ErrorKind::InvalidKeyFormat.into()),
121 }
122 }
123 Err(_) => Err(ErrorKind::InvalidKeyFormat.into()),
124 }
125 }
126
127 pub fn as_ec_private_key(&self) -> Result<&[u8]> {
129 match self.standard {
130 Standard::Pkcs1 => Err(ErrorKind::InvalidKeyFormat.into()),
131 Standard::Pkcs8 => match self.pem_type {
132 PemType::EcPrivate => Ok(self.content.as_slice()),
133 _ => Err(ErrorKind::InvalidKeyFormat.into()),
134 },
135 }
136 }
137
138 pub fn as_ec_public_key(&self) -> Result<&[u8]> {
140 match self.standard {
141 Standard::Pkcs1 => Err(ErrorKind::InvalidKeyFormat.into()),
142 Standard::Pkcs8 => match self.pem_type {
143 PemType::EcPublic => extract_first_bitstring(&self.asn1),
144 _ => Err(ErrorKind::InvalidKeyFormat.into()),
145 },
146 }
147 }
148
149 pub fn as_ed_private_key(&self) -> Result<&[u8]> {
151 match self.standard {
152 Standard::Pkcs1 => Err(ErrorKind::InvalidKeyFormat.into()),
153 Standard::Pkcs8 => match self.pem_type {
154 PemType::EdPrivate => Ok(self.content.as_slice()),
155 _ => Err(ErrorKind::InvalidKeyFormat.into()),
156 },
157 }
158 }
159
160 pub fn as_ed_public_key(&self) -> Result<&[u8]> {
162 match self.standard {
163 Standard::Pkcs1 => Err(ErrorKind::InvalidKeyFormat.into()),
164 Standard::Pkcs8 => match self.pem_type {
165 PemType::EdPublic => extract_first_bitstring(&self.asn1),
166 _ => Err(ErrorKind::InvalidKeyFormat.into()),
167 },
168 }
169 }
170
171 pub fn as_rsa_key(&self) -> Result<&[u8]> {
173 match self.standard {
174 Standard::Pkcs1 => Ok(self.content.as_slice()),
175 Standard::Pkcs8 => match self.pem_type {
176 PemType::RsaPrivate => extract_first_bitstring(&self.asn1),
177 PemType::RsaPublic => extract_first_bitstring(&self.asn1),
178 _ => Err(ErrorKind::InvalidKeyFormat.into()),
179 },
180 }
181 }
182}
183
184fn extract_first_bitstring(asn1: &[simple_asn1::ASN1Block]) -> Result<&[u8]> {
190 for asn1_entry in asn1.iter() {
191 match asn1_entry {
192 simple_asn1::ASN1Block::Sequence(_, entries) => {
193 if let Ok(result) = extract_first_bitstring(entries) {
194 return Ok(result);
195 }
196 }
197 simple_asn1::ASN1Block::BitString(_, _, value) => {
198 return Ok(value.as_ref());
199 }
200 simple_asn1::ASN1Block::OctetString(_, value) => {
201 return Ok(value.as_ref());
202 }
203 _ => (),
204 }
205 }
206
207 Err(ErrorKind::InvalidEcdsaKey.into())
208}
209
210fn classify_pem(asn1: &[simple_asn1::ASN1Block]) -> Option<Classification> {
212 let ec_public_key_oid = simple_asn1::oid!(1, 2, 840, 10_045, 2, 1);
215 let rsa_public_key_oid = simple_asn1::oid!(1, 2, 840, 113_549, 1, 1, 1);
216 let ed25519_oid = simple_asn1::oid!(1, 3, 101, 112);
217
218 for asn1_entry in asn1.iter() {
219 match asn1_entry {
220 simple_asn1::ASN1Block::Sequence(_, entries) => {
221 if let Some(classification) = classify_pem(entries) {
222 return Some(classification);
223 }
224 }
225 simple_asn1::ASN1Block::ObjectIdentifier(_, oid) => {
226 if oid == ec_public_key_oid {
227 return Some(Classification::Ec);
228 }
229 if oid == rsa_public_key_oid {
230 return Some(Classification::Rsa);
231 }
232 if oid == ed25519_oid {
233 return Some(Classification::Ed);
234 }
235 }
236 _ => {}
237 }
238 }
239 None
240}