summary refs log tree commit diff
diff options
context:
space:
mode:
authormw <megan@cryptoworkshop.com>2020-08-28 23:36:29 +1000
committermw <megan@cryptoworkshop.com>2020-08-28 23:36:29 +1000
commit326817d43b7033ff124924642dec1e84148e898e (patch)
tree66aa5c3215f6976f187bf7236294fe59aeba71fb
parentadded IDigestFactory (diff)
downloadBouncyCastle.NET-ed25519-326817d43b7033ff124924642dec1e84148e898e.tar.xz
Updated TimeStampTokenGenerator
-rw-r--r--crypto/src/cms/SignerInfoGenerator.cs11
-rw-r--r--crypto/src/crypto/IDigestFactory.cs9
-rw-r--r--crypto/src/crypto/operators/DigestFactory.cs79
-rw-r--r--crypto/src/tsp/TimeStampToken.cs12
-rw-r--r--crypto/src/tsp/TimeStampTokenGenerator.cs591
5 files changed, 472 insertions, 230 deletions
diff --git a/crypto/src/cms/SignerInfoGenerator.cs b/crypto/src/cms/SignerInfoGenerator.cs
index df8d1d0a1..786749cb5 100644
--- a/crypto/src/cms/SignerInfoGenerator.cs
+++ b/crypto/src/cms/SignerInfoGenerator.cs
@@ -58,6 +58,16 @@ namespace Org.BouncyCastle.Cms
         {
             this.certificate = certificate;
         }
+
+        public SignerInfoGeneratorBuilder NewBuilder()
+        {
+            SignerInfoGeneratorBuilder builder = new SignerInfoGeneratorBuilder();
+            builder.WithSignedAttributeGenerator(signedGen);
+            builder.WithUnsignedAttributeGenerator(unsignedGen);
+            builder.SetDirectSignature(isDirectSignature);
+            return builder;
+        }
+
     }
 
     public class SignerInfoGeneratorBuilder
@@ -69,6 +79,7 @@ namespace Org.BouncyCastle.Cms
         public SignerInfoGeneratorBuilder()
         {
         }
