Skip to content

Commit 13e0bbe

Browse files
authored
cms: adds support for AsyncSigner (#1533)
1 parent 52f302d commit 13e0bbe

File tree

4 files changed

+124
-2
lines changed

4 files changed

+124
-2
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cms/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const-oid = { version = "0.10.0-rc.0", features = ["db"] }
2222

2323
# optional dependencies
2424
aes = { version = "=0.9.0-pre.1", optional = true }
25+
async-signature = { version = "=0.6.0-pre.4", features = ["digest", "rand_core"], optional = true }
2526
cbc = { version = "=0.2.0-pre.1", optional = true }
2627
cipher = { version = "=0.5.0-pre.6", features = ["alloc", "block-padding", "rand_core"], optional = true }
2728
rsa = { version = "=0.10.0-pre.2", optional = true }
@@ -40,11 +41,12 @@ rand = "0.8.5"
4041
rsa = { version = "=0.10.0-pre.2", features = ["sha2"] }
4142
ecdsa = { version = "=0.17.0-pre.9", features = ["digest", "pem"] }
4243
p256 = "=0.14.0-pre.2"
44+
tokio = { version = "1.40.0", features = ["macros", "rt"] }
4345

4446
[features]
4547
alloc = ["der/alloc"]
4648
std = ["der/std", "spki/std"]
47-
builder = ["aes", "cbc", "cipher", "rsa", "sha1", "sha2", "sha3", "signature", "std", "spki/alloc", "x509-cert/builder", "zeroize"]
49+
builder = ["aes", "async-signature", "cbc", "cipher", "rsa", "sha1", "sha2", "sha3", "signature", "std", "spki/alloc", "x509-cert/builder", "zeroize"]
4850
pem = ["alloc", "der/pem"]
4951

5052
[package.metadata.docs.rs]

cms/src/builder.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use alloc::borrow::ToOwned;
1919
use alloc::boxed::Box;
2020
use alloc::string::String;
2121
use alloc::vec::Vec;
22+
use async_signature::{AsyncRandomizedSigner, AsyncSigner};
2223
use cipher::{
2324
block_padding::Pkcs7,
2425
rand_core::{self, CryptoRng, CryptoRngCore, RngCore},
@@ -43,7 +44,7 @@ use spki::{
4344
use std::time::SystemTime;
4445
use std::vec;
4546
use x509_cert::attr::{Attribute, AttributeValue, Attributes};
46-
use x509_cert::builder::{self, Builder};
47+
use x509_cert::builder::{self, AsyncBuilder, Builder};
4748
use zeroize::Zeroize;
4849

4950
/// Error type
@@ -426,6 +427,51 @@ impl<'s> SignedDataBuilder<'s> {
426427
Ok(self)
427428
}
428429

430+
/// Add a signer info. The signature will be calculated. Note that the encapsulated content
431+
/// must not be changed after the first signer info was added.
432+
pub async fn add_signer_info_async<S, Signature>(
433+
&mut self,
434+
signer_info_builder: SignerInfoBuilder<'_>,
435+
signer: &S,
436+
) -> Result<&mut Self>
437+
where
438+
S: Keypair + DynSignatureAlgorithmIdentifier,
439+
S: AsyncSigner<Signature>,
440+
S::VerifyingKey: EncodePublicKey,
441+
Signature: SignatureBitStringEncoding + 'static,
442+
{
443+
let signer_info = signer_info_builder
444+
.build_async::<S, Signature>(signer)
445+
.await
446+
.map_err(|_| der::Error::from(ErrorKind::Failed))?;
447+
self.signer_infos.push(signer_info);
448+
449+
Ok(self)
450+
}
451+
452+
/// Add a signer info. The signature will be calculated. Note that the encapsulated content
453+
/// must not be changed after the first signer info was added.
454+
pub async fn add_signer_info_with_rng_async<S, Signature>(
455+
&mut self,
456+
signer_info_builder: SignerInfoBuilder<'_>,
457+
signer: &S,
458+
rng: &mut impl CryptoRngCore,
459+
) -> Result<&mut Self>
460+
where
461+
S: Keypair + DynSignatureAlgorithmIdentifier,
462+
S: AsyncRandomizedSigner<Signature>,
463+
S::VerifyingKey: EncodePublicKey,
464+
Signature: SignatureBitStringEncoding + 'static,
465+
{
466+
let signer_info = signer_info_builder
467+
.build_with_rng_async::<S, Signature>(signer, rng)
468+
.await
469+
.map_err(|_| der::Error::from(ErrorKind::Failed))?;
470+
self.signer_infos.push(signer_info);
471+
472+
Ok(self)
473+
}
474+
429475
/// This method returns a `ContentInfo` of type `signedData`.
430476
pub fn build(&mut self) -> Result<ContentInfo> {
431477
let digest_algorithms =

cms/tests/builder.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,3 +595,75 @@ fn test_create_signing_attribute() {
595595
"Invalid tag number in signing time attribute value"
596596
);
597597
}
598+
599+
#[tokio::test]
600+
async fn async_builder() {
601+
// Make some content
602+
let content = EncapsulatedContentInfo {
603+
econtent_type: const_oid::db::rfc5911::ID_DATA,
604+
econtent: Some(
605+
Any::new(
606+
Tag::OctetString,
607+
OctetString::new(vec![48]).unwrap().to_der().unwrap(),
608+
)
609+
.unwrap(),
610+
),
611+
};
612+
// Create multiple signer infos
613+
let signer_1 = rsa_pkcs1v15_signer();
614+
let digest_algorithm = AlgorithmIdentifierOwned {
615+
oid: const_oid::db::rfc5912::ID_SHA_256,
616+
parameters: None,
617+
};
618+
let external_message_digest = None;
619+
let signer_info_builder_1 = SignerInfoBuilder::new(
620+
signer_identifier(1),
621+
digest_algorithm.clone(),
622+
&content,
623+
external_message_digest,
624+
)
625+
.expect("Could not create RSA SignerInfoBuilder");
626+
627+
let signer_3 = rsa_pss_signer();
628+
let digest_algorithm = AlgorithmIdentifierOwned {
629+
oid: const_oid::db::rfc5912::ID_SHA_256,
630+
parameters: None,
631+
};
632+
let external_message_digest = None;
633+
let signer_info_builder_3 = SignerInfoBuilder::new(
634+
signer_identifier(3),
635+
digest_algorithm.clone(),
636+
&content,
637+
external_message_digest,
638+
)
639+
.expect("Could not create RSA SignerInfoBuilder");
640+
641+
let mut builder = SignedDataBuilder::new(&content);
642+
643+
let signed_data_pkcs7 = builder
644+
.add_digest_algorithm(digest_algorithm)
645+
.expect("could not add a digest algorithm")
646+
.add_signer_info_async::<pkcs1v15::SigningKey<Sha256>, rsa::pkcs1v15::Signature>(
647+
signer_info_builder_1,
648+
&signer_1,
649+
)
650+
.await
651+
.expect("error adding PKCS1v15 RSA signer info")
652+
.add_signer_info_with_rng_async::<pss::SigningKey<Sha256>, pss::Signature>(
653+
signer_info_builder_3,
654+
&signer_3,
655+
&mut OsRng,
656+
)
657+
.await
658+
.expect("error adding PKCS1v15 RSA signer info")
659+
.build()
660+
.expect("building signed data failed");
661+
let signed_data_pkcs7_der = signed_data_pkcs7
662+
.to_der()
663+
.expect("conversion of signed data to DER failed.");
664+
println!(
665+
"{}",
666+
pem_rfc7468::encode_string("PKCS7", LineEnding::LF, &signed_data_pkcs7_der)
667+
.expect("PEM encoding of signed data DER failed")
668+
);
669+
}

0 commit comments

Comments
 (0)