1pub const TAG_INTEGER: u8 = 0x02;
13pub const TAG_BIT_STRING: u8 = 0x03;
15pub const TAG_OCTET_STRING: u8 = 0x04;
17pub const TAG_NULL: u8 = 0x05;
19pub const TAG_OID: u8 = 0x06;
21pub const TAG_SEQUENCE: u8 = 0x30;
23
24pub struct DerEncoder {
30 buf: Vec<u8>,
31}
32
33impl DerEncoder {
34 pub fn new() -> Self {
36 Self { buf: Vec::new() }
37 }
38
39 pub fn finish(self) -> Vec<u8> {
41 self.buf
42 }
43
44 pub fn write_length(&mut self, len: usize) {
46 if len < 0x80 {
47 self.buf.push(len as u8);
48 } else if len < 0x100 {
49 self.buf.push(0x81);
50 self.buf.push(len as u8);
51 } else if len < 0x10000 {
52 self.buf.push(0x82);
53 self.buf.push((len >> 8) as u8);
54 self.buf.push((len & 0xFF) as u8);
55 } else {
56 self.buf.push(0x83);
57 self.buf.push((len >> 16) as u8);
58 self.buf.push(((len >> 8) & 0xFF) as u8);
59 self.buf.push((len & 0xFF) as u8);
60 }
61 }
62
63 pub fn sequence(&mut self, content: &[u8]) {
65 self.buf.push(TAG_SEQUENCE);
66 self.write_length(content.len());
67 self.buf.extend_from_slice(content);
68 }
69
70 pub fn integer(&mut self, value: &[u8]) {
73 let mut start = 0;
75 while start < value.len() - 1 && value[start] == 0 {
76 start += 1;
77 }
78 let val = &value[start..];
79 let needs_pad = val[0] & 0x80 != 0;
80 let total = val.len() + if needs_pad { 1 } else { 0 };
81
82 self.buf.push(TAG_INTEGER);
83 self.write_length(total);
84 if needs_pad {
85 self.buf.push(0x00);
86 }
87 self.buf.extend_from_slice(val);
88 }
89
90 pub fn integer_u64(&mut self, v: u64) {
92 if v == 0 {
93 self.buf.extend_from_slice(&[TAG_INTEGER, 1, 0]);
94 return;
95 }
96 let be = v.to_be_bytes();
97 let start = be.iter().position(|&b| b != 0).unwrap_or(7);
98 self.integer(&be[start..]);
99 }
100
101 pub fn octet_string(&mut self, data: &[u8]) {
103 self.buf.push(TAG_OCTET_STRING);
104 self.write_length(data.len());
105 self.buf.extend_from_slice(data);
106 }
107
108 pub fn bit_string(&mut self, data: &[u8]) {
110 self.buf.push(TAG_BIT_STRING);
111 self.write_length(data.len() + 1);
112 self.buf.push(0x00); self.buf.extend_from_slice(data);
114 }
115
116 pub fn oid(&mut self, encoded: &[u8]) {
118 self.buf.push(TAG_OID);
119 self.write_length(encoded.len());
120 self.buf.extend_from_slice(encoded);
121 }
122
123 pub fn null(&mut self) {
125 self.buf.extend_from_slice(&[TAG_NULL, 0x00]);
126 }
127
128 pub fn context_explicit(&mut self, tag_num: u8, content: &[u8]) {
130 self.buf.push(0xA0 | tag_num);
131 self.write_length(content.len());
132 self.buf.extend_from_slice(content);
133 }
134
135 pub fn raw(&mut self, data: &[u8]) {
137 self.buf.extend_from_slice(data);
138 }
139}
140
141pub struct DerDecoder<'a> {
147 data: &'a [u8],
148 pos: usize,
149}
150
151impl<'a> DerDecoder<'a> {
152 pub fn new(data: &'a [u8]) -> Self {
154 Self { data, pos: 0 }
155 }
156
157 pub fn remaining(&self) -> usize {
159 self.data.len() - self.pos
160 }
161
162 pub fn is_empty(&self) -> bool {
164 self.pos >= self.data.len()
165 }
166
167 pub fn peek_tag(&self) -> Option<u8> {
169 self.data.get(self.pos).copied()
170 }
171
172 pub fn read_tlv(&mut self) -> Option<(u8, &'a [u8])> {
174 let tag = *self.data.get(self.pos)?;
175 self.pos += 1;
176 let len = self.read_length()?;
177 if self.pos + len > self.data.len() {
178 return None;
179 }
180 let content = &self.data[self.pos..self.pos + len];
181 self.pos += len;
182 Some((tag, content))
183 }
184
185 fn read_length(&mut self) -> Option<usize> {
186 let first = *self.data.get(self.pos)?;
187 self.pos += 1;
188 if first < 0x80 {
189 Some(first as usize)
190 } else if first == 0x81 {
191 let b = *self.data.get(self.pos)? as usize;
192 self.pos += 1;
193 Some(b)
194 } else if first == 0x82 {
195 let hi = *self.data.get(self.pos)? as usize;
196 let lo = *self.data.get(self.pos + 1)? as usize;
197 self.pos += 2;
198 Some((hi << 8) | lo)
199 } else if first == 0x83 {
200 let a = *self.data.get(self.pos)? as usize;
201 let b = *self.data.get(self.pos + 1)? as usize;
202 let c = *self.data.get(self.pos + 2)? as usize;
203 self.pos += 3;
204 Some((a << 16) | (b << 8) | c)
205 } else {
206 None
207 }
208 }
209
210 pub fn read_sequence(&mut self) -> Option<DerDecoder<'a>> {
212 let (tag, content) = self.read_tlv()?;
213 if tag != TAG_SEQUENCE {
214 return None;
215 }
216 Some(DerDecoder::new(content))
217 }
218
219 pub fn read_integer(&mut self) -> Option<&'a [u8]> {
222 let (tag, content) = self.read_tlv()?;
223 if tag != TAG_INTEGER || content.is_empty() {
224 return None;
225 }
226 if content[0] == 0x00 && content.len() > 1 {
228 Some(&content[1..])
229 } else {
230 Some(content)
231 }
232 }
233
234 pub fn read_integer_u64(&mut self) -> Option<u64> {
236 let bytes = self.read_integer()?;
237 let mut v = 0u64;
238 for &b in bytes {
239 v = (v << 8) | b as u64;
240 }
241 Some(v)
242 }
243
244 pub fn read_octet_string(&mut self) -> Option<&'a [u8]> {
246 let (tag, content) = self.read_tlv()?;
247 if tag != TAG_OCTET_STRING {
248 return None;
249 }
250 Some(content)
251 }
252
253 pub fn read_bit_string(&mut self) -> Option<&'a [u8]> {
255 let (tag, content) = self.read_tlv()?;
256 if tag != TAG_BIT_STRING || content.is_empty() {
257 return None;
258 }
259 Some(&content[1..])
261 }
262
263 pub fn read_oid(&mut self) -> Option<&'a [u8]> {
265 let (tag, content) = self.read_tlv()?;
266 if tag != TAG_OID {
267 return None;
268 }
269 Some(content)
270 }
271
272 pub fn read_null(&mut self) -> Option<()> {
274 let (tag, content) = self.read_tlv()?;
275 if tag != TAG_NULL || !content.is_empty() {
276 return None;
277 }
278 Some(())
279 }
280
281 pub fn read_context_explicit(&mut self, tag_num: u8) -> Option<DerDecoder<'a>> {
285 let expected = 0xA0 | tag_num;
286 if self.peek_tag() != Some(expected) {
287 return None;
288 }
289 let (_, content) = self.read_tlv()?;
290 Some(DerDecoder::new(content))
291 }
292
293 pub fn skip(&mut self) -> Option<()> {
295 self.read_tlv().map(|_| ())
296 }
297}
298
299pub const OID_RSA: &[u8] = &[0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01];
305
306pub const OID_EC_PUBLIC_KEY: &[u8] = &[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01];
308
309pub const OID_SECP256R1: &[u8] = &[0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07];
311
312pub const OID_SECP384R1: &[u8] = &[0x2B, 0x81, 0x04, 0x00, 0x22];
314
315pub const OID_SECP521R1: &[u8] = &[0x2B, 0x81, 0x04, 0x00, 0x23];
317
318pub const OID_SECP256K1: &[u8] = &[0x2B, 0x81, 0x04, 0x00, 0x0A];
320
321pub const OID_BRAINPOOL_P256R1: &[u8] = &[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07];
323
324pub const OID_BRAINPOOL_P384R1: &[u8] = &[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B];
326
327pub const OID_BRAINPOOL_P512R1: &[u8] = &[0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D];
329
330pub const OID_ED25519: &[u8] = &[0x2B, 0x65, 0x70];
332
333pub const OID_X25519: &[u8] = &[0x2B, 0x65, 0x6E];
335
336pub const OID_X448: &[u8] = &[0x2B, 0x65, 0x6F];
338
339#[cfg(test)]
344mod tests {
345 use super::*;
346
347 #[test]
348 fn roundtrip_integer() {
349 let val = [0x00, 0x80, 0xFF]; let mut enc = DerEncoder::new();
351 enc.integer(&val);
352 let der = enc.finish();
353 let mut dec = DerDecoder::new(&der);
354 let got = dec.read_integer().unwrap();
355 assert_eq!(got, &[0x80, 0xFF]);
356 }
357
358 #[test]
359 fn roundtrip_integer_u64() {
360 for v in [0u64, 1, 127, 128, 255, 256, 65535, 0xDEADBEEF] {
361 let mut enc = DerEncoder::new();
362 enc.integer_u64(v);
363 let der = enc.finish();
364 let mut dec = DerDecoder::new(&der);
365 assert_eq!(dec.read_integer_u64().unwrap(), v, "v={}", v);
366 }
367 }
368
369 #[test]
370 fn roundtrip_sequence() {
371 let mut inner = DerEncoder::new();
372 inner.integer_u64(42);
373 inner.octet_string(b"hello");
374 let content = inner.finish();
375
376 let mut outer = DerEncoder::new();
377 outer.sequence(&content);
378 let der = outer.finish();
379
380 let mut dec = DerDecoder::new(&der);
381 let mut seq = dec.read_sequence().unwrap();
382 assert_eq!(seq.read_integer_u64().unwrap(), 42);
383 assert_eq!(seq.read_octet_string().unwrap(), b"hello");
384 assert!(seq.is_empty());
385 }
386
387 #[test]
388 fn roundtrip_bit_string() {
389 let data = [0x04, 0x01, 0x02]; let mut enc = DerEncoder::new();
391 enc.bit_string(&data);
392 let der = enc.finish();
393
394 let mut dec = DerDecoder::new(&der);
395 let got = dec.read_bit_string().unwrap();
396 assert_eq!(got, &data);
397 }
398
399 #[test]
400 fn roundtrip_oid() {
401 let mut enc = DerEncoder::new();
402 enc.oid(OID_RSA);
403 let der = enc.finish();
404
405 let mut dec = DerDecoder::new(&der);
406 assert_eq!(dec.read_oid().unwrap(), OID_RSA);
407 }
408
409 #[test]
410 fn context_explicit_tag() {
411 let mut inner = DerEncoder::new();
412 inner.integer_u64(1);
413 let content = inner.finish();
414
415 let mut enc = DerEncoder::new();
416 enc.context_explicit(0, &content);
417 let der = enc.finish();
418
419 let mut dec = DerDecoder::new(&der);
420 let mut ctx = dec.read_context_explicit(0).unwrap();
421 assert_eq!(ctx.read_integer_u64().unwrap(), 1);
422 }
423
424 #[test]
425 fn large_length_encoding() {
426 let data = vec![0xABu8; 256];
428 let mut enc = DerEncoder::new();
429 enc.octet_string(&data);
430 let der = enc.finish();
431
432 let mut dec = DerDecoder::new(&der);
433 let got = dec.read_octet_string().unwrap();
434 assert_eq!(got, &data[..]);
435 }
436}