summary refs log tree commit diff
path: root/crypto/src/cms/SignerInfoGenerator.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/cms/SignerInfoGenerator.cs')
-rw-r--r--crypto/src/cms/SignerInfoGenerator.cs163
1 files changed, 158 insertions, 5 deletions
diff --git a/crypto/src/cms/SignerInfoGenerator.cs b/crypto/src/cms/SignerInfoGenerator.cs
index f78cf2c01..62db40ad8 100644
--- a/crypto/src/cms/SignerInfoGenerator.cs
+++ b/crypto/src/cms/SignerInfoGenerator.cs
@@ -3,12 +3,165 @@ using System;
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Cms;
 using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.X509;
 
 namespace Org.BouncyCastle.Cms
 {
-	internal interface SignerInfoGenerator
-	{
-		SignerInfo Generate(DerObjectIdentifier contentType, AlgorithmIdentifier digestAlgorithm,
-        	byte[] calculatedDigest);
-	}
+    internal interface ISignerInfoGenerator
+    {
+        SignerInfo Generate(DerObjectIdentifier contentType, AlgorithmIdentifier digestAlgorithm,
+            byte[] calculatedDigest);
+    }
+
+    public class SignerInfoGenerator
+    {
+        internal X509Certificate certificate;
+        internal ISignatureCalculator contentSigner;
+        internal SignerIdentifier sigId;
+        internal CmsAttributeTableGenerator signedGen;
+        internal CmsAttributeTableGenerator unsignedGen;
+        private bool isDirectSignature;
+
+        internal SignerInfoGenerator(SignerIdentifier sigId, ISignatureCalculator contentSigner): this(sigId, contentSigner, false)
+        {
+
+        }
+
+        internal SignerInfoGenerator(SignerIdentifier sigId, ISignatureCalculator contentSigner, bool isDirectSignature)
+        {
+            this.sigId = sigId;
+            this.contentSigner = contentSigner;
+            this.isDirectSignature = isDirectSignature;
+            if (this.isDirectSignature)
+            {
+                this.signedGen = null;
+                this.unsignedGen = null;
+            }
+            else
+            {
+                this.signedGen = new DefaultSignedAttributeTableGenerator();
+                this.unsignedGen = null;
+            }
+        }
+
+        internal SignerInfoGenerator(SignerIdentifier sigId, ISignatureCalculator contentSigner, CmsAttributeTableGenerator signedGen, CmsAttributeTableGenerator unsignedGen)
+        {
+            this.sigId = sigId;
+            this.contentSigner = contentSigner;
+            this.signedGen = signedGen;
+            this.unsignedGen = unsignedGen;
+            this.isDirectSignature = false;
+        }
+
+        internal void setAssociatedCertificate(X509Certificate certificate)
+        {
+            this.certificate = certificate;
+        }
+    }
+
+    public class SignerInfoGeneratorBuilder
+    {
+        private bool directSignature;
+        private CmsAttributeTableGenerator signedGen;
+        private CmsAttributeTableGenerator unsignedGen;
+
+        public SignerInfoGeneratorBuilder()
+        {
+        }
+
+        /**
+         * If the passed in flag is true, the signer signature will be based on the data, not
+         * a collection of signed attributes, and no signed attributes will be included.
+         *
+         * @return the builder object
+         */
+        public SignerInfoGeneratorBuilder SetDirectSignature(bool hasNoSignedAttributes)
+        {
+            this.directSignature = hasNoSignedAttributes;
+
+            return this;
+        }
+
+        /**
+         *  Provide a custom signed attribute generator.
+         *
+         * @param signedGen a generator of signed attributes.
+         * @return the builder object
+         */
+        public SignerInfoGeneratorBuilder WithSignedAttributeGenerator(CmsAttributeTableGenerator signedGen)
+        {
+            this.signedGen = signedGen;
+
+            return this;
+        }
+
+        /**
+         * Provide a generator of unsigned attributes.
+         *
+         * @param unsignedGen  a generator for signed attributes.
+         * @return the builder object
+         */
+        public SignerInfoGeneratorBuilder WithUnsignedAttributeGenerator(CmsAttributeTableGenerator unsignedGen)
+        {
+            this.unsignedGen = unsignedGen;
+
+            return this;
+        }
+
+        /**
+         * Build a generator with the passed in certHolder issuer and serial number as the signerIdentifier.
+         *
+         * @param contentSigner  operator for generating the final signature in the SignerInfo with.
+         * @param certHolder  carrier for the X.509 certificate related to the contentSigner.
+         * @return  a SignerInfoGenerator
+         * @throws OperatorCreationException   if the generator cannot be built.
+         */
+        public SignerInfoGenerator Build(ISignatureCalculator contentSigner, X509Certificate certificate)
+        {
+            SignerIdentifier sigId = new SignerIdentifier(new IssuerAndSerialNumber(certificate.IssuerDN, new DerInteger(certificate.SerialNumber)));
+
+            SignerInfoGenerator sigInfoGen = CreateGenerator(contentSigner, sigId);
+
+            sigInfoGen.setAssociatedCertificate(certificate);
+
+            return sigInfoGen;
+        }
+
+        /**
+         * Build a generator with the passed in subjectKeyIdentifier as the signerIdentifier. If used  you should
+         * try to follow the calculation described in RFC 5280 section 4.2.1.2.
+         *
+         * @param contentSigner  operator for generating the final signature in the SignerInfo with.
+         * @param subjectKeyIdentifier    key identifier to identify the public key for verifying the signature.
+         * @return  a SignerInfoGenerator
+         * @throws OperatorCreationException if the generator cannot be built.
+         */
+        public SignerInfoGenerator Build(ISignatureCalculator contentSigner, byte[] subjectKeyIdentifier)
+        {
+            SignerIdentifier sigId = new SignerIdentifier(new DerOctetString(subjectKeyIdentifier));
+
+            return CreateGenerator(contentSigner, sigId);
+        }
+
+        private SignerInfoGenerator CreateGenerator(ISignatureCalculator contentSigner, SignerIdentifier sigId)
+        {
+            if (directSignature)
+            {
+                return new SignerInfoGenerator(sigId, contentSigner, true);
+            }
+
+            if (signedGen != null || unsignedGen != null)
+            {
+                if (signedGen == null)
+                {
+                    signedGen = new DefaultSignedAttributeTableGenerator();
+                }
+
+                return new SignerInfoGenerator(sigId, contentSigner, signedGen, unsignedGen);
+            }
+
+            return new SignerInfoGenerator(sigId, contentSigner);
+        }
+    }
 }