From e2e211455cacc15839da897199699db3a5b59881 Mon Sep 17 00:00:00 2001 From: Konradsop Date: Thu, 30 Jul 2026 17:36:44 +0200 Subject: [PATCH] Add XML documentation for CMS SignedData parser --- crypto/src/cms/CMSSignedDataParser.cs | 241 ++++++++++---------------- 1 file changed, 96 insertions(+), 145 deletions(-) diff --git a/crypto/src/cms/CMSSignedDataParser.cs b/crypto/src/cms/CMSSignedDataParser.cs index c419c1f61..bb49ba4af 100644 --- a/crypto/src/cms/CMSSignedDataParser.cs +++ b/crypto/src/cms/CMSSignedDataParser.cs @@ -13,58 +13,32 @@ namespace Org.BouncyCastle.Cms { - /** - * Parsing class for an CMS Signed Data object from an input stream. - *

- * Note: that because we are in a streaming mode only one signer can be tried and it is important - * that the methods on the parser are called in the appropriate order. - *

- *

- * A simple example of usage for an encapsulated signature. - *

- *

- * Two notes: first, in the example below the validity of - * the certificate isn't verified, just the fact that one of the certs - * matches the given signer, and, second, because we are in a streaming - * mode the order of the operations is important. - *

- *
-     *      CmsSignedDataParser     sp = new CmsSignedDataParser(encapSigData);
-     *
-     *      sp.GetSignedContent().Drain();
-     *
-     *      IX509Store              certs = sp.GetCertificates();
-     *      SignerInformationStore  signers = sp.GetSignerInfos();
-     *
-     *      foreach (SignerInformation signer in signers.GetSigners())
-     *      {
-     *          ArrayList       certList = new ArrayList(certs.GetMatches(signer.SignerID));
-     *          X509Certificate cert = (X509Certificate) certList[0];
-     *
-     *          Console.WriteLine("verify returns: " + signer.Verify(cert));
-     *      }
-     * 
- * Note also: this class does not introduce buffering - if you are processing large files you should create - * the parser with: - *
-     *          CmsSignedDataParser     ep = new CmsSignedDataParser(new BufferedInputStream(encapSigData, bufSize));
-     *  
- * where bufSize is a suitably large buffer size. - *

- * Stream handling note: - *

- *

- */ + /// + /// Streaming parser for CMS SignedData messages, the counterpart to . In streaming + /// mode only one signer can be verified per pass and parser methods must be called in order. + /// + /// + /// The constructor reads only enough of the supplied stream to expose digest algorithms and signed-content + /// metadata. Encapsulated content must be drained (for example via and + /// ) before calling so running digests can be + /// finalized. + /// The supplied stream is not closed automatically. Dispose this parser to close the underlying stream, + /// or close it yourself. + /// This class does not introduce buffering. For large inputs, pass a buffered stream with a suitably + /// large buffer size. + /// Example (encapsulated content): + /// + /// CmsSignedDataParser sp = new CmsSignedDataParser(sigData); + /// sp.GetSignedContent().Drain(); + /// IStore<X509Certificate> certs = sp.GetCertificates(); + /// SignerInformationStore signers = sp.GetSignerInfos(); + /// foreach (SignerInformation signer in signers.GetSigners()) + /// { + /// X509Certificate cert = certs.GetMatches(signer.SignerID).First(); + /// signer.Verify(cert); + /// } + /// + /// public class CmsSignedDataParser : CmsContentInfoParser { @@ -79,30 +53,35 @@ public class CmsSignedDataParser private Asn1Set _certSet, _crlSet; private bool _isCertCrlParsed; + /// Creates a parser from an encoded SignedData message with encapsulated content. + /// The DER-encoded CMS ContentInfo bytes. public CmsSignedDataParser(byte[] sigBlock) : this(new MemoryStream(sigBlock, false)) { } + /// + /// Creates a parser from detached content and an encoded SignedData message without encapsulated content. + /// + /// The content that was signed. + /// The DER-encoded CMS ContentInfo bytes. public CmsSignedDataParser(CmsTypedStream signedContent, byte[] sigBlock) : this(signedContent, new MemoryStream(sigBlock, false)) { } - /** - * base constructor - with encapsulated content - */ + /// Creates a parser from an encoded SignedData message with encapsulated content. + /// The stream containing the DER-encoded CMS ContentInfo. public CmsSignedDataParser(Stream sigData) : this(null, sigData) { } - /** - * base constructor - * - * @param signedContent the content that was signed. - * @param sigData the signature object. - */ + /// Creates a parser from optional detached content and an encoded SignedData message. + /// The detached signed content, or null when content is encapsulated. + /// The stream containing the DER-encoded CMS ContentInfo. + /// is null. + /// The stream cannot be parsed as CMS SignedData. public CmsSignedDataParser(CmsTypedStream signedContent, Stream sigData) : base(sigData) { @@ -166,13 +145,10 @@ public CmsSignedDataParser(CmsTypedStream signedContent, Stream sigData) } } - /** - * Return the version number for the SignedData object - * - * @return the version number - */ + /// Gets the SignedData version number. public int Version => _signedData.Version.IntValueExact; + /// Gets the digest algorithm OIDs for which running digests are maintained. public ISet DigestOids { get @@ -186,11 +162,8 @@ public ISet DigestOids } } - /** - * return the collection of signers that are associated with the - * signatures for the message. - * @throws CmsException - */ + /// Returns a store of signers associated with the message signatures. + /// The signer information cannot be parsed. public SignerInformationStore GetSignerInfos() { if (_signerInfoStore == null) @@ -230,15 +203,8 @@ public SignerInformationStore GetSignerInfos() return _signerInfoStore; } - /** - * return a X509Store containing the attribute certificates, if any, contained - * in this message. - * - * @param type type of store to create - * @return a store of attribute certificates - * @exception Org.BouncyCastle.X509.NoSuchStoreException if the store type isn't available. - * @exception CmsException if a general exception prevents creation of the X509Store - */ + /// Returns a store of attribute certificates carried in the message, if any. + /// The certificate set cannot be parsed. public IStore GetAttributeCertificates() { PopulateCertCrlSets(); @@ -246,15 +212,8 @@ public IStore GetAttributeCertificates() return CmsSignedHelper.GetAttributeCertificates(_certSet); } - /** - * return a X509Store containing the public key certificates, if any, contained - * in this message. - * - * @param type type of store to create - * @return a store of public key certificates - * @exception NoSuchStoreException if the store type isn't available. - * @exception CmsException if a general exception prevents creation of the X509Store - */ + /// Returns a store of public-key certificates carried in the message, if any. + /// The certificate set cannot be parsed. public IStore GetCertificates() { PopulateCertCrlSets(); @@ -262,15 +221,8 @@ public IStore GetCertificates() return CmsSignedHelper.GetCertificates(_certSet); } - /** - * return a X509Store containing CRLs, if any, contained - * in this message. - * - * @param type type of store to create - * @return a store of CRLs - * @exception NoSuchStoreException if the store type isn't available. - * @exception CmsException if a general exception prevents creation of the X509Store - */ + /// Returns a store of CRLs carried in the message, if any. + /// The CRL set cannot be parsed. public IStore GetCrls() { PopulateCertCrlSets(); @@ -278,6 +230,9 @@ public IStore GetCrls() return CmsSignedHelper.GetCrls(_crlSet); } + /// Returns a store of other revocation information entries of the given format, if any. + /// The other revocation information format OID to select. + /// The revocation set cannot be parsed. public IStore GetOtherRevInfos(DerObjectIdentifier otherRevInfoFormat) { PopulateCertCrlSets(); @@ -285,31 +240,14 @@ public IStore GetOtherRevInfos(DerObjectIdentifier otherRevInfoFo return CmsSignedHelper.GetOtherRevInfos(_crlSet, otherRevInfoFormat); } - private void PopulateCertCrlSets() - { - if (_isCertCrlParsed) - return; - - _isCertCrlParsed = true; - - try - { - // care! Streaming - Must process the GetCertificates() result before calling GetCrls() - _certSet = GetAsn1Set(_signedData.GetCertificates()); - _crlSet = GetAsn1Set(_signedData.GetCrls()); - } - catch (IOException e) - { - throw new CmsException("problem parsing cert/crl sets", e); - } - } + /// Gets the content type OID of the signed encapsulated content. + public DerObjectIdentifier SignedContentType => _signedContentType; /// - /// Return the DerObjectIdentifier associated with the encapsulated - /// content info structure carried in the signed data. + /// Returns a stream over the signed content with digest calculators attached, or null if no content is + /// present. /// - public DerObjectIdentifier SignedContentType => _signedContentType; - + /// A typed stream over the signed content, or null. public CmsTypedStream GetSignedContent() { if (_signedContent == null) @@ -325,19 +263,14 @@ public CmsTypedStream GetSignedContent() return new CmsTypedStream(_signedContent.ContentTypeOid, digStream); } - /** - * Replace the signerinformation store associated with the passed - * in message contained in the stream original with the new one passed in. - * You would probably only want to do this if you wanted to change the unsigned - * attributes associated with a signer, or perhaps delete one. - *

- * The output stream is returned unclosed. - *

- * @param original the signed data stream to be used as a base. - * @param signerInformationStore the new signer information store to use. - * @param out the stream to Write the new signed data object to. - * @return out. - */ + /// + /// Writes a copy of SignedData to with signers replaced + /// by . The output stream is returned unclosed. + /// + /// The signed-data stream to use as a base. + /// The replacement signer information. + /// The stream to receive the new SignedData object. + /// . public static Stream ReplaceSigners(Stream original, SignerInformationStore signerInformationStore, Stream outStr) { @@ -367,18 +300,17 @@ public static Stream ReplaceSigners(Stream original, SignerInformationStore sign return outStr; } - /** - * Replace the certificate and CRL information associated with this - * CMSSignedData object with the new one passed in. - *

- * The output stream is returned unclosed. - *

- * @param original the signed data stream to be used as a base. - * @param certsAndCrls the new certificates and CRLs to be used. - * @param out the stream to Write the new signed data object to. - * @return out. - * @exception CmsException if there is an error processing the CertStore - */ + /// + /// Writes a copy of SignedData to with certificates and + /// CRLs replaced. The output stream is returned unclosed. + /// + /// The signed-data stream to use as a base. + /// Replacement public-key certificates, or null to omit. + /// Replacement CRLs, or null to omit. + /// Replacement attribute certificates, or null to omit. + /// The stream to receive the new SignedData object. + /// . + /// The signed-data stream cannot be processed. public static Stream ReplaceCertificatesAndCrls(Stream original, IStore x509Certs, IStore x509Crls, IStore x509AttrCerts, Stream outStr) { @@ -416,6 +348,25 @@ public static Stream ReplaceCertificatesAndCrls(Stream original, IStore