1pub const TAG_INTEGER: u8 = 0x02;
18pub const TAG_BIT_STRING: u8 = 0x03;
20pub const TAG_OCTET_STRING: u8 = 0x04;
22pub const TAG_NULL: u8 = 0x05;
24pub const TAG_OID: u8 = 0x06;
26pub const TAG_SEQUENCE: u8 = 0x30;
28
29pub struct DerEncoder {
35 buf: Vec<u8>,
36}
37
38impl Default for DerEncoder {
39 fn default() -> Self {
40 Self::new()
41 }
42}
43
44impl DerEncoder {
45 pub fn new() -> Self {
47 Self { buf: Vec::new() }
48 }
49
50 pub fn finish(self) -> Vec<u8> {
52 self.buf
53 }
54
55 pub fn write_length(&mut self, len: usize) {
57 if len < 0x80 {
58 self.buf.push(len as u8);
59 } else if len < 0x100 {
60 self.buf.push(0x81);
61 self.buf.push(len as u8);
62 } else if len < 0x10000 {
63 self.buf.push(0x82);
64 self.buf.push((len >> 8) as u8);
65 self.buf.push((len & 0xFF) as u8);
66 } else {
67 self.buf.push(0x83);
68 self.buf.push((len >> 16) as u8);
69 self.buf.push(((len >> 8) & 0xFF) as u8);
70 self.buf.push((len & 0xFF) as u8);
71 }
72 }
73
74 pub fn sequence(&mut self, content: &[u8]) {
76 self.buf.push(TAG_SEQUENCE);
77 self.write_length(content.len());
78 self.buf.extend_from_slice(content);
79 }
80
81 pub fn integer(&mut self, value: &[u8]) {
84 let mut start = 0;
86 while start < value.len() - 1 && value[start] == 0 {
87 start += 1;
88 }
89 let val = &value[start..];
90 let needs_pad = val[0] & 0x80 != 0;
91 let total = val.len() + if needs_pad { 1 } else { 0 };
92
93 self.buf.push(TAG_INTEGER);
94 self.write_length(total);
95 if needs_pad {
96 self.buf.push(0x00);
97 }
98 self.buf.extend_from_slice(val);
99 }
100
101 pub fn integer_u64(&mut self, v: u64) {
103 if v == 0 {
104 self.buf.extend_from_slice(&[TAG_INTEGER, 1, 0]);
105 return;
106 }
107 let be = v.to_be_bytes();
108 let start = be.iter().position(|&b| b != 0).unwrap_or(7);
109 self.integer(&be[start..]);
110 }
111
112 pub fn octet_string(&mut self, data: &[u8]) {
114 self.buf.push(TAG_OCTET_STRING);
115 self.write_length(data.len());
116 self.buf.extend_from_slice(data);
117 }
118
119 pub fn bit_string(&mut self, data: &[u8]) {
121 self.buf.push(TAG_BIT_STRING);
122 self.write_length(data.len() + 1);
123 self.buf.push(0x00); self.buf.extend_from_slice(data);
125 }
126
127 pub fn oid(&mut self, encoded: &[u8]) {
129 self.buf.push(TAG_OID);
130 self.write_length(encoded.len());
131 self.buf.extend_from_slice(encoded);
132 }
133
134 pub fn null(&mut self) {
136 self.buf.extend_from_slice(&[TAG_NULL, 0x00]);
137 }
138
139 pub fn context_explicit(&mut self, tag_num: u8, content: &[u8]) {
141 self.buf.push(0xA0 | tag_num);
142 self.write_length(content.len());
143 self.buf.extend_from_slice(content);
144 }
145
146 pub fn raw(&mut self, data: &[u8]) {
148 self.buf.extend_from_slice(data);
149 }
150}
151
152pub struct DerDecoder<'a> {
158 data: &'a [u8],
159 pos: usize,
160}
161
162impl<'a> DerDecoder<'a> {
163 pub fn new(data: &'a [u8]) -> Self {
165 Self { data, pos: 0 }
166 }
167
168 pub fn remaining(&self) -> usize {
170 self.data.len() - self.pos
171 }
172
173 pub fn is_empty(&self) -> bool {
175 self.pos >= self.data.len()
176 }
177
178 pub fn peek_tag(&self) -> Option<u8> {
180 self.data.get(self.pos).copied()
181 }
182
183 pub fn read_tlv(&mut self) -> Option<(u8, &'a [u8])> {
185 let tag = *self.data.get(self.pos)?;
186 self.pos += 1;
187 let len = self.read_length()?;
188 if self.pos + len > self.data.len() {
189 return None;
190 }
191 let content = &self.data[self.pos..self.pos + len];
192 self.pos += len;
193 Some((tag, content))
194 }
195
196 fn read_length(&mut self) -> Option<usize> {
197 let first = *self.data.get(self.pos)?;
198 self.pos += 1;
199 if first < 0x80 {
200 Some(first as usize)
201 } else if first == 0x81 {
202 let b = *self.data.get(self.pos)? as usize;
203 self.pos += 1;
204 Some(b)
205 } else if first == 0x82 {
206 let hi = *self.data.get(self.pos)? as usize;
207 let lo = *self.data.get(self.pos + 1)? as usize;
208 self.pos += 2;
209 Some((hi << 8) | lo)
210 } else if first == 0x83 {
211 let a = *self.data.get(self.pos)? as usize;
212 let b = *self.data.get(self.pos + 1)? as usize;
213 let c = *self.data.get(self.pos + 2)? as usize;
214 self.pos += 3;
215 Some((a << 16) | (b << 8) | c)
216 } else {
217 None
218 }
219 }
220
221 pub fn read_sequence(&mut self) -> Option<DerDecoder<'a>> {
223 let (tag, content) = self.read_tlv()?;
224 if tag != TAG_SEQUENCE {
225 return None;
226 }
227 Some(DerDecoder::new(content))
228 }
229
230 pub fn read_integer(&mut self) -> Option<&'a [u8]> {
233 let (tag, content) = self.read_tlv()?;
234 if tag != TAG_INTEGER || content.is_empty() {
235 return None;
236 }
237 if content[0] == 0x00 && content.len() > 1 {
239 Some(&content[1..])
240 } else {
241 Some(content)
242 }
243 }
244
245 pub fn read_integer_u64(&mut self) -> Option<u64> {
247 let bytes = self.read_integer()?;
248 let mut v = 0u64;
249 for &b in bytes {
250 v = (v << 8) | b as u64;
251 }
252 Some(v)
253 }
254
255 pub fn read_octet_string(&mut self) -> Option<&'a [u8]> {
257 let (tag, content) = self.read_tlv()?;
258 if tag != TAG_OCTET_STRING {
259 return None;
260 }
261 Some(content)
262 }
263
264 pub fn read_bit_string(&mut self) -> Option<&'a [u8]> {
266 let (tag, content) = self.read_tlv()?;
267 if tag != TAG_BIT_STRING || content.is_empty() {
268 return None;
269 }
270 Some(&content[1..])
272 }
273
274 pub fn read_oid(&mut self) -> Option<&'a [u8]> {
276 let (tag, content) = self.read_tlv()?;
277 if tag != TAG_OID {
278 return None;
279 }
280 Some(content)
281 }
282
283 pub fn read_null(&mut self) -> Option<()> {
285 let (tag, content) = self.read_tlv()?;
286 if tag != TAG_NULL || !content.is_empty() {
287 return None;
288 }
289 Some(())
290 }
291
292 pub fn read_context_explicit(&mut self, tag_num: u8) -> Option<DerDecoder<'a>> {
296 let expected = 0xA0 | tag_num;
297 if self.peek_tag() != Some(expected) {
298 return None;
299 }
300 let (_, content) = self.read_tlv()?;
301 Some(DerDecoder::new(content))
302 }
303
304 pub fn skip(&mut self) -> Option<()> {
306 self.read_tlv().map(|_| ())
307 }
308}
309
310pub const OID_RSA: &[u8] = &[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01];
316
317pub const OID_EC_PUBLIC_KEY: &[u8] = &[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01];
319
320pub const OID_SECP256R1: &[u8] = &[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07];
322
323pub const OID_SECP384R1: &[u8] = &[0x2B, 0x81, 0x04, 0x00, 0x22];
325
326pub const OID_SECP521R1: &[u8] = &[0x2B, 0x81, 0x04, 0x00, 0x23];
328
329pub const OID_SECP256K1: &[u8] = &[0x2B, 0x81, 0x04, 0x00, 0x0A];
331
332pub const OID_BRAINPOOL_P256R1: &[u8] = &[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07];
334
335pub const OID_BRAINPOOL_P384R1: &[u8] = &[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B];
337
338pub const OID_BRAINPOOL_P512R1: &[u8] = &[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D];
340
341pub const OID_ED25519: &[u8] = &[0x2B, 0x65, 0x70];
343
344pub const OID_X25519: &[u8] = &[0x2B, 0x65, 0x6E];
346
347pub const OID_X448: &[u8] = &[0x2B, 0x65, 0x6F];
349
350#[cfg(test)]
355mod tests {
356 use super::*;
357
358 #[test]
359 fn roundtrip_integer() {
360 let val = [0x00, 0x80, 0xFF]; let mut enc = DerEncoder::new();
362 enc.integer(&val);
363 let der = enc.finish();
364 let mut dec = DerDecoder::new(&der);
365 let got = dec.read_integer().unwrap();
366 assert_eq!(got, &[0x80, 0xFF]);
367 }
368
369 #[test]
370 fn roundtrip_integer_u64() {
371 for v in [0u64, 1, 127, 128, 255, 256, 65535, 0xDEADBEEF] {
372 let mut enc = DerEncoder::new();
373 enc.integer_u64(v);
374 let der = enc.finish();
375 let mut dec = DerDecoder::new(&der);
376 assert_eq!(dec.read_integer_u64().unwrap(), v, "v={}", v);
377 }
378 }
379
380 #[test]
381 fn roundtrip_sequence() {
382 let mut inner = DerEncoder::new();
383 inner.integer_u64(42);
384 inner.octet_string(b"hello");
385 let content = inner.finish();
386
387 let mut outer = DerEncoder::new();
388 outer.sequence(&content);
389 let der = outer.finish();
390
391 let mut dec = DerDecoder::new(&der);
392 let mut seq = dec.read_sequence().unwrap();
393 assert_eq!(seq.read_integer_u64().unwrap(), 42);
394 assert_eq!(seq.read_octet_string().unwrap(), b"hello");
395 assert!(seq.is_empty());
396 }
397
398 #[test]
399 fn roundtrip_bit_string() {
400 let data = [0x04, 0x01, 0x02]; let mut enc = DerEncoder::new();
402 enc.bit_string(&data);
403 let der = enc.finish();
404
405 let mut dec = DerDecoder::new(&der);
406 let got = dec.read_bit_string().unwrap();
407 assert_eq!(got, &data);
408 }
409
410 #[test]
411 fn roundtrip_oid() {
412 let mut enc = DerEncoder::new();
413 enc.oid(OID_RSA);
414 let der = enc.finish();
415
416 let mut dec = DerDecoder::new(&der);
417 assert_eq!(dec.read_oid().unwrap(), OID_RSA);
418 }
419
420 #[test]
421 fn context_explicit_tag() {
422 let mut inner = DerEncoder::new();
423 inner.integer_u64(1);
424 let content = inner.finish();
425
426 let mut enc = DerEncoder::new();
427 enc.context_explicit(0, &content);
428 let der = enc.finish();
429
430 let mut dec = DerDecoder::new(&der);
431 let mut ctx = dec.read_context_explicit(0).unwrap();
432 assert_eq!(ctx.read_integer_u64().unwrap(), 1);
433 }
434
435 #[test]
436 fn large_length_encoding() {
437 let data = vec![0xABu8; 256];
439 let mut enc = DerEncoder::new();
440 enc.octet_string(&data);
441 let der = enc.finish();
442
443 let mut dec = DerDecoder::new(&der);
444 let got = dec.read_octet_string().unwrap();
445 assert_eq!(got, &data[..]);
446 }
447}