From 5fecdb9cee0fa6d3c3bbe4a7a9f81a5fbeefdfcb Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Tue, 27 Oct 2026 23:25:40 +0000 Subject: [PATCH] Group signing and timestamp validation inputs --- crates/sign/src/cms.rs | 27 +++++++++------- crates/sign/src/pdf/validate.rs | 57 +++++++++++++++++---------------- crates/sign/src/timestamp.rs | 30 ++++++++++------- crates/sign/tests/it/pdf.rs | 37 ++++++++++++++------- 4 files changed, 89 insertions(+), 62 deletions(-) diff --git a/crates/sign/src/cms.rs b/crates/sign/src/cms.rs index b148ea4d1..4e232af61 100644 --- a/crates/sign/src/cms.rs +++ b/crates/sign/src/cms.rs @@ -376,7 +376,7 @@ pub fn sign_detached( alg: DigestAlg, content_digest: &[u8], ) -> Result, SignError> { - build(key, cert, chain, alg, DATA, None, content_digest) + build(SignedDataInput { key, cert, chain, alg, content_type: DATA, content: None, content_digest }) } /// A CMS SignedData that encapsulates `content` under `content_type` (an RFC 3161 token wraps @@ -389,20 +389,23 @@ pub fn sign_encapsulated( content_type: &str, content: &[u8], ) -> Result, SignError> { - build(key, cert, chain, alg, content_type, Some(content), &alg.digest(&[content])) + let content_digest = alg.digest(&[content]); + build(SignedDataInput { key, cert, chain, alg, content_type, content: Some(content), content_digest: &content_digest }) } -// The parameters mirror the SignedData fields being assembled. -#[allow(clippy::too_many_arguments)] -fn build( - key: &PrivateKey, - cert: &Certificate, - chain: &[Certificate], +/// The values needed to assemble a CMS SignedData object. +struct SignedDataInput<'a> { + key: &'a PrivateKey, + cert: &'a Certificate, + chain: &'a [Certificate], alg: DigestAlg, - content_type: &str, - content: Option<&[u8]>, - content_digest: &[u8], -) -> Result, SignError> { + content_type: &'a str, + content: Option<&'a [u8]>, + content_digest: &'a [u8], +} + +fn build(input: SignedDataInput<'_>) -> Result, SignError> { + let SignedDataInput { key, cert, chain, alg, content_type, content, content_digest } = input; let cert_hash = DigestAlg::Sha256.digest(&[&cert.raw]); let general_names = der::seq(&[&der::explicit(4, &cert.issuer.raw)]); let ess = der::seq(&[&der::seq(&[&der::seq(&[&der::octets(&cert_hash), &der::seq(&[&general_names, &der::uint(&cert.serial)])])])]); diff --git a/crates/sign/src/pdf/validate.rs b/crates/sign/src/pdf/validate.rs index 668798c20..08b482c4b 100644 --- a/crates/sign/src/pdf/validate.rs +++ b/crates/sign/src/pdf/validate.rs @@ -5,6 +5,22 @@ use super::{ Certificate, Dict, DigestAlg, Document, HashSet, ObjRef, Object, SignError, SignatureInfo, SignedData, Time, build_chain, build_chain_noted, }; +struct SignatureValidation<'a> { + doc: &'a Document, + bytes: &'a [u8], + trust: &'a TrustStore, + info: &'a mut SignatureInfo, + cache: &'a DigestCache, +} + +struct VerifiedSignature<'a> { + covered: usize, + certificate: Certificate, + embedded: &'a [Certificate], + cms_time: Option