1use crate::cms::signed_data::{
16 AlgorithmIdentifier, EncapContentInfo, SignedData, SignerIdentifier, SignerInfo,
17};
18
19pub fn encode_signed_data_der(signed_data: &SignedData) -> Result<Vec<u8>, DerError> {
28 let inner = encode_signed_data_inner(signed_data)?;
30
31 let content_type_oid_bytes = oid_to_der(&[1, 2, 840, 113549, 1, 7, 2]);
33
34 let mut explicit_content = Vec::new();
35 explicit_content.push(0xA0); explicit_content.extend_from_slice(&encode_length(inner.len()));
37 explicit_content.extend_from_slice(&inner);
38
39 let mut seq_body = Vec::new();
40 seq_body.extend_from_slice(&content_type_oid_bytes);
41 seq_body.extend_from_slice(&explicit_content);
42
43 let mut out = Vec::new();
44 out.push(0x30); out.extend_from_slice(&encode_length(seq_body.len()));
46 out.extend_from_slice(&seq_body);
47 Ok(out)
48}
49
50fn encode_signed_data_inner(sd: &SignedData) -> Result<Vec<u8>, DerError> {
51 let mut body = Vec::new();
59 body.extend_from_slice(&integer_to_der(sd.version as i64));
60
61 let mut digest_algs = Vec::new();
62 for alg in &sd.digest_algorithms {
63 digest_algs.extend_from_slice(&encode_algorithm_identifier(alg));
64 }
65 body.extend_from_slice(&wrap_der(0x31, &digest_algs)); body.extend_from_slice(&encode_encap_content_info(&sd.encap_content_info)?);
68
69 if !sd.certificates.is_empty() {
71 let mut certs_body = Vec::new();
72 for cert in &sd.certificates {
73 certs_body.extend_from_slice(cert); }
75 body.push(0xA0);
77 body.extend_from_slice(&encode_length(certs_body.len()));
78 body.extend_from_slice(&certs_body);
79 }
80
81 let mut signer_infos = Vec::new();
82 for si in &sd.signer_infos {
83 signer_infos.extend_from_slice(&encode_signer_info(si)?);
84 }
85 body.extend_from_slice(&wrap_der(0x31, &signer_infos)); Ok(wrap_der(0x30, &body)) }
89
90fn encode_encap_content_info(eci: &EncapContentInfo) -> Result<Vec<u8>, DerError> {
91 let oid_bytes = oid_from_string(&eci.content_type)?;
92
93 let mut body = Vec::new();
94 body.extend_from_slice(&oid_bytes);
95
96 if let Some(content) = &eci.content {
97 let octet = wrap_der(0x04, content);
99 body.push(0xA0);
100 body.extend_from_slice(&encode_length(octet.len()));
101 body.extend_from_slice(&octet);
102 }
103
104 Ok(wrap_der(0x30, &body))
105}
106
107fn encode_algorithm_identifier(alg: &AlgorithmIdentifier) -> Vec<u8> {
108 let oid_bytes = match oid_from_string(&alg.oid) {
109 Ok(b) => b,
110 Err(_) => return Vec::new(),
111 };
112 let mut body = oid_bytes;
113 if let Some(params) = &alg.parameters {
114 body.extend_from_slice(params);
115 } else {
116 body.extend_from_slice(&[0x05, 0x00]);
118 }
119 wrap_der(0x30, &body)
120}
121
122fn encode_signer_info(si: &SignerInfo) -> Result<Vec<u8>, DerError> {
123 let mut body = Vec::new();
124 body.extend_from_slice(&integer_to_der(si.version as i64));
125
126 match &si.sid {
128 SignerIdentifier::IssuerAndSerialNumber {
129 issuer_der,
130 serial_number,
131 } => {
132 let mut seq = Vec::new();
134 seq.extend_from_slice(issuer_der);
135 seq.extend_from_slice(&integer_bytes_to_der(serial_number));
136 body.extend_from_slice(&wrap_der(0x30, &seq));
137 }
138 SignerIdentifier::SubjectKeyIdentifier { key_identifier } => {
139 let octet = wrap_der(0x04, key_identifier);
141 body.push(0x80);
142 body.extend_from_slice(&encode_length(octet.len()));
143 body.extend_from_slice(&octet);
144 }
145 }
146
147 body.extend_from_slice(&encode_algorithm_identifier(&si.digest_algorithm));
148
149 body.extend_from_slice(&encode_algorithm_identifier(&si.signature_algorithm));
152
153 body.extend_from_slice(&wrap_der(0x04, &si.signature));
155
156 Ok(wrap_der(0x30, &body))
159}
160
161#[derive(Debug, thiserror::Error)]
163pub enum DerError {
164 #[error("invalid OID: {0}")]
166 InvalidOid(String),
167 #[error("value too large: {0}")]
169 TooLarge(String),
170}
171
172fn oid_to_der(arcs: &[u64]) -> Vec<u8> {
173 let first = (40 * arcs.first().copied().unwrap_or(0) + arcs.get(1).copied().unwrap_or(0)) as u8;
175 let mut out = vec![first];
176 for arc in arcs.iter().skip(2) {
177 out.extend_from_slice(&encode_base128(*arc));
178 }
179 wrap_der(0x06, &out)
181}
182
183fn oid_from_string(s: &str) -> Result<Vec<u8>, DerError> {
184 let arcs: Vec<u64> = s
185 .split('.')
186 .map(|a| a.parse::<u64>().map_err(|_| DerError::InvalidOid(s.into())))
187 .collect::<Result<Vec<_>, _>>()?;
188 if arcs.len() < 2 {
189 return Err(DerError::InvalidOid("OID must have >= 2 arcs".into()));
190 }
191 Ok(oid_to_der(&arcs))
192}
193
194fn encode_base128(n: u64) -> Vec<u8> {
195 let mut bytes = Vec::new();
196 let mut n = n;
197 loop {
198 bytes.insert(0, (n & 0x7F) as u8);
199 n >>= 7;
200 if n == 0 {
201 break;
202 }
203 }
204 let last = bytes.len() - 1;
206 for b in &mut bytes[..last] {
207 *b |= 0x80;
208 }
209 bytes
210}
211
212fn integer_to_der(n: i64) -> Vec<u8> {
213 if (0..=127).contains(&n) {
214 return vec![0x02, 0x01, n as u8];
215 }
216 let bytes = n.to_be_bytes();
217 let mut start = 0;
219 while start < bytes.len() - 1 && bytes[start] == 0 && (bytes[start + 1] & 0x80) == 0 {
220 start += 1;
221 }
222 wrap_der(0x02, &bytes[start..])
223}
224
225fn integer_bytes_to_der(bytes: &[u8]) -> Vec<u8> {
226 let mut value = bytes.to_vec();
228 if value.first().map(|b| b & 0x80 != 0).unwrap_or(false) {
229 value.insert(0, 0);
230 }
231 wrap_der(0x02, &value)
232}
233
234fn encode_length(len: usize) -> Vec<u8> {
235 if len < 128 {
236 return vec![len as u8];
237 }
238 let mut bytes = Vec::new();
239 let mut l = len;
240 while l > 0 {
241 bytes.insert(0, (l & 0xFF) as u8);
242 l >>= 8;
243 }
244 let mut out = vec![0x80 | bytes.len() as u8];
245 out.extend_from_slice(&bytes);
246 out
247}
248
249fn wrap_der(tag: u8, body: &[u8]) -> Vec<u8> {
250 let mut out = vec![tag];
251 out.extend_from_slice(&encode_length(body.len()));
252 out.extend_from_slice(body);
253 out
254}
255
256#[cfg(test)]
257mod tests {
258 use super::*;
259 use crate::cms::signed_data::{EncapContentInfo, SignerIdentifier, SignerInfo};
260
261 #[test]
262 fn encode_length_short_form() {
263 assert_eq!(encode_length(5), vec![5]);
264 assert_eq!(encode_length(127), vec![127]);
265 }
266
267 #[test]
268 fn encode_length_long_form() {
269 assert_eq!(encode_length(128), vec![0x81, 0x80]);
270 assert_eq!(encode_length(256), vec![0x82, 0x01, 0x00]);
271 }
272
273 #[test]
274 fn integer_short() {
275 assert_eq!(integer_to_der(0), vec![0x02, 0x01, 0x00]);
276 assert_eq!(integer_to_der(42), vec![0x02, 0x01, 0x2A]);
277 assert_eq!(integer_to_der(127), vec![0x02, 0x01, 0x7F]);
278 }
279
280 #[test]
281 fn oid_sha256() {
282 let bytes = oid_from_string("2.16.840.1.101.3.4.2.1").unwrap();
284 assert_eq!(bytes[0], 0x06);
286 assert_eq!(bytes[1], 0x09);
287 assert_eq!(bytes[2], 96); assert_eq!(bytes[3], 0x86);
289 assert_eq!(bytes[4], 0x48);
290 }
291
292 #[test]
293 fn oid_invalid_arcs() {
294 assert!(oid_from_string("not-a-number").is_err());
295 assert!(oid_from_string("1").is_err());
296 }
297
298 #[test]
299 fn base128_single_byte() {
300 assert_eq!(encode_base128(0), vec![0]);
301 assert_eq!(encode_base128(127), vec![127]);
302 }
303
304 #[test]
305 fn base128_multi_byte() {
306 assert_eq!(encode_base128(840), vec![0x86, 0x48]);
308 }
309
310 #[test]
311 fn encode_signed_data_minimal() {
312 let sd = SignedData {
313 version: 1,
314 digest_algorithms: vec![AlgorithmIdentifier {
315 oid: "2.16.840.1.101.3.4.2.1".into(),
316 parameters: None,
317 }],
318 encap_content_info: EncapContentInfo {
319 content_type: "1.2.840.113549.1.7.1".into(),
320 content: None,
321 },
322 certificates: vec![],
323 signer_infos: vec![SignerInfo {
324 version: 1,
325 sid: SignerIdentifier::SubjectKeyIdentifier {
326 key_identifier: vec![0xAA; 20],
327 },
328 digest_algorithm: AlgorithmIdentifier {
329 oid: "2.16.840.1.101.3.4.2.1".into(),
330 parameters: None,
331 },
332 signed_attrs: vec![],
333 signature_algorithm: AlgorithmIdentifier {
334 oid: "1.2.840.113549.1.1.11".into(),
335 parameters: None,
336 },
337 signature: vec![0u8; 256],
338 unsigned_attrs: vec![],
339 }],
340 };
341 let der = encode_signed_data_der(&sd).unwrap();
342 assert_eq!(der[0], 0x30); assert!(der.len() > 50);
345 }
346}