summary refs log tree commit diff
path: root/crypto/src/cms/CMSSignedData.cs
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-07-24 17:35:02 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-07-24 17:35:02 +0700
commita4eccbf1b23c10003c0fb2b8e73144cbd3d68d2c (patch)
tree4b5b379d5ab1db3224cb1911f1ccf51b9e8e5462 /crypto/src/cms/CMSSignedData.cs
parentRefactoring in Cms (diff)
downloadBouncyCastle.NET-ed25519-a4eccbf1b23c10003c0fb2b8e73144cbd3d68d2c.tar.xz
Updates to Cms from bc-java
Diffstat (limited to 'crypto/src/cms/CMSSignedData.cs')
-rw-r--r--crypto/src/cms/CMSSignedData.cs184
1 files changed, 147 insertions, 37 deletions
diff --git a/crypto/src/cms/CMSSignedData.cs b/crypto/src/cms/CMSSignedData.cs
index 5a73df4f1..bfe4705e7 100644
--- a/crypto/src/cms/CMSSignedData.cs
+++ b/crypto/src/cms/CMSSignedData.cs
@@ -4,6 +4,7 @@ using System.IO;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Utilities.Collections;
 using Org.BouncyCastle.X509;
 
@@ -35,6 +36,8 @@ namespace Org.BouncyCastle.Cms
 	public class CmsSignedData
 	{
 		private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
+        internal static readonly DefaultDigestAlgorithmIdentifierFinder DigestAlgIDFinder =
+			new DefaultDigestAlgorithmIdentifierFinder();
 
 		private readonly CmsProcessable	signedContent;
 		private SignedData				signedData;
@@ -209,11 +212,30 @@ namespace Org.BouncyCastle.Cms
 			return Helper.GetOtherRevInfos(signedData.CRLs, otherRevInfoFormat);
 		}
 
-		/// <summary>
-		/// Return the <c>DerObjectIdentifier</c> associated with the encapsulated
-		/// content info structure carried in the signed data.
-		/// </summary>
-		public DerObjectIdentifier SignedContentType
+        /**
+         * Return the digest algorithm identifiers for the SignedData object
+         *
+         * @return the set of digest algorithm identifiers
+         */
+        public ISet<AlgorithmIdentifier> GetDigestAlgorithmIDs()
+        {
+			var digestAlgorithms = signedData.DigestAlgorithms;
+
+            HashSet<AlgorithmIdentifier> result = new HashSet<AlgorithmIdentifier>();
+
+			foreach (var entry in digestAlgorithms)
+			{
+                result.Add(AlgorithmIdentifier.GetInstance(entry));
+			}
+
+			return CollectionUtilities.ReadOnly(result);
+        }
+
+        /// <summary>
+        /// Return the <c>DerObjectIdentifier</c> associated with the encapsulated
+        /// content info structure carried in the signed data.
+        /// </summary>
+        public DerObjectIdentifier SignedContentType
 		{
 			get { return signedData.EncapContentInfo.ContentType; }
 		}
@@ -249,59 +271,147 @@ namespace Org.BouncyCastle.Cms
             return contentInfo.GetEncoded(encoding);
         }
 