+    
 
         /**
          * If the passed in flag is true, the signer signature will be based on the data, not
diff --git a/crypto/src/crypto/IDigestFactory.cs b/crypto/src/crypto/IDigestFactory.cs
index b37bab90e..b46769cd3 100644
--- a/crypto/src/crypto/IDigestFactory.cs
+++ b/crypto/src/crypto/IDigestFactory.cs
@@ -2,12 +2,11 @@ namespace Org.BouncyCastle.Crypto
 {
     /// <summary>
     /// Base interface for operator factories that create stream-based digest calculators.
-    /// </summary>
-    /// <typeparam name="A">The algorithm details/parameter type for the digest factory.</typeparam>
-    public interface IDigestFactory<out A>
+    /// </summary>   
+    public interface IDigestFactory
 	{
 		/// <summary>The algorithm details object for calculators made by this factory.</summary>
-		A AlgorithmDetails { get ; }
+		object AlgorithmDetails { get ; }
 
 		/// <summary>Return the size of the digest associated with this factory.</summary>
 		/// <returns>The length of the digest produced by this calculators from this factory in bytes.</returns>
@@ -19,6 +18,6 @@ namespace Org.BouncyCastle.Crypto
 		/// and producing the digest block.
 		/// </summary>
 		/// <returns>A calculator producing an IBlockResult with the final digest in it.</returns>
-		IStreamCalculator<IBlockResult> CreateCalculator();
+		IStreamCalculator CreateCalculator();
 	}
 }
diff --git a/crypto/src/crypto/operators/DigestFactory.cs b/crypto/src/crypto/operators/DigestFactory.cs
new file mode 100644
index 000000000..7624fdf43
--- /dev/null
+++ b/crypto/src/crypto/operators/DigestFactory.cs
@@ -0,0 +1,79 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Tests;
+using Org.BouncyCastle.Security;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Org.BouncyCastle.Crypto.Operators
+{
+
+
+
+    public class DigestFactory : IDigestFactory
+    {
+
+        public static DigestFactory Get(DerObjectIdentifier oid)
+        {
+            return new DigestFactory(DigestUtilities.GetDigest(oid), oid);          
+        }
+
+        public static DigestFactory Get(String mechanism)
+        {
+            DerObjectIdentifier oid = DigestUtilities.GetObjectIdentifier(mechanism);
+            return new DigestFactory(DigestUtilities.GetDigest(oid), oid);
+        }
+
+
+        private IDigest digest;
+        private DerObjectIdentifier oid;
+
+        public DigestFactory(IDigest digest, DerObjectIdentifier oid)
+        {
+            this.digest = digest;
+            this.oid = oid;
+        }    
+
+        public object AlgorithmDetails => new AlgorithmIdentifier(oid);
+
+        public int DigestLength => digest.GetDigestSize();
+
+        public IStreamCalculator CreateCalculator() => new DfDigestStream(digest);
+        
+    }
+
+
+    internal class DfDigestStream : IStreamCalculator
+    {
+
+        private DigestSink stream;
+
+        public DfDigestStream(IDigest digest)
+        {          
+            stream = new DigestSink(digest);
+        }
+
+        public Stream Stream => stream;
+
+        public object GetResult()
+        {
+            byte[] result = new byte[stream.Digest.GetDigestSize()];
+            stream.Digest.DoFinal(result, 0);
+            return new SimpleBlockResult(result);
+        }
+      
+    }
+
+   
+
+}
diff --git a/crypto/src/tsp/TimeStampToken.cs b/crypto/src/tsp/TimeStampToken.cs
index 643813552..32f2523ce 100644
--- a/crypto/src/tsp/TimeStampToken.cs
+++ b/crypto/src/tsp/TimeStampToken.cs
@@ -85,9 +85,17 @@ namespace Org.BouncyCastle.Tsp
 
 				if (attr != null)
 				{
-					SigningCertificate signCert = SigningCertificate.GetInstance(attr.AttrValues[0]);
 
-					this.certID = new CertID(EssCertID.GetInstance(signCert.GetCerts()[0]));
+					if (attr.AttrValues[0] is SigningCertificateV2)
+					{
+						SigningCertificateV2 signCert = SigningCertificateV2.GetInstance(attr.AttrValues[0]);
+						this.certID = new CertID(EssCertIDv2.GetInstance(signCert.GetCerts()[0]));
+					}
+					else
+					{
+						SigningCertificate signCert = SigningCertificate.GetInstance(attr.AttrValues[0]);
+						this.certID = new CertID(EssCertID.GetInstance(signCert.GetCerts()[0]));
+					}
 				}
 				else
 				{
diff --git a/crypto/src/tsp/TimeStampTokenGenerator.cs b/crypto/src/tsp/TimeStampTokenGenerator.cs
index 07eddd4b9..3441a18a2 100644
--- a/crypto/src/tsp/TimeStampTokenGenerator.cs
+++ b/crypto/src/tsp/TimeStampTokenGenerator.cs
@@ -1,14 +1,20 @@
 using System;
 using System.Collections;
 using System.IO;
-
+using System.Runtime.InteropServices.ComTypes;
 using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
 using Org.BouncyCastle.Asn1.Ess;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
 using Org.BouncyCastle.Asn1.Pkcs;
 using Org.BouncyCastle.Asn1.Tsp;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Cms;
 using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Operators;
+using Org.BouncyCastle.Crypto.Paddings;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Security.Certificates;
@@ -18,228 +24,367 @@ using Org.BouncyCastle.X509.Store;
 
 namespace Org.BouncyCastle.Tsp
 {
-	public class TimeStampTokenGenerator
-	{
-		private int accuracySeconds = -1;
-		private int accuracyMillis = -1;
-		private int accuracyMicros = -1;
-		private bool ordering = false;
-		private GeneralName tsa = null;
-		private string tsaPolicyOID;
-
-		private AsymmetricKeyParameter	key;
-		private X509Certificate			cert;
-		private string					digestOID;
-		private Asn1.Cms.AttributeTable	signedAttr;
-		private Asn1.Cms.AttributeTable	unsignedAttr;
-		private IX509Store				x509Certs;
-		private IX509Store				x509Crls;
-
-		/**
+    public class TimeStampTokenGenerator
+    {
+        private int accuracySeconds = -1;
+        private int accuracyMillis = -1;
+        private int accuracyMicros = -1;
+        private bool ordering = false;
+        private GeneralName tsa = null;
+        private String tsaPolicyOID;
+    
+        private IX509Store x509Certs;
+        private IX509Store x509Crls;
+        private SignerInfoGenerator signerInfoGenerator;
+        IDigestFactory digestCalculator;
+
+        /**
 		 * basic creation - only the default attributes will be included here.
 		 */
