Skip to main content

rust_pdf_box/crypto/
asn1.rs

1/// Lightweight ASN.1 DER encoder for X.509 certificates and PKCS#7 SignedData.
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub enum DerElement {
5    Boolean(bool),
6    Integer(Vec<u8>),       // signed big-endian integer bytes
7    BitString(Vec<u8>, u8), // data and unused bits count
8    OctetString(Vec<u8>),
9    Null,
10    ObjectIdentifier(Vec<u64>),
11    Utf8String(String),
12    PrintableString(String),
13    UtcTime(String),         // YYMMDDHHMMSSZ
14    GeneralizedTime(String), // YYYYMMDDHHMMSSZ
15    Sequence(Vec<DerElement>),
16    Set(Vec<DerElement>),
17    ContextSpecific(u8, Box<DerElement>, bool), // tag number, inner element, is_constructed
18}
19
20impl DerElement {
21    pub fn integer_from_u64(val: u64) -> Self {
22        let bytes = val.to_be_bytes();
23        let mut start = 0;
24        while start < bytes.len() - 1 && bytes[start] == 0 {
25            start += 1;
26        }
27        let mut slice = bytes[start..].to_vec();
28        // If highest bit is 1, prepend 0x00 so it is positive
29        if (slice[0] & 0x80) != 0 {
30            slice.insert(0, 0x00);
31        }
32        Self::Integer(slice)
33    }
34
35    pub fn integer_from_bytes(bytes: &[u8]) -> Self {
36        let mut v = bytes.to_vec();
37        if v.is_empty() {
38            v.push(0);
39        } else if (v[0] & 0x80) != 0 {
40            v.insert(0, 0x00);
41        }
42        Self::Integer(v)
43    }
44
45    pub fn to_der(&self) -> Vec<u8> {
46        let mut out = Vec::new();
47        match self {
48            Self::Boolean(b) => {
49                out.push(0x01);
50                out.push(0x01);
51                out.push(if *b { 0xFF } else { 0x00 });
52            }
53            Self::Integer(bytes) => {
54                out.push(0x02);
55                encode_length(&mut out, bytes.len());
56                out.extend_from_slice(bytes);
57            }
58            Self::BitString(bytes, unused_bits) => {
59                out.push(0x03);
60                encode_length(&mut out, bytes.len() + 1);
61                out.push(*unused_bits);
62                out.extend_from_slice(bytes);
63            }
64            Self::OctetString(bytes) => {
65                out.push(0x04);
66                encode_length(&mut out, bytes.len());
67                out.extend_from_slice(bytes);
68            }
69            Self::Null => {
70                out.push(0x05);
71                out.push(0x00);
72            }
73            Self::ObjectIdentifier(arcs) => {
74                out.push(0x06);
75                let mut body = Vec::new();
76                if arcs.len() >= 2 {
77                    body.push((arcs[0] * 40 + arcs[1]) as u8);
78                    for &arc in &arcs[2..] {
79                        encode_oid_arc(&mut body, arc);
80                    }
81                }
82                encode_length(&mut out, body.len());
83                out.extend_from_slice(&body);
84            }
85            Self::Utf8String(s) => {
86                out.push(0x0C);
87                encode_length(&mut out, s.len());
88                out.extend_from_slice(s.as_bytes());
89            }
90            Self::PrintableString(s) => {
91                out.push(0x13);
92                encode_length(&mut out, s.len());
93                out.extend_from_slice(s.as_bytes());
94            }
95            Self::UtcTime(s) => {
96                out.push(0x17);
97                encode_length(&mut out, s.len());
98                out.extend_from_slice(s.as_bytes());
99            }
100            Self::GeneralizedTime(s) => {
101                out.push(0x18);
102                encode_length(&mut out, s.len());
103                out.extend_from_slice(s.as_bytes());
104            }
105            Self::Sequence(elements) => {
106                let mut body = Vec::new();
107                for el in elements {
108                    body.extend_from_slice(&el.to_der());
109                }
110                out.push(0x30); // 0x20 | 0x10 (Constructed | Sequence)
111                encode_length(&mut out, body.len());
112                out.extend_from_slice(&body);
113            }
114            Self::Set(elements) => {
115                let mut body = Vec::new();
116                for el in elements {
117                    body.extend_from_slice(&el.to_der());
118                }
119                out.push(0x31); // 0x20 | 0x11 (Constructed | Set)
120                encode_length(&mut out, body.len());
121                out.extend_from_slice(&body);
122            }
123            Self::ContextSpecific(tag, inner, is_constructed) => {
124                let body = inner.to_der();
125                let tag_byte = 0x80 | (if *is_constructed { 0x20 } else { 0x00 }) | (tag & 0x1F);
126                out.push(tag_byte);
127                // For explicit tagging, inner DER includes its own tag and length
128                encode_length(&mut out, body.len());
129                out.extend_from_slice(&body);
130            }
131        }
132        out
133    }
134}
135
136fn encode_length(out: &mut Vec<u8>, len: usize) {
137    if len < 128 {
138        out.push(len as u8);
139    } else {
140        let mut len_bytes = Vec::new();
141        let mut temp = len;
142        while temp > 0 {
143            len_bytes.push((temp & 0xFF) as u8);
144            temp >>= 8;
145        }
146        len_bytes.reverse();
147        out.push(0x80 | (len_bytes.len() as u8));
148        out.extend_from_slice(&len_bytes);
149    }
150}
151
152fn encode_oid_arc(out: &mut Vec<u8>, mut arc: u64) {
153    let mut chunks = Vec::new();
154    chunks.push((arc & 0x7F) as u8);
155    arc >>= 7;
156    while arc > 0 {
157        chunks.push(0x80 | ((arc & 0x7F) as u8));
158        arc >>= 7;
159    }
160    chunks.reverse();
161    out.extend_from_slice(&chunks);
162}