summary refs log tree commit diff
path: root/crypto/src
diff options
context:
space:
mode:
authormw <megan@cryptoworkshop.com>2021-09-01 16:00:23 +1000
committermw <megan@cryptoworkshop.com>2021-09-01 16:00:23 +1000
commit0b0f03c598b558c7acf79a969315a8d2e0aa1f1b (patch)
treeeb8091bd81be5d8225a38ac8947594d7f694a3c6 /crypto/src
parentfixed typos (diff)
downloadBouncyCastle.NET-ed25519-0b0f03c598b558c7acf79a969315a8d2e0aa1f1b.tar.xz
Issue #1
Added logic to handle duplicate extensions.
New method on Pkcs10CertificationRequest for extracting X509Extensions
Tests
Diffstat (limited to 'crypto/src')
-rw-r--r--crypto/src/asn1/x509/X509ExtensionsGenerator.cs195
-rw-r--r--crypto/src/pkcs/Pkcs10CertificationRequest.cs583
2 files changed, 441 insertions, 337 deletions
diff --git a/crypto/src/asn1/x509/X509ExtensionsGenerator.cs b/crypto/src/asn1/x509/X509ExtensionsGenerator.cs
index 58620ea5e..3b952fffa 100644
--- a/crypto/src/asn1/x509/X509ExtensionsGenerator.cs
+++ b/crypto/src/asn1/x509/X509ExtensionsGenerator.cs
@@ -5,88 +5,133 @@ using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.X509
 {
-	/// <remarks>Generator for X.509 extensions</remarks>
-	public class X509ExtensionsGenerator
-	{
-		private IDictionary extensions = Platform.CreateHashtable();
+    /// <remarks>Generator for X.509 extensions</remarks>
+    public class X509ExtensionsGenerator
+    {
+        private IDictionary extensions = Platform.CreateHashtable();
         private IList extOrdering = Platform.CreateArrayList();
 
-		/// <summary>Reset the generator</summary>
-		public void Reset()
-		{
+        private static readonly IDictionary dupsAllowed = Platform.CreateHashtable();
+
+        static X509ExtensionsGenerator()
+        {
+            dupsAllowed.Add(X509Extensions.SubjectAlternativeName, true);
+            dupsAllowed.Add(X509Extensions.IssuerAlternativeName, true);
+            dupsAllowed.Add(X509Extensions.SubjectDirectoryAttributes, true);
+            dupsAllowed.Add(X509Extensions.CertificateIssuer, true);
+
+        }
+
+
+
+        /// <summary>Reset the generator</summary>
+        public void Reset()
+        {
             extensions = Platform.CreateHashtable();
             extOrdering = Platform.CreateArrayList();
-		}
-
-		/// <summary>
-		/// Add an extension with the given oid and the passed in value to be included
-		/// in the OCTET STRING associated with the extension.
-		/// </summary>
-		/// <param name="oid">OID for the extension.</param>
-		/// <param name="critical">True if critical, false otherwise.</param>
-		/// <param name="extValue">The ASN.1 object to be included in the extension.</param>
-		public void AddExtension(
-			DerObjectIdentifier	oid,
-			bool				critical,
-			Asn1Encodable		extValue)
-		{
-			byte[] encoded;
-			try
-			{
-				encoded = extValue.GetDerEncoded();
-			}
-			catch (Exception e)
-			{
-				throw new ArgumentException("error encoding value: " + e);
-			}
-
-			this.AddExtension(oid, critical, encoded);
-		}
-
-		/// <summary>
-		/// Add an extension with the given oid and the passed in byte array to be wrapped
-		/// in the OCTET STRING associated with the extension.
-		/// </summary>
-		/// <param name="oid">OID for the extension.</param>
-		/// <param name="critical">True if critical, false otherwise.</param>
-		/// <param name="extValue">The byte array to be wrapped.</param>
-		public void AddExtension(
-			DerObjectIdentifier	oid,
-			bool				critical,
-			byte[]				extValue)
-		{
-			if (extensions.Contains(oid))
-			{
-				throw new ArgumentException("extension " + oid + " already added");
-			}
-
-			extOrdering.Add(oid);
-			extensions.Add(oid, new X509Extension(critical, new DerOctetString(extValue)));
-		}
-
-		/// <summary>Return true if there are no extension present in this generator.</summary>
-		/// <returns>True if empty, false otherwise</returns>
-		public bool IsEmpty
-		{
-			get { return extOrdering.Count < 1; }
-		}
-
-		/// <summary>Generate an X509Extensions object based on the current state of the generator.</summary>
-		/// <returns>An <c>X509Extensions</c> object</returns>
-		public X509Extensions Generate()
-		{
-			return new X509Extensions(extOrdering, extensions);
-		}
-
-        internal void AddExtension(DerObjectIdentifier oid,  X509Extension x509Extension)
+        }
+
+        /// <summary>
+        /// Add an extension with the given oid and the passed in value to be included
+        /// in the OCTET STRING associated with the extension.
+        /// </summary>
+        /// <param name="oid">OID for the extension.</param>
+        /// <param name="critical">True if critical, false otherwise.</param>
+        /// <param name="extValue">The ASN.1 object to be included in the extension.</param>
+        public void AddExtension(
+            DerObjectIdentifier oid,
+            bool critical,
+            Asn1Encodable extValue)
+        {
+            byte[] encoded;
+            try
+            {
+                encoded = extValue.GetDerEncoded();
+            }
+            catch (Exception e)
+            {
+                throw new ArgumentException("error encoding value: " + e);
+            }
+
+            this.AddExtension(oid, critical, encoded);
+        }
+
+        /// <summary>
+        /// Add an extension with the given oid and the passed in byte array to be wrapped
+        /// in the OCTET STRING associated with the extension.
+        /// </summary>
+        /// <param name="oid">OID for the extension.</param>
+        /// <param name="critical">True if critical, false otherwise.</param>
+        /// <param name="extValue">The byte array to be wrapped.</param>
+        public void AddExtension(
+            DerObjectIdentifier oid,
+            bool critical,
+            byte[] extValue)
+        {
+            if (extensions.Contains(oid))
+            {
+                if (dupsAllowed.Contains(oid))
+                {
+                    X509Extension existingExtension = (X509Extension)extensions[oid];
+
+                    Asn1Sequence seq1 = Asn1Sequence.GetInstance(DerOctetString.GetInstance(existingExtension.Value).GetOctets());
+                    Asn1EncodableVector items = Asn1EncodableVector.FromEnumerable(seq1);
+                    Asn1Sequence seq2 = Asn1Sequence.GetInstance(extValue);
+
+                    foreach (Asn1Encodable enc in seq2)
+                    {
+                        items.Add(enc);
+                    }
+
+                    extensions[oid] = new X509Extension(existingExtension.IsCritical, new DerOctetString(new DerSequence(items).GetEncoded()));
+
+                }
+                else
+                {
+                    throw new ArgumentException("extension " + oid + " already added");
+                }
+            }
+            else
+            {
+                extOrdering.Add(oid);
+                extensions.Add(oid, new X509Extension(critical, new DerOctetString(extValue)));
+            }
+        }
+
+        public void AddExtensions(X509Extensions extensions)
+        {
+            foreach (DerObjectIdentifier ident in extensions.ExtensionOids)
+            {
+                X509Extension ext = extensions.GetExtension(ident);
+                AddExtension(ident, ext.critical, ext.Value.GetOctets());
+            }
+        }
+
+
+
+        /// <summary>Return true if there are no extension present in this generator.</summary>
+        /// <returns>True if empty, false otherwise</returns>
+        public bool IsEmpty
+        {
+            get { return extOrdering.Count < 1; }
+        }
+
+        /// <summary>Generate an X509Extensions object based on the current state of the generator.</summary>
+        /// <returns>An <c>X509Extensions</c> object</returns>
+        public X509Extensions Generate()
+        {
+            return new X509Extensions(extOrdering, extensions);
+        }
+
+        internal void AddExtension(DerObjectIdentifier oid, X509Extension x509Extension)
         {
             if (extensions.Contains(oid))
-            {				
-				throw new ArgumentException  ("extension " + oid + " already added");
-			}
+            {
+                throw new ArgumentException("extension " + oid + " already added");
+            }
 
-			extOrdering.Add(oid);
-			extensions.Add(oid, x509Extension);
+            extOrdering.Add(oid);
+            extensions.Add(oid, x509Extension);
         }
     }
 }
diff --git a/crypto/src/pkcs/Pkcs10CertificationRequest.cs b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
index f422e0332..28b6ddb5b 100644
--- a/crypto/src/pkcs/Pkcs10CertificationRequest.cs
+++ b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
@@ -16,50 +16,51 @@ using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
 using Org.BouncyCastle.X509;
 using Org.BouncyCastle.Crypto.Operators;
+using Org.BouncyCastle.Asn1.Utilities;
 
 namespace Org.BouncyCastle.Pkcs
 {
-	/// <remarks>
-	/// A class for verifying and creating Pkcs10 Certification requests.
-	/// </remarks>
-	/// <code>
-	/// CertificationRequest ::= Sequence {
-	///   certificationRequestInfo  CertificationRequestInfo,
-	///   signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
-	///   signature                 BIT STRING
-	/// }
-	///
-	/// CertificationRequestInfo ::= Sequence {
-	///   version             Integer { v1(0) } (v1,...),
-	///   subject             Name,
-	///   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
-	///   attributes          [0] Attributes{{ CRIAttributes }}
-	///  }
-	///
-	///  Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
-	///
-	///  Attr { ATTRIBUTE:IOSet } ::= Sequence {
-	///    type    ATTRIBUTE.&amp;id({IOSet}),
-	///    values  Set SIZE(1..MAX) OF ATTRIBUTE.&amp;Type({IOSet}{\@type})
-	///  }
-	/// </code>
-	/// see <a href="http://www.rsasecurity.com/rsalabs/node.asp?id=2132"/>
-	public class Pkcs10CertificationRequest
-		: CertificationRequest
-	{
-		protected static readonly IDictionary algorithms = Platform.CreateHashtable();
+    /// <remarks>
+    /// A class for verifying and creating Pkcs10 Certification requests.
+    /// </remarks>
+    /// <code>
+    /// CertificationRequest ::= Sequence {
+    ///   certificationRequestInfo  CertificationRequestInfo,
+    ///   signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
+    ///   signature                 BIT STRING
+    /// }
+    ///
+    /// CertificationRequestInfo ::= Sequence {
+    ///   version             Integer { v1(0) } (v1,...),
+    ///   subject             Name,
+    ///   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+    ///   attributes          [0] Attributes{{ CRIAttributes }}
+    ///  }
+    ///
+    ///  Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
+    ///
+    ///  Attr { ATTRIBUTE:IOSet } ::= Sequence {
+    ///    type    ATTRIBUTE.&amp;id({IOSet}),
+    ///    values  Set SIZE(1..MAX) OF ATTRIBUTE.&amp;Type({IOSet}{\@type})
+    ///  }
+    /// </code>
+    /// see <a href="http://www.rsasecurity.com/rsalabs/node.asp?id=2132"/>
+    public class Pkcs10CertificationRequest
+        : CertificationRequest
+    {
+        protected static readonly IDictionary algorithms = Platform.CreateHashtable();
         protected static readonly IDictionary exParams = Platform.CreateHashtable();
         protected static readonly IDictionary keyAlgorithms = Platform.CreateHashtable();
         protected static readonly IDictionary oids = Platform.CreateHashtable();
-		protected static readonly ISet noParams = new HashSet();
-
-		static Pkcs10CertificationRequest()
-		{
-			algorithms.Add("MD2WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD2WithRsaEncryption);
-			algorithms.Add("MD2WITHRSA", PkcsObjectIdentifiers.MD2WithRsaEncryption);
-			algorithms.Add("MD5WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD5WithRsaEncryption);
-			algorithms.Add("MD5WITHRSA", PkcsObjectIdentifiers.MD5WithRsaEncryption);
-			algorithms.Add("RSAWITHMD5", PkcsObjectIdentifiers.MD5WithRsaEncryption);
+        protected static readonly ISet noParams = new HashSet();
+
+        static Pkcs10CertificationRequest()
+        {
+            algorithms.Add("MD2WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD2WithRsaEncryption);
+            algorithms.Add("MD2WITHRSA", PkcsObjectIdentifiers.MD2WithRsaEncryption);
+            algorithms.Add("MD5WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD5WithRsaEncryption);
+            algorithms.Add("MD5WITHRSA", PkcsObjectIdentifiers.MD5WithRsaEncryption);
+            algorithms.Add("RSAWITHMD5", PkcsObjectIdentifiers.MD5WithRsaEncryption);
             algorithms.Add("SHA1WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
             algorithms.Add("SHA-1WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
             algorithms.Add("SHA1WITHRSA", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
@@ -89,38 +90,38 @@ namespace Org.BouncyCastle.Pkcs
             algorithms.Add("SHA512(256)WITHRSA", PkcsObjectIdentifiers.Sha512_256WithRSAEncryption);
             algorithms.Add("SHA-512(256)WITHRSA", PkcsObjectIdentifiers.Sha512_256WithRSAEncryption);
             algorithms.Add("SHA1WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
-			algorithms.Add("SHA224WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
-			algorithms.Add("SHA256WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
-			algorithms.Add("SHA384WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
-			algorithms.Add("SHA512WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
-			algorithms.Add("RSAWITHSHA1", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
-			algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
-			algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
-			algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
-			algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
-			algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
-			algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
-			algorithms.Add("SHA1WITHDSA", X9ObjectIdentifiers.IdDsaWithSha1);
-			algorithms.Add("DSAWITHSHA1", X9ObjectIdentifiers.IdDsaWithSha1);
-			algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224);
-			algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256);
-			algorithms.Add("SHA384WITHDSA", NistObjectIdentifiers.DsaWithSha384);
-			algorithms.Add("SHA512WITHDSA", NistObjectIdentifiers.DsaWithSha512);
-			algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1);
-			algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
-			algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
-			algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
-			algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
-			algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1);
-			algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
-			algorithms.Add("GOST3410WITHGOST3411", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
-			algorithms.Add("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
-			algorithms.Add("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
-			algorithms.Add("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
-
-			//
-			// reverse mappings
-			//
+            algorithms.Add("SHA224WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+            algorithms.Add("SHA256WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+            algorithms.Add("SHA384WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+            algorithms.Add("SHA512WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+            algorithms.Add("RSAWITHSHA1", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
+            algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+            algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+            algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+            algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+            algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
+            algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
+            algorithms.Add("SHA1WITHDSA", X9ObjectIdentifiers.IdDsaWithSha1);
+            algorithms.Add("DSAWITHSHA1", X9ObjectIdentifiers.IdDsaWithSha1);
+            algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224);
+            algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256);
+            algorithms.Add("SHA384WITHDSA", NistObjectIdentifiers.DsaWithSha384);
+            algorithms.Add("SHA512WITHDSA", NistObjectIdentifiers.DsaWithSha512);
+            algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1);
+            algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
+            algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
+            algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
+            algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
+            algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1);
+            algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+            algorithms.Add("GOST3410WITHGOST3411", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+            algorithms.Add("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+            algorithms.Add("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+            algorithms.Add("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+
+            //
+            // reverse mappings
+            //
             oids.Add(PkcsObjectIdentifiers.Sha1WithRsaEncryption, "SHA1WITHRSA");
             oids.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption, "SHA224WITHRSA");
             oids.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption, "SHA256WITHRSA");
@@ -145,82 +146,82 @@ namespace Org.BouncyCastle.Pkcs
             oids.Add(NistObjectIdentifiers.DsaWithSha224, "SHA224WITHDSA");
             oids.Add(NistObjectIdentifiers.DsaWithSha256, "SHA256WITHDSA");
 
-			//
-			// key types
-			//
-			keyAlgorithms.Add(PkcsObjectIdentifiers.RsaEncryption, "RSA");
-			keyAlgorithms.Add(X9ObjectIdentifiers.IdDsa, "DSA");
-
-			//
-			// According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
-			// The parameters field SHALL be NULL for RSA based signature algorithms.
-			//
-			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1);
-			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224);
-			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256);
-			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384);
-			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512);
-			noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1);
+            //
+            // key types
+            //
+            keyAlgorithms.Add(PkcsObjectIdentifiers.RsaEncryption, "RSA");
+            keyAlgorithms.Add(X9ObjectIdentifiers.IdDsa, "DSA");
+
+            //
+            // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
+            // The parameters field SHALL be NULL for RSA based signature algorithms.
+            //
+            noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1);
+            noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224);
+            noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256);
+            noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384);
+            noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512);
+            noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1);
             noParams.Add(OiwObjectIdentifiers.DsaWithSha1);
             noParams.Add(NistObjectIdentifiers.DsaWithSha224);
-			noParams.Add(NistObjectIdentifiers.DsaWithSha256);
-
-			//
-			// RFC 4491
-			//
-			noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
-			noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
-
-			//
-			// explicit params
-			//
-			AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
-			exParams.Add("SHA1WITHRSAANDMGF1", CreatePssParams(sha1AlgId, 20));
-
-			AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance);
-			exParams.Add("SHA224WITHRSAANDMGF1", CreatePssParams(sha224AlgId, 28));
-
-			AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance);
-			exParams.Add("SHA256WITHRSAANDMGF1", CreatePssParams(sha256AlgId, 32));
-
-			AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance);
-			exParams.Add("SHA384WITHRSAANDMGF1", CreatePssParams(sha384AlgId, 48));
-
-			AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha512, DerNull.Instance);
-			exParams.Add("SHA512WITHRSAANDMGF1", CreatePssParams(sha512AlgId, 64));
-		}
-
-		private static RsassaPssParameters CreatePssParams(
-			AlgorithmIdentifier	hashAlgId,
-			int					saltSize)
-		{
-			return new RsassaPssParameters(
-				hashAlgId,
-				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, hashAlgId),
-				new DerInteger(saltSize),
-				new DerInteger(1));
-		}
-
-		protected Pkcs10CertificationRequest()
-		{
-		}
-
-		public Pkcs10CertificationRequest(
-			byte[] encoded)
-			: base((Asn1Sequence) Asn1Object.FromByteArray(encoded))
-		{
-		}
-
-		public Pkcs10CertificationRequest(
-			Asn1Sequence seq)
-			: base(seq)
-		{
-		}
-
-		public Pkcs10CertificationRequest(
-			Stream input)
-			: base((Asn1Sequence) Asn1Object.FromStream(input))
-		{
+            noParams.Add(NistObjectIdentifiers.DsaWithSha256);
+
+            //
+            // RFC 4491
+            //
+            noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+            noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+
+            //
+            // explicit params
+            //
+            AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
+            exParams.Add("SHA1WITHRSAANDMGF1", CreatePssParams(sha1AlgId, 20));
+
+            AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance);
+            exParams.Add("SHA224WITHRSAANDMGF1", CreatePssParams(sha224AlgId, 28));
+
+            AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance);
+            exParams.Add("SHA256WITHRSAANDMGF1", CreatePssParams(sha256AlgId, 32));
+
+            AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance);
+            exParams.Add("SHA384WITHRSAANDMGF1", CreatePssParams(sha384AlgId, 48));
+
+            AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha512, DerNull.Instance);
+            exParams.Add("SHA512WITHRSAANDMGF1", CreatePssParams(sha512AlgId, 64));
+        }
+
+        private static RsassaPssParameters CreatePssParams(
+            AlgorithmIdentifier hashAlgId,
+            int saltSize)
+        {
+            return new RsassaPssParameters(
+                hashAlgId,
+                new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, hashAlgId),
+                new DerInteger(saltSize),
+                new DerInteger(1));
+        }
+
+        protected Pkcs10CertificationRequest()
+        {
+        }
+
+        public Pkcs10CertificationRequest(
+            byte[] encoded)
+            : base((Asn1Sequence)Asn1Object.FromByteArray(encoded))
+        {
+        }
+
+        public Pkcs10CertificationRequest(
+            Asn1Sequence seq)
+            : base(seq)
+        {
+        }
+
+        public Pkcs10CertificationRequest(
+            Stream input)
+            : base((Asn1Sequence)Asn1Object.FromStream(input))
+        {
         }
 
         /// <summary>