-		/**
-		* Replace the signerinformation store associated with this
-		* CmsSignedData object 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.
-		*
-		* @param signedData the signed data object to be used as a base.
-		* @param signerInformationStore the new signer information store to use.
-		* @return a new signed data object.
-		*/
-		public static CmsSignedData ReplaceSigners(
-			CmsSignedData           signedData,
-			SignerInformationStore  signerInformationStore)
+        /**
+         * Return a new CMSSignedData which guarantees to have the passed in digestAlgorithm
+         * in it. Uses the current DigestAlgorithmIdentifierFinder for creating the digest sets.
+         *
+         * @param signedData      the signed data object to be used as a base.
+         * @param digestAlgorithm the digest algorithm to be added to the signed data.
+         * @return a new signed data object.
+         */
+        public static CmsSignedData AddDigestAlgorithm(CmsSignedData signedData, AlgorithmIdentifier digestAlgorithm) =>
+            AddDigestAlgorithm(signedData, digestAlgorithm, DigestAlgIDFinder);
+
+        /**
+         * Return a new CMSSignedData which guarantees to have the passed in digestAlgorithm
+         * in it. Uses the passed in DigestAlgorithmIdentifierFinder for creating the digest sets.
+         *
+         * @param signedData      the signed data object to be used as a base.
+         * @param digestAlgorithm the digest algorithm to be added to the signed data.
+         * @param digestAlgIDFinder      the digest algorithmID map to generate the digest set with.
+         * @return a new signed data object.
+         */
+        public static CmsSignedData AddDigestAlgorithm(CmsSignedData signedData, AlgorithmIdentifier digestAlgorithm,
+			DefaultDigestAlgorithmIdentifierFinder digestAlgIDFinder)
 		{
+			ISet<AlgorithmIdentifier> digestAlgorithms = signedData.GetDigestAlgorithmIDs();
+			AlgorithmIdentifier digestAlg = Helper.FixDigestAlgID(digestAlgorithm, digestAlgIDFinder);
+
 			//
-			// copy
+			// if the algorithm is already present there is no need to add it.
 			//
-			CmsSignedData cms = new CmsSignedData(signedData);
+			if (digestAlgorithms.Contains(digestAlg))
+				return signedData;
 
 			//
-			// replace the store
+			// copy
 			//
-			cms.signerInfoStore = signerInformationStore;
+			CmsSignedData cms = new CmsSignedData(signedData);
+
+            //
+            // build up the new set
+            //
+            HashSet<AlgorithmIdentifier> digestAlgs = new HashSet<AlgorithmIdentifier>();
+
+            foreach (var entry in digestAlgs)
+			{
+				digestAlgs.Add(Helper.FixDigestAlgID(entry, digestAlgIDFinder));
+			}
+			digestAlgs.Add(digestAlg);
+
+			Asn1Set digests = CmsUtilities.ConvertToDLSet(digestAlgs);
+			Asn1Sequence sD = (Asn1Sequence)signedData.signedData.ToAsn1Object();
+
+            //
+            // signers are the last item in the sequence.
+            //
+            Asn1EncodableVector vec = new Asn1EncodableVector(sD.Count);
+            vec.Add(sD[0]); // version
+			vec.Add(digests);
+
+			for (int i = 2; i != sD.Count; i++)
+			{
+				vec.Add(sD[i]);
+			}
+
+			cms.signedData = SignedData.GetInstance(new BerSequence(vec));
 
 			//
-			// replace the signers in the SignedData object
+			// replace the contentInfo with the new one
 			//
-			var storeSigners = signerInformationStore.GetSigners();
-            Asn1EncodableVector digestAlgs = new Asn1EncodableVector(storeSigners.Count);
-            Asn1EncodableVector vec = new Asn1EncodableVector(storeSigners.Count);
-            foreach (SignerInformation signer in storeSigners)
+			cms.contentInfo = new ContentInfo(cms.contentInfo.ContentType, cms.signedData);
+
+			return cms;
+		}
+
+        /**
+		 * Replace the SignerInformation store associated with this CMSSignedData object with the new one passed in
+		 * using the current DigestAlgorithmIdentifierFinder for creating the digest sets. You would probably only want
+		 * to do this if you wanted to change the unsigned attributes associated with a signer, or perhaps delete one.
+		 *
+		 * @param signedData             the signed data object to be used as a base.
+		 * @param signerInformationStore the new signer information store to use.
+		 * @return a new signed data object.
+		 */
+        public static CmsSignedData ReplaceSigners(CmsSignedData signedData,
+			SignerInformationStore signerInformationStore) =>
+				ReplaceSigners(signedData, signerInformationStore, DigestAlgIDFinder);
+
+        /**
+         * Replace the SignerInformation store associated with this CMSSignedData object with the new one passed in
+         * using the passed in DigestAlgorithmIdentifierFinder for creating the digest sets. You would probably only
+         * want to do this if you wanted to change the unsigned attributes associated with a signer, or perhaps delete
+         * one.
+         *
+         * @param signedData             the signed data object to be used as a base.
+         * @param signerInformationStore the new signer information store to use.
+         * @param dgstAlgIDFinder      the digest algorithmID map to generate the digest set with.
+         * @return a new signed data object.
+         */
+        public static CmsSignedData ReplaceSigners(CmsSignedData signedData,
+			SignerInformationStore signerInformationStore, DefaultDigestAlgorithmIdentifierFinder digestAlgIDFinder)
+		{
+            //
+            // copy
+            //
+            CmsSignedData cms = new CmsSignedData(signedData);
+
+            //
+            // replace the store
+            //
+            cms.signerInfoStore = signerInformationStore;
+
+            //
+            // replace the signers in the SignedData object
+            //
+            HashSet<AlgorithmIdentifier> digestAlgs = new HashSet<AlgorithmIdentifier>();
+
+			var signers = signerInformationStore.GetSigners();
+			Asn1EncodableVector vec = new Asn1EncodableVector(signers.Count);
+
+			foreach (var signer in signers)
 			{
-				digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
+				CmsUtilities.AddDigestAlgs(digestAlgs, signer, digestAlgIDFinder);
 				vec.Add(signer.ToSignerInfo());
 			}
 
-			Asn1Set digests = new DerSet(digestAlgs);
-			Asn1Set signers = new DerSet(vec);
+			Asn1Set digestSet = CmsUtilities.ConvertToDLSet(digestAlgs);
+			Asn1Set signerSet = DLSet.FromVector(vec);
 			Asn1Sequence sD = (Asn1Sequence)signedData.signedData.ToAsn1Object();
 
-			//
-			// signers are the last item in the sequence.
-			//
-			vec = new Asn1EncodableVector(sD.Count);
-			vec.Add(sD[0]); // version
-			vec.Add(digests);
+            //
+            // signers are the last item in the sequence.
+            //
+            vec = new Asn1EncodableVector(sD.Count);
+            vec.Add(sD[0]); // version
+			vec.Add(digestSet);
 
 			for (int i = 2; i != sD.Count - 1; i++)
 			{
 				vec.Add(sD[i]);
 			}
 
-			vec.Add(signers);
+			vec.Add(signerSet);
 
 			cms.signedData = SignedData.GetInstance(new BerSequence(vec));