|
1 | 1 | //! X509 Certificate builder |
2 | 2 |
|
3 | 3 | use alloc::vec; |
| 4 | +use async_signature::{AsyncRandomizedSigner, AsyncSigner}; |
4 | 5 | use core::fmt; |
5 | 6 | use der::{asn1::BitString, referenced::OwnedToRef, Encode}; |
6 | 7 | use signature::{rand_core::CryptoRngCore, Keypair, RandomizedSigner, Signer}; |
@@ -538,3 +539,86 @@ impl Builder for RequestBuilder { |
538 | 539 | }) |
539 | 540 | } |
540 | 541 | } |
| 542 | + |
| 543 | +/// Trait for async X509 builders |
| 544 | +/// |
| 545 | +/// This trait defines the interface between builder and the signers. |
| 546 | +/// |
| 547 | +/// This is the async counterpart of [`Builder`]. |
| 548 | +#[allow(async_fn_in_trait)] |
| 549 | +pub trait AsyncBuilder: Sized { |
| 550 | + /// Type built by this builder |
| 551 | + type Output: Sized; |
| 552 | + |
| 553 | + /// Assemble the final object from signature. |
| 554 | + fn assemble<S>(self, signature: BitString, signer: &S) -> Result<Self::Output> |
| 555 | + where |
| 556 | + S: Keypair + DynSignatureAlgorithmIdentifier, |
| 557 | + S::VerifyingKey: EncodePublicKey; |
| 558 | + |
| 559 | + /// Finalize and return a serialization of the object for signature. |
| 560 | + fn finalize<S>(&mut self, signer: &S) -> Result<vec::Vec<u8>> |
| 561 | + where |
| 562 | + S: Keypair + DynSignatureAlgorithmIdentifier, |
| 563 | + S::VerifyingKey: EncodePublicKey; |
| 564 | + |
| 565 | + /// Run the object through the signer and build it. |
| 566 | + async fn build_async<S, Signature: 'static>(mut self, signer: &S) -> Result<Self::Output> |
| 567 | + where |
| 568 | + S: AsyncSigner<Signature>, |
| 569 | + S: Keypair + DynSignatureAlgorithmIdentifier, |
| 570 | + S::VerifyingKey: EncodePublicKey, |
| 571 | + Signature: SignatureBitStringEncoding, |
| 572 | + { |
| 573 | + let blob = self.finalize(signer)?; |
| 574 | + |
| 575 | + let signature = signer.sign_async(&blob).await?.to_bitstring()?; |
| 576 | + |
| 577 | + self.assemble(signature, signer) |
| 578 | + } |
| 579 | + |
| 580 | + /// Run the object through the signer and build it. |
| 581 | + async fn build_with_rng_async<S, Signature: 'static>( |
| 582 | + mut self, |
| 583 | + signer: &S, |
| 584 | + rng: &mut impl CryptoRngCore, |
| 585 | + ) -> Result<Self::Output> |
| 586 | + where |
| 587 | + S: AsyncRandomizedSigner<Signature>, |
| 588 | + S: Keypair + DynSignatureAlgorithmIdentifier, |
| 589 | + S::VerifyingKey: EncodePublicKey, |
| 590 | + Signature: SignatureBitStringEncoding, |
| 591 | + { |
| 592 | + let blob = self.finalize(signer)?; |
| 593 | + |
| 594 | + let signature = signer |
| 595 | + .try_sign_with_rng_async(rng, &blob) |
| 596 | + .await? |
| 597 | + .to_bitstring()?; |
| 598 | + |
| 599 | + self.assemble(signature, signer) |
| 600 | + } |
| 601 | +} |
| 602 | + |
| 603 | +impl<T> AsyncBuilder for T |
| 604 | +where |
| 605 | + T: Builder, |
| 606 | +{ |
| 607 | + type Output = <T as Builder>::Output; |
| 608 | + |
| 609 | + fn assemble<S>(self, signature: BitString, signer: &S) -> Result<Self::Output> |
| 610 | + where |
| 611 | + S: Keypair + DynSignatureAlgorithmIdentifier, |
| 612 | + S::VerifyingKey: EncodePublicKey, |
| 613 | + { |
| 614 | + <T as Builder>::assemble(self, signature, signer) |
| 615 | + } |
| 616 | + |
| 617 | + fn finalize<S>(&mut self, signer: &S) -> Result<vec::Vec<u8>> |
| 618 | + where |
| 619 | + S: Keypair + DynSignatureAlgorithmIdentifier, |
| 620 | + S::VerifyingKey: EncodePublicKey, |
| 621 | + { |
| 622 | + <T as Builder>::finalize(self, signer) |
| 623 | + } |
| 624 | +} |
0 commit comments