@@ -232,14 +233,14 @@ namespace Org.BouncyCastle.Pkcs
         /// <param name="attributes">ASN1Set of Attributes.</param>
         /// <param name="signingKey">Matching Private key for nominated (above) public key to be used to sign the request.</param>
         public Pkcs10CertificationRequest(
-			string					signatureAlgorithm,
-			X509Name				subject,
-			AsymmetricKeyParameter	publicKey,
-			Asn1Set					attributes,
-			AsymmetricKeyParameter	signingKey)
+            string signatureAlgorithm,
+            X509Name subject,
+            AsymmetricKeyParameter publicKey,
+            Asn1Set attributes,
+            AsymmetricKeyParameter signingKey)
             : this(new Asn1SignatureFactory(signatureAlgorithm, signingKey), subject, publicKey, attributes)
-		{
-		}
+        {
+        }
 
         /// <summary>
         /// Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
@@ -286,7 +287,7 @@ namespace Org.BouncyCastle.Pkcs
         }
 
         private void Init(
-            ISignatureFactory signatureFactory, 
+            ISignatureFactory signatureFactory,
             X509Name subject,
             AsymmetricKeyParameter publicKey,
             Asn1Set attributes)
@@ -330,24 +331,24 @@ namespace Org.BouncyCastle.Pkcs
         /// </summary>
         /// <returns>The public key.</returns>
         public AsymmetricKeyParameter GetPublicKey()
