isideload_cryptographic_message_syntax/
signing.rs1use {
8 crate::{
9 CmsError,
10 asn1::rfc5652::{
11 CertificateChoices, CertificateSet, CmsVersion, DigestAlgorithmIdentifier,
12 DigestAlgorithmIdentifiers, EncapsulatedContentInfo, IssuerAndSerialNumber,
13 OID_CONTENT_TYPE, OID_ID_DATA, OID_ID_SIGNED_DATA, OID_MESSAGE_DIGEST,
14 OID_SIGNING_TIME, SignatureValue, SignedAttributes, SignedData, SignerIdentifier,
15 SignerInfo, SignerInfos,
16 },
17 },
18 bcder::{
19 Captured, Mode, OctetString, Oid,
20 encode::{PrimitiveContent, Values},
21 },
22 bytes::Bytes,
23 std::collections::HashSet,
24 x509_certificate::{
25 CapturedX509Certificate, DigestAlgorithm, KeyInfoSigner, SignatureAlgorithm,
26 asn1time::UtcTime,
27 rfc5652::{Attribute, AttributeValue},
28 },
29};
30
31#[derive(Clone)]
36pub struct SignerBuilder<'a> {
37 signing_key: &'a dyn KeyInfoSigner,
39
40 signer_identifier: SignerIdentifier,
43
44 signing_certificate: Option<CapturedX509Certificate>,
46
47 digest_algorithm: DigestAlgorithm,
49
50 message_id_content: Option<Vec<u8>>,
53
54 content_type: Oid,
59
60 extra_signed_attributes: Vec<Attribute>,
62}
63
64impl<'a> SignerBuilder<'a> {
65 pub fn new(
69 signing_key: &'a dyn KeyInfoSigner,
70 signing_certificate: CapturedX509Certificate,
71 ) -> Self {
72 Self {
73 signing_key,
74 signer_identifier: SignerIdentifier::IssuerAndSerialNumber(IssuerAndSerialNumber {
75 issuer: signing_certificate.issuer_name().clone(),
76 serial_number: signing_certificate.serial_number_asn1().clone(),
77 }),
78 signing_certificate: Some(signing_certificate),
79 digest_algorithm: DigestAlgorithm::Sha256,
80 message_id_content: None,
81 content_type: Oid(Bytes::copy_from_slice(OID_ID_DATA.as_ref())),
82 extra_signed_attributes: Vec::new(),
83 }
84 }
85
86 pub fn new_with_signer_identifier(
91 signing_key: &'a dyn KeyInfoSigner,
92 signer_identifier: SignerIdentifier,
93 ) -> Self {
94 Self {
95 signing_key,
96 signer_identifier,
97 signing_certificate: None,
98 digest_algorithm: DigestAlgorithm::Sha256,
99 message_id_content: None,
100 content_type: Oid(Bytes::copy_from_slice(OID_ID_DATA.as_ref())),
101 extra_signed_attributes: Vec::new(),
102 }
103 }
104
105 pub fn signature_algorithm(&self) -> Result<SignatureAlgorithm, CmsError> {
107 Ok(self.signing_key.signature_algorithm()?)
108 }
109
110 #[must_use]
117 pub fn message_id_content(mut self, data: Vec<u8>) -> Self {
118 self.message_id_content = Some(data);
119 self
120 }
121
122 #[must_use]
124 pub fn content_type(mut self, oid: Oid) -> Self {
125 self.content_type = oid;
126 self
127 }
128
129 #[must_use]
131 pub fn signed_attribute(mut self, typ: Oid, values: Vec<AttributeValue>) -> Self {
132 self.extra_signed_attributes.push(Attribute { typ, values });
133 self
134 }
135
136 #[must_use]
141 pub fn signed_attribute_octet_string(self, typ: Oid, data: &[u8]) -> Self {
142 self.signed_attribute(
143 typ,
144 vec![AttributeValue::new(Captured::from_values(
145 Mode::Der,
146 data.encode_ref(),
147 ))],
148 )
149 }
150}
151
152enum SignedContent {
154 None,
156
157 Inline(Vec<u8>),
159
160 External(Vec<u8>),
164}
165
166pub struct SignedDataBuilder<'a> {
173 signed_content: SignedContent,
175
176 signers: Vec<SignerBuilder<'a>>,
178
179 certificates: Vec<CapturedX509Certificate>,
181
182 content_type: Oid,
188
189 signing_time: UtcTime,
193}
194
195impl Default for SignedDataBuilder<'_> {
196 fn default() -> Self {
197 Self {
198 signed_content: SignedContent::None,
199 signers: vec![],
200 certificates: vec![],
201 content_type: Oid(OID_ID_SIGNED_DATA.as_ref().into()),
202 signing_time: UtcTime::now(),
203 }
204 }
205}
206
207impl<'a> SignedDataBuilder<'a> {
208 #[must_use]
210 pub fn content_inline(mut self, content: Vec<u8>) -> Self {
211 self.signed_content = SignedContent::Inline(content);
212 self
213 }
214
215 #[must_use]
221 pub fn content_external(mut self, content: Vec<u8>) -> Self {
222 self.signed_content = SignedContent::External(content);
223 self
224 }
225
226 #[must_use]
231 pub fn signer(mut self, signer: SignerBuilder<'a>) -> Self {
232 self.signers.push(signer);
233 self
234 }
235
236 #[must_use]
238 pub fn certificate(mut self, cert: CapturedX509Certificate) -> Self {
239 if !self.certificates.iter().any(|x| x == &cert) {
240 self.certificates.push(cert);
241 }
242
243 self
244 }
245
246 #[must_use]
248 pub fn certificates(mut self, certs: impl Iterator<Item = CapturedX509Certificate>) -> Self {
249 for cert in certs {
250 if !self.certificates.iter().any(|x| x == &cert) {
251 self.certificates.push(cert);
252 }
253 }
254
255 self
256 }
257
258 #[must_use]
260 pub fn content_type(mut self, oid: Oid) -> Self {
261 self.content_type = oid;
262 self
263 }
264
265 #[must_use]
269 pub fn signing_time(mut self, time: UtcTime) -> Self {
270 self.signing_time = time;
271 self
272 }
273
274 pub fn build_signed_data(&self) -> Result<SignedData, CmsError> {
276 let mut signer_infos = SignerInfos::default();
277 let mut seen_digest_algorithms = HashSet::new();
278 let mut seen_certificates = self.certificates.clone();
279
280 for signer in &self.signers {
281 seen_digest_algorithms.insert(signer.digest_algorithm);
282
283 if let Some(signing_certificate) = &signer.signing_certificate {
284 if !seen_certificates.iter().any(|x| x == signing_certificate) {
285 seen_certificates.push(signing_certificate.clone());
286 }
287 }
288
289 let version = CmsVersion::V1;
290 let digest_algorithm = DigestAlgorithmIdentifier {
291 algorithm: signer.digest_algorithm.into(),
292 parameters: None,
293 };
294
295 let mut hasher = signer.digest_algorithm.digester();
301 if let Some(content) = &signer.message_id_content {
302 hasher.update(content);
303 } else {
304 match &self.signed_content {
305 SignedContent::None => {}
306 SignedContent::Inline(content) | SignedContent::External(content) => {
307 hasher.update(content)
308 }
309 }
310 }
311 let digest = hasher.finish();
312
313 let mut signed_attributes = SignedAttributes::default();
314
315 signed_attributes.push(Attribute {
317 typ: Oid(Bytes::copy_from_slice(OID_CONTENT_TYPE.as_ref())),
318 values: vec![AttributeValue::new(Captured::from_values(
319 Mode::Der,
320 signer.content_type.encode_ref(),
321 ))],
322 });
323
324 signed_attributes.push(Attribute {
326 typ: Oid(Bytes::copy_from_slice(OID_MESSAGE_DIGEST.as_ref())),
327 values: vec![AttributeValue::new(Captured::from_values(
328 Mode::Der,
329 digest.as_ref().encode(),
330 ))],
331 });
332
333 signed_attributes.push(Attribute {
335 typ: Oid(Bytes::copy_from_slice(OID_SIGNING_TIME.as_ref())),
336 values: vec![AttributeValue::new(Captured::from_values(
337 Mode::Der,
338 self.signing_time.clone().encode(),
339 ))],
340 });
341
342 signed_attributes.extend(signer.extra_signed_attributes.iter().cloned());
343
344 let signed_attributes = signed_attributes.as_sorted()?;
348
349 let signed_attributes = Some(signed_attributes);
350
351 let signature_algorithm = signer.signature_algorithm()?.into();
352
353 let mut signer_info = SignerInfo {
357 version,
358 sid: signer.signer_identifier.clone(),
359 digest_algorithm,
360 signed_attributes,
361 signature_algorithm,
362 signature: SignatureValue::new(Bytes::copy_from_slice(&[])),
363 unsigned_attributes: None,
364 signed_attributes_data: None,
365 };
366
367 let signed_content = signer_info
371 .signed_attributes_digested_content()?
372 .expect("presence of signed attributes should ensure this is Some(T)");
373
374 let signature = signer.signing_key.try_sign(&signed_content)?;
375 let signature_algorithm = signer.signing_key.signature_algorithm()?;
376
377 signer_info.signature = SignatureValue::new(Bytes::from(signature.clone()));
378 signer_info.signature_algorithm = signature_algorithm.into();
379
380 signer_infos.push(signer_info);
381 }
382
383 let mut digest_algorithms = DigestAlgorithmIdentifiers::default();
384 digest_algorithms.extend(seen_digest_algorithms.into_iter().map(|alg| {
385 DigestAlgorithmIdentifier {
386 algorithm: alg.into(),
387 parameters: None,
388 }
389 }));
390
391 seen_certificates.sort_by(|a, b| a.compare_issuer(b));
395
396 let mut certificates = CertificateSet::default();
397 certificates.extend(
398 seen_certificates
399 .into_iter()
400 .map(|cert| CertificateChoices::Certificate(Box::new(cert.into()))),
401 );
402
403 let signed_data = SignedData {
407 version: CmsVersion::V1,
408 digest_algorithms,
409 content_info: EncapsulatedContentInfo {
410 content_type: self.content_type.clone(),
411 content: match &self.signed_content {
412 SignedContent::None | SignedContent::External(_) => None,
413 SignedContent::Inline(content) => {
414 Some(OctetString::new(Bytes::copy_from_slice(content)))
415 }
416 },
417 },
418 certificates: if certificates.is_empty() {
419 None
420 } else {
421 Some(certificates)
422 },
423 crls: None,
424 signer_infos,
425 };
426
427 Ok(signed_data)
428 }
429
430 pub fn build_der(&self) -> Result<Vec<u8>, CmsError> {
436 let signed_data = self.build_signed_data()?;
437
438 let mut ber = Vec::new();
439 signed_data
440 .encode_ref()
441 .write_encoded(Mode::Der, &mut ber)?;
442
443 Ok(ber)
444 }
445}
446
447#[cfg(test)]
448mod tests {
449 use {
450 super::*,
451 crate::SignedData,
452 x509_certificate::{EcdsaCurve, testutil::*},
453 };
454
455 const DIGICERT_TIMESTAMP_URL: &str = "http://timestamp.digicert.com";
456
457 #[test]
458 fn simple_rsa_signature_inline() {
459 let key = rsa_private_key();
460 let cert = rsa_cert();
461
462 let signer = SignerBuilder::new(&key, cert);
463
464 let ber = SignedDataBuilder::default()
465 .content_inline(vec![42])
466 .signer(signer)
467 .build_der()
468 .unwrap();
469
470 let signed_data = crate::SignedData::parse_ber(&ber).unwrap();
471 assert_eq!(signed_data.signed_content(), Some(vec![42].as_ref()));
472
473 for signer in signed_data.signers() {
474 signer
475 .verify_message_digest_with_signed_data(&signed_data)
476 .unwrap();
477 signer
478 .verify_signature_with_signed_data(&signed_data)
479 .unwrap();
480 assert!(signer.unsigned_attributes.is_none());
481 }
482 }
483
484 #[test]
485 fn simple_rsa_signature_external() {
486 let key = rsa_private_key();
487 let cert = rsa_cert();
488
489 let signer = SignerBuilder::new(&key, cert);
490
491 let ber = SignedDataBuilder::default()
492 .content_external(vec![42])
493 .signer(signer)
494 .build_der()
495 .unwrap();
496
497 let signed_data = crate::SignedData::parse_ber(&ber).unwrap();
498 assert!(signed_data.signed_content().is_none());
499
500 for signer in signed_data.signers() {
501 signer.verify_message_digest_with_content(&[42]).unwrap();
502 signer
503 .verify_signature_with_signed_data(&signed_data)
504 .unwrap();
505 assert!(signer.unsigned_attributes.is_none());
506 }
507 }
508
509 #[test]
510 fn time_stamp_url() {
511 let key = rsa_private_key();
512 let cert = rsa_cert();
513
514 let signer = SignerBuilder::new(&key, cert)
515 .time_stamp_url(DIGICERT_TIMESTAMP_URL)
516 .unwrap();
517
518 let ber = SignedDataBuilder::default()
519 .content_inline(vec![42])
520 .signer(signer)
521 .build_der()
522 .unwrap();
523
524 let signed_data = crate::SignedData::parse_ber(&ber).unwrap();
525
526 for signer in signed_data.signers() {
527 let unsigned = signer.unsigned_attributes().unwrap();
528 let tst = unsigned.time_stamp_token.as_ref().unwrap();
529 assert!(tst.certificates.is_some());
530
531 let tst_signed_data = signer.time_stamp_token_signed_data().unwrap().unwrap();
532 for signer in tst_signed_data.signers() {
533 signer
534 .verify_message_digest_with_signed_data(&tst_signed_data)
535 .unwrap();
536 signer
537 .verify_signature_with_signed_data(&tst_signed_data)
538 .unwrap();
539 }
540
541 assert!(signer.verify_time_stamp_token().unwrap().is_some());
542 }
543 }
544
545 #[test]
546 fn simple_ecdsa_signature() {
547 for curve in EcdsaCurve::all() {
548 let (cert, key) = self_signed_ecdsa_key_pair(Some(*curve));
549
550 let cms = SignedDataBuilder::default()
551 .content_inline("hello world".as_bytes().to_vec())
552 .certificate(cert.clone())
553 .signer(SignerBuilder::new(&key, cert))
554 .build_der()
555 .unwrap();
556
557 let signed_data = SignedData::parse_ber(&cms).unwrap();
558
559 for signer in signed_data.signers() {
560 signer
561 .verify_signature_with_signed_data(&signed_data)
562 .unwrap();
563 }
564 }
565 }
566
567 #[test]
568 fn simple_ed25519_signature() {
569 let (cert, key) = self_signed_ed25519_key_pair();
570
571 let cms = SignedDataBuilder::default()
572 .content_inline("hello world".as_bytes().to_vec())
573 .certificate(cert.clone())
574 .signer(SignerBuilder::new(&key, cert))
575 .build_der()
576 .unwrap();
577
578 let signed_data = SignedData::parse_ber(&cms).unwrap();
579
580 for signer in signed_data.signers() {
581 signer
582 .verify_signature_with_signed_data(&signed_data)
583 .unwrap();
584 }
585 }
586}