-		public TimeStampTokenGenerator(
-			AsymmetricKeyParameter	key,
-			X509Certificate			cert,
-			string					digestOID,
-			string					tsaPolicyOID)
-			: this(key, cert, digestOID, tsaPolicyOID, null, null)
-		{
-		}
-
-		/**
-		 * create with a signer with extra signed/unsigned attributes.
-		 */
-		public TimeStampTokenGenerator(
-			AsymmetricKeyParameter	key,
-			X509Certificate			cert,
-			string					digestOID,
-			string					tsaPolicyOID,
-			Asn1.Cms.AttributeTable	signedAttr,
-			Asn1.Cms.AttributeTable	unsignedAttr)
-		{
-			this.key = key;
-			this.cert = cert;
-			this.digestOID = digestOID;
-			this.tsaPolicyOID = tsaPolicyOID;
-			this.unsignedAttr = unsignedAttr;
-
-			TspUtil.ValidateCertificate(cert);
-
-			//
-			// Add the ESSCertID attribute
-			//
-			IDictionary signedAttrs;
-			if (signedAttr != null)
-			{
-				signedAttrs = signedAttr.ToDictionary();
-			}
-			else
-			{
-				signedAttrs = Platform.CreateHashtable();
-			}
-
-			try
-			{
-				byte[] hash = DigestUtilities.CalculateDigest("SHA-1", cert.GetEncoded());
-
-				EssCertID essCertid = new EssCertID(hash);
-
-				Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(
-					PkcsObjectIdentifiers.IdAASigningCertificate,
-					new DerSet(new SigningCertificate(essCertid)));
-
-				signedAttrs[attr.AttrType] = attr;
-			}
-			catch (CertificateEncodingException e)
-			{
-				throw new TspException("Exception processing certificate.", e);
-			}
-			catch (SecurityUtilityException e)
-			{
-				throw new TspException("Can't find a SHA-1 implementation.", e);
-			}
-
-			this.signedAttr = new Asn1.Cms.AttributeTable(signedAttrs);
-		}
-
-		public void SetCertificates(
-			IX509Store certificates)
-		{
-			this.x509Certs = certificates;
-		}
-
-		public void SetCrls(
-			IX509Store crls)
-		{
-			this.x509Crls = crls;
-		}
-
-		public void SetAccuracySeconds(
-			int accuracySeconds)
-		{
-			this.accuracySeconds = accuracySeconds;
-		}
-
-		public void SetAccuracyMillis(
-			int accuracyMillis)
-		{
-			this.accuracyMillis = accuracyMillis;
-		}
-
-		public void SetAccuracyMicros(
-			int accuracyMicros)
-		{
-			this.accuracyMicros = accuracyMicros;
-		}
-
-		public void SetOrdering(
-			bool ordering)
-		{
-			this.ordering = ordering;
-		}
-
-		public void SetTsa(
-			GeneralName tsa)
-		{
-			this.tsa = tsa;
-		}
-
-		//------------------------------------------------------------------------------
-
-		public TimeStampToken Generate(
-			TimeStampRequest	request,
-			BigInteger			serialNumber,
-			DateTime			genTime)
-		{
-			DerObjectIdentifier digestAlgOID = new DerObjectIdentifier(request.MessageImprintAlgOid);
-
-			AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOID, DerNull.Instance);
-			MessageImprint messageImprint = new MessageImprint(algID, request.GetMessageImprintDigest());
-
-			Accuracy accuracy = null;
-			if (accuracySeconds > 0 || accuracyMillis > 0 || accuracyMicros > 0)
-			{
-				DerInteger seconds = null;
-				if (accuracySeconds > 0)
-				{
-					seconds = new DerInteger(accuracySeconds);
-				}
-
-				DerInteger millis = null;
-				if (accuracyMillis > 0)
-				{
-					millis = new DerInteger(accuracyMillis);
-				}
-
-				DerInteger micros = null;
-				if (accuracyMicros > 0)
-				{
-					micros = new DerInteger(accuracyMicros);
-				}
-
-				accuracy = new Accuracy(seconds, millis, micros);
-			}
-
-			DerBoolean derOrdering = null;
-			if (ordering)
-			{
-				derOrdering = DerBoolean.GetInstance(ordering);
-			}
-
-			DerInteger nonce = null;
-			if (request.Nonce != null)
-			{
-				nonce = new DerInteger(request.Nonce);
-			}
-
-			DerObjectIdentifier tsaPolicy = new DerObjectIdentifier(tsaPolicyOID);
-			if (request.ReqPolicy != null)
-			{
-				tsaPolicy = new DerObjectIdentifier(request.ReqPolicy);
-			}
-
-			TstInfo tstInfo = new TstInfo(tsaPolicy, messageImprint,
-				new DerInteger(serialNumber), new DerGeneralizedTime(genTime), accuracy,
-				derOrdering, nonce, tsa, request.Extensions);
-
-			try
-			{
-				CmsSignedDataGenerator signedDataGenerator = new CmsSignedDataGenerator();
-
-				byte[] derEncodedTstInfo = tstInfo.GetDerEncoded();
-
-				if (request.CertReq)
-				{
-					signedDataGenerator.AddCertificates(x509Certs);
-				}
-
-				signedDataGenerator.AddCrls(x509Crls);
-				signedDataGenerator.AddSigner(key, cert, digestOID, signedAttr, unsignedAttr);
-
-				CmsSignedData signedData = signedDataGenerator.Generate(
-					PkcsObjectIdentifiers.IdCTTstInfo.Id,
-					new CmsProcessableByteArray(derEncodedTstInfo),
-					true);
-
-				return new TimeStampToken(signedData);
-			}
-			catch (CmsException cmsEx)
-			{
-				throw new TspException("Error generating time-stamp token", cmsEx);
-			}
-			catch (IOException e)
-			{
-				throw new TspException("Exception encoding info", e);
-			}
-			catch (X509StoreException e)
-			{
-				throw new TspException("Exception handling CertStore", e);
-			}
-//			catch (InvalidAlgorithmParameterException e)
-//			{
-//				throw new TspException("Exception handling CertStore CRLs", e);
-//			}
-		}
-	}
+        public TimeStampTokenGenerator(
+            AsymmetricKeyParameter key,
+            X509Certificate cert,
+            string digestOID,
+            string tsaPolicyOID)
+            : this(key, cert, digestOID, tsaPolicyOID, null, null)
+        {
+        }
+
+
+        public TimeStampTokenGenerator(
+            SignerInfoGenerator signerInfoGen,
+            IDigestFactory digestCalculator,
+            DerObjectIdentifier tsaPolicy,
+            bool isIssuerSerialIncluded)
+        {
+
+            this.signerInfoGenerator = signerInfoGen;
+            this.digestCalculator = digestCalculator;
+            this.tsaPolicyOID = tsaPolicy.Id;
+
+            if (signerInfoGenerator.certificate == null)
+            {
+                throw new ArgumentException("SignerInfoGenerator must have an associated certificate");
+            }
+
+            X509Certificate assocCert = signerInfoGenerator.certificate;
+            TspUtil.ValidateCertificate(assocCert);
+
+            try
+            {
+                IStreamCalculator calculator = digestCalculator.CreateCalculator();
+                Stream stream = calculator.Stream;
+                byte[] certEnc = assocCert.GetEncoded();
+                stream.Write(certEnc, 0, certEnc.Length);
+                stream.Flush();
+                stream.Close();
+
+                if (((AlgorithmIdentifier)digestCalculator.AlgorithmDetails).Algorithm.Equals(OiwObjectIdentifiers.IdSha1))
+                {
+                    EssCertID essCertID = new EssCertID(
+                       ((IBlockResult)calculator.GetResult()).Collect(),
+                       isIssuerSerialIncluded ?
+                           new IssuerSerial(
+                               new GeneralNames(
+                                   new GeneralName(assocCert.IssuerDN)),
+                               new DerInteger(assocCert.SerialNumber)) : null);
+
+                    this.signerInfoGenerator = signerInfoGen.NewBuilder()
+                        .WithSignedAttributeGenerator(new TableGen(signerInfoGen, essCertID))
+                        .Build(signerInfoGen.contentSigner, signerInfoGen.certificate);
+                }
+                else
+                {
+                    AlgorithmIdentifier digestAlgID = new AlgorithmIdentifier(
+                        ((AlgorithmIdentifier)digestCalculator.AlgorithmDetails).Algorithm);
+
+                    EssCertIDv2 essCertID = new EssCertIDv2(
+                        ((IBlockResult)calculator.GetResult()).Collect(),
+                        isIssuerSerialIncluded ?
+                            new IssuerSerial(
+                                new GeneralNames(
+                                    new GeneralName(assocCert.IssuerDN)),
+                                new DerInteger(assocCert.SerialNumber)) : null);
+
+                    this.signerInfoGenerator = signerInfoGen.NewBuilder()
+                        .WithSignedAttributeGenerator(new TableGen2(signerInfoGen, essCertID))
+                        .Build(signerInfoGen.contentSigner, signerInfoGen.certificate);
+                }
+
+            }
+            catch (Exception ex)
+            {
+                throw new TspException("Exception processing certificate", ex);
+            }
+        }
+
+        /**
+         * create with a signer with extra signed/unsigned attributes.
+         */
+        public TimeStampTokenGenerator(
+           AsymmetricKeyParameter key,
+           X509Certificate cert,
+           string digestOID,
+           string tsaPolicyOID,
+           Asn1.Cms.AttributeTable signedAttr,
+           Asn1.Cms.AttributeTable unsignedAttr) : this(
+               makeInfoGenerator(key, cert, digestOID, signedAttr, unsignedAttr),
+               DigestFactory.Get(OiwObjectIdentifiers.IdSha1),
+               tsaPolicyOID != null?new DerObjectIdentifier(tsaPolicyOID):null, false)
+        {
+
+            this.tsaPolicyOID = tsaPolicyOID;
+
+        
+        }
+
+
+        internal static SignerInfoGenerator makeInfoGenerator(
+          AsymmetricKeyParameter key,
+          X509Certificate cert,
+          string digestOID,
+
+          Asn1.Cms.AttributeTable signedAttr,
+          Asn1.Cms.AttributeTable unsignedAttr)
+        {
+
+
+            TspUtil.ValidateCertificate(cert);
+
+            //
+            // Add the ESSCertID attribute
+            //
+            IDictionary signedAttrs;
+            if (signedAttr != null)
+            {
+                signedAttrs = signedAttr.ToDictionary();
+            }
+            else
+            {
+                signedAttrs = Platform.CreateHashtable();
+            }
+
+            //try
+            //{
+            //    byte[] hash = DigestUtilities.CalculateDigest("SHA-1", cert.GetEncoded());
+
+            //    EssCertID essCertid = new EssCertID(hash);
+
+            //    Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(
+            //        PkcsObjectIdentifiers.IdAASigningCertificate,
+            //        new DerSet(new SigningCertificate(essCertid)));
+
+            //    signedAttrs[attr.AttrType] = attr;
+            //}
+            //catch (CertificateEncodingException e)
+            //{
+            //    throw new TspException("Exception processing certificate.", e);
+            //}
+            //catch (SecurityUtilityException e)
+            //{
+            //    throw new TspException("Can't find a SHA-1 implementation.", e);
+            //}
+
+
+            string digestName = CmsSignedHelper.Instance.GetDigestAlgName(digestOID);
+            string signatureName = digestName + "with" + CmsSignedHelper.Instance.GetEncryptionAlgName(CmsSignedHelper.Instance.GetEncOid(key, digestOID));
+
+            Asn1SignatureFactory sigfact = new Asn1SignatureFactory(signatureName, key);
+            return new SignerInfoGeneratorBuilder()
+             .WithSignedAttributeGenerator(
+                new DefaultSignedAttributeTableGenerator(
+                    new Asn1.Cms.AttributeTable(signedAttrs)))
+              .WithUnsignedAttributeGenerator(
+                new SimpleAttributeTableGenerator(unsignedAttr))
+                .Build(sigfact, cert);
+        }
+
+
+        public void SetCertificates(
+        IX509Store certificates)
+        {
+            this.x509Certs = certificates;
+        }
+
+        public void SetCrls(
+            IX509Store crls)
+        {
+            this.x509Crls = crls;
+        }
+
+        public void SetAccuracySeconds(
+            int accuracySeconds)
+        {
+            this.accuracySeconds = accuracySeconds;
+        }
+
+        public void SetAccuracyMillis(
+            int accuracyMillis)
+        {
+            this.accuracyMillis = accuracyMillis;
+        }
+
+        public void SetAccuracyMicros(
+            int accuracyMicros)
+        {
+            this.accuracyMicros = accuracyMicros;
+        }
+
+        public void SetOrdering(
+            bool ordering)
+        {
+            this.ordering = ordering;
+        }
+
+        public void SetTsa(
+            GeneralName tsa)
+        {
+            this.tsa = tsa;
+        }
+
+        //------------------------------------------------------------------------------
+
+        public TimeStampToken Generate(
+            TimeStampRequest request,
+            BigInteger serialNumber,
+            DateTime genTime)
+        {
+            DerObjectIdentifier digestAlgOID = new DerObjectIdentifier(request.MessageImprintAlgOid);
+
+            AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOID, DerNull.Instance);
+            MessageImprint messageImprint = new MessageImprint(algID, request.GetMessageImprintDigest());
+
+            Accuracy accuracy = null;
+            if (accuracySeconds > 0 || accuracyMillis > 0 || accuracyMicros > 0)
+            {
+                DerInteger seconds = null;
+                if (accuracySeconds > 0)
+                {
+                    seconds = new DerInteger(accuracySeconds);
+                }
+
+                DerInteger millis = null;
+                if (accuracyMillis > 0)
+                {
+                    millis = new DerInteger(accuracyMillis);
+                }
+
+                DerInteger micros = null;
+                if (accuracyMicros > 0)
+                {
+                    micros = new DerInteger(accuracyMicros);
+                }
+
+                accuracy = new Accuracy(seconds, millis, micros);
+            }
+
+            DerBoolean derOrdering = null;
+            if (ordering)
+            {
+                derOrdering = DerBoolean.GetInstance(ordering);
+            }
+
+            DerInteger nonce = null;
+            if (request.Nonce != null)
+            {
+                nonce = new DerInteger(request.Nonce);
+            }
+
+            DerObjectIdentifier tsaPolicy = new DerObjectIdentifier(tsaPolicyOID);
+            if (request.ReqPolicy != null)
+            {
+                tsaPolicy = new DerObjectIdentifier(request.ReqPolicy);
+            }
+
+            TstInfo tstInfo = new TstInfo(tsaPolicy, messageImprint,
+                new DerInteger(serialNumber), new DerGeneralizedTime(genTime), accuracy,
+                derOrdering, nonce, tsa, request.Extensions);
+
+            try
+            {
+                CmsSignedDataGenerator signedDataGenerator = new CmsSignedDataGenerator();
+
+                byte[] derEncodedTstInfo = tstInfo.GetDerEncoded();
+
+                if (request.CertReq)
+                {
+                    signedDataGenerator.AddCertificates(x509Certs);
+                }
+
+                signedDataGenerator.AddCrls(x509Crls);
+
+                signedDataGenerator.AddSignerInfoGenerator(signerInfoGenerator);
+
+                CmsSignedData signedData = signedDataGenerator.Generate(
+                    PkcsObjectIdentifiers.IdCTTstInfo.Id,
+                    new CmsProcessableByteArray(derEncodedTstInfo),
+                    true);
+
+                return new TimeStampToken(signedData);
+            }
+            catch (CmsException cmsEx)
+            {
+                throw new TspException("Error generating time-stamp token", cmsEx);
+            }
+            catch (IOException e)
+            {
+                throw new TspException("Exception encoding info", e);
+            }
+            catch (X509StoreException e)
+            {
+                throw new TspException("Exception handling CertStore", e);
+            }
+            //			catch (InvalidAlgorithmParameterException e)
+            //			{
+            //				throw new TspException("Exception handling CertStore CRLs", e);
+            //			}
+        }
+
+
+        private class TableGen : CmsAttributeTableGenerator
+        {
+            private readonly SignerInfoGenerator infoGen;
+            private readonly EssCertID essCertID;
+
+
+            public TableGen(SignerInfoGenerator infoGen, EssCertID essCertID)
+            {
+                this.infoGen = infoGen;
+                this.essCertID = essCertID;
+            }
+
+            public Asn1.Cms.AttributeTable GetAttributes(IDictionary parameters)
+            {
+                Asn1.Cms.AttributeTable tab = infoGen.signedGen.GetAttributes(parameters);
+                if (tab[PkcsObjectIdentifiers.IdAASigningCertificate] == null)
+                {
+                    return tab.Add(PkcsObjectIdentifiers.IdAASigningCertificate, new SigningCertificate(essCertID));
+                }
+                return tab;
+            }
+        }
+
+        private class TableGen2 : CmsAttributeTableGenerator
+        {
+            private readonly SignerInfoGenerator infoGen;
+            private readonly EssCertIDv2 essCertID;
+
+
+            public TableGen2(SignerInfoGenerator infoGen, EssCertIDv2 essCertID)
+            {
+                this.infoGen = infoGen;
+                this.essCertID = essCertID;
+            }
+
+            public Asn1.Cms.AttributeTable GetAttributes(IDictionary parameters)
+            {
+                Asn1.Cms.AttributeTable tab = infoGen.signedGen.GetAttributes(parameters);
+                if (tab[PkcsObjectIdentifiers.IdAASigningCertificate] == null)
+                {
+                    return tab.Add(PkcsObjectIdentifiers.IdAASigningCertificate, new SigningCertificateV2(essCertID));
+                }
+                return tab;
+            }
+        }
+    }
 }