-		{
-			return PublicKeyFactory.CreateKey(reqInfo.SubjectPublicKeyInfo);
-		}
-
-		/// <summary>
-		/// Verify Pkcs10 Cert Request is valid.
-		/// </summary>
-		/// <returns>true = valid.</returns>
-		public bool Verify()
-		{
-			return Verify(this.GetPublicKey());
-		}
-
-		public bool Verify(
-			AsymmetricKeyParameter publicKey)
-		{
+        {
+            return PublicKeyFactory.CreateKey(reqInfo.SubjectPublicKeyInfo);
+        }
+
+        /// <summary>
+        /// Verify Pkcs10 Cert Request is valid.
+        /// </summary>
+        /// <returns>true = valid.</returns>
+        public bool Verify()
+        {
+            return Verify(this.GetPublicKey());
+        }
+
+        public bool Verify(
+            AsymmetricKeyParameter publicKey)
+        {
             return Verify(new Asn1VerifierFactoryProvider(publicKey));
-		}
+        }
 
         public bool Verify(
             IVerifierFactoryProvider verifierProvider)
@@ -387,82 +388,82 @@ namespace Org.BouncyCastle.Pkcs
 
         // TODO Figure out how to set parameters on an ISigner
         private void SetSignatureParameters(
-			ISigner			signature,
-			Asn1Encodable	asn1Params)
-		{
-			if (asn1Params != null && !(asn1Params is Asn1Null))
-			{
-//				AlgorithmParameters sigParams = AlgorithmParameters.GetInstance(signature.getAlgorithm());
-//
-//				try
-//				{
-//					sigParams.init(asn1Params.ToAsn1Object().GetDerEncoded());
-//				}
-//				catch (IOException e)
-//				{
-//					throw new SignatureException("IOException decoding parameters: " + e.Message);
-//				}
-
-				if (Platform.EndsWith(signature.AlgorithmName, "MGF1"))
-				{
-					throw Platform.CreateNotImplementedException("signature algorithm with MGF1");
-
-//					try
-//					{
-//						signature.setParameter(sigParams.getParameterSpec(PSSParameterSpec.class));
-//					}
-//					catch (GeneralSecurityException e)
-//					{
-//						throw new SignatureException("Exception extracting parameters: " + e.getMessage());
-//					}
-				}
-			}
-		}
-
-		internal static string GetSignatureName(
-			AlgorithmIdentifier sigAlgId)
-		{
-			Asn1Encodable asn1Params = sigAlgId.Parameters;
-
-			if (asn1Params != null && !(asn1Params is Asn1Null))
-			{
+            ISigner signature,
+            Asn1Encodable asn1Params)
+        {
+            if (asn1Params != null && !(asn1Params is Asn1Null))
+            {
+                //				AlgorithmParameters sigParams = AlgorithmParameters.GetInstance(signature.getAlgorithm());
+                //
+                //				try
+                //				{
+                //					sigParams.init(asn1Params.ToAsn1Object().GetDerEncoded());
+                //				}
+                //				catch (IOException e)
+                //				{
+                //					throw new SignatureException("IOException decoding parameters: " + e.Message);
+                //				}
+
+                if (Platform.EndsWith(signature.AlgorithmName, "MGF1"))
+                {
+                    throw Platform.CreateNotImplementedException("signature algorithm with MGF1");
+
+                    //					try
+                    //					{
+                    //						signature.setParameter(sigParams.getParameterSpec(PSSParameterSpec.class));
+                    //					}
+                    //					catch (GeneralSecurityException e)
+                    //					{
+                    //						throw new SignatureException("Exception extracting parameters: " + e.getMessage());
+                    //					}
+                }
+            }
+        }
+
+        internal static string GetSignatureName(
+            AlgorithmIdentifier sigAlgId)
+        {
+            Asn1Encodable asn1Params = sigAlgId.Parameters;
+
+            if (asn1Params != null && !(asn1Params is Asn1Null))
+            {
                 if (sigAlgId.Algorithm.Equals(PkcsObjectIdentifiers.IdRsassaPss))
-				{
-					RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(asn1Params);
+                {
+                    RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(asn1Params);
                     return GetDigestAlgName(rsaParams.HashAlgorithm.Algorithm) + "withRSAandMGF1";
-				}
-			}
+                }
+            }
 
             return sigAlgId.Algorithm.Id;
-		}
-
-		private static string GetDigestAlgName(
-			DerObjectIdentifier digestAlgOID)
-		{
-			if (PkcsObjectIdentifiers.MD5.Equals(digestAlgOID))
-			{
-				return "MD5";
-			}
-			else if (OiwObjectIdentifiers.IdSha1.Equals(digestAlgOID))
-			{
-				return "SHA1";
-			}
-			else if (NistObjectIdentifiers.IdSha224.Equals(digestAlgOID))
-			{
-				return "SHA224";
-			}
-			else if (NistObjectIdentifiers.IdSha256.Equals(digestAlgOID))
-			{
-				return "SHA256";
-			}
-			else if (NistObjectIdentifiers.IdSha384.Equals(digestAlgOID))
-			{
-				return "SHA384";
-			}
-			else if (NistObjectIdentifiers.IdSha512.Equals(digestAlgOID))
-			{
-				return "SHA512";
-			}
+        }
+
+        private static string GetDigestAlgName(
+            DerObjectIdentifier digestAlgOID)
+        {
+            if (PkcsObjectIdentifiers.MD5.Equals(digestAlgOID))
+            {
+                return "MD5";
+            }
+            else if (OiwObjectIdentifiers.IdSha1.Equals(digestAlgOID))
+            {
+                return "SHA1";
+            }
+            else if (NistObjectIdentifiers.IdSha224.Equals(digestAlgOID))
+            {
+                return "SHA224";
+            }
+            else if (NistObjectIdentifiers.IdSha256.Equals(digestAlgOID))
+            {
+                return "SHA256";
+            }
+            else if (NistObjectIdentifiers.IdSha384.Equals(digestAlgOID))
+            {
+                return "SHA384";
+            }
+            else if (NistObjectIdentifiers.IdSha512.Equals(digestAlgOID))
+            {
+                return "SHA512";
+            }
             else if (NistObjectIdentifiers.IdSha512_224.Equals(digestAlgOID))
             {
                 return "SHA512(224)";
@@ -472,25 +473,83 @@ namespace Org.BouncyCastle.Pkcs
                 return "SHA512(256)";
             }
             else if (TeleTrusTObjectIdentifiers.RipeMD128.Equals(digestAlgOID))
-			{
-				return "RIPEMD128";
-			}
-			else if (TeleTrusTObjectIdentifiers.RipeMD160.Equals(digestAlgOID))
-			{
-				return "RIPEMD160";
-			}
-			else if (TeleTrusTObjectIdentifiers.RipeMD256.Equals(digestAlgOID))
-			{
-				return "RIPEMD256";
-			}
-			else if (CryptoProObjectIdentifiers.GostR3411.Equals(digestAlgOID))
-			{
-				return "GOST3411";
-			}
-			else
-			{
-				return digestAlgOID.Id;
-			}
-		}
-	}
+            {
+                return "RIPEMD128";
+            }
+            else if (TeleTrusTObjectIdentifiers.RipeMD160.Equals(digestAlgOID))
+            {
+                return "RIPEMD160";
+            }
+            else if (TeleTrusTObjectIdentifiers.RipeMD256.Equals(digestAlgOID))
+            {
+                return "RIPEMD256";
+            }
+            else if (CryptoProObjectIdentifiers.GostR3411.Equals(digestAlgOID))
+            {
+                return "GOST3411";
+            }
+            else
+            {
+                return digestAlgOID.Id;
+            }
+        }
+
+        /// <summary>
+        /// Returns X509Extensions if the attribute can be found and returns the extensions block.
+        /// </summary>
+        /// <returns>X509Extensions block or null if one cannot be found.</returns>
+        public X509Extensions GetX509Extensions()
+        {
+            if (reqInfo.Attributes != null)
+            {
+                foreach (Asn1Encodable item in reqInfo.Attributes)
+                {
+                    AttributePkcs attributePkcs;
+                    try
+                    {
+                        attributePkcs = AttributePkcs.GetInstance(item);
+
+                    }
+                    catch (ArgumentException ex)
+                    {
+                        throw new ArgumentException("encountered non PKCS attribute in extensions block", ex);
+                    }
+
+                    if (attributePkcs.AttrType.Equals(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest))
+                    {
+                        X509ExtensionsGenerator generator = new X509ExtensionsGenerator();
+
+                        Asn1Sequence extensionSequence = Asn1Sequence.GetInstance(attributePkcs.AttrValues[0]);
+
+
+                        foreach (Asn1Encodable seqItem in extensionSequence)
+                        {
+
+                            Asn1Sequence itemSeq = Asn1Sequence.GetInstance(seqItem);
+                            bool critical = itemSeq.Count == 3 && DerBoolean.GetInstance(itemSeq[1]).IsTrue;
+
+                            if (itemSeq.Count == 2)
+                            {
+                                generator.AddExtension(DerObjectIdentifier.GetInstance(itemSeq[0]), false, Asn1OctetString.GetInstance(itemSeq[1]).GetOctets());
+                            }
+                            else if (itemSeq.Count == 3)
+                            {
+                                generator.AddExtension(DerObjectIdentifier.GetInstance(itemSeq[0]), DerBoolean.GetInstance(itemSeq[1]).IsTrue, Asn1OctetString.GetInstance(itemSeq[2]).GetOctets());
+                            }
+                            else
+                            {
+                                throw new ArgumentException("incorrect sequence size of X509Extension got " + itemSeq.Count + " expected 2 or 3");
+                            }
+                        }
+
+                        return generator.Generate();
+                    }
+
+                }
+            }
+
+            return null;
+        }
+
+    }
 }