summary refs log tree commit diff
diff options
context:
space:
mode:
authorOren Novotny <oren@novotny.org>2018-08-31 10:01:01 -0400
committerOren Novotny <oren@novotny.org>2018-08-31 10:01:01 -0400
commitecb090130c0e8cb79c9a977a01bb0290b4854f52 (patch)
treec64d2f6f53a30dfe468d083e6b3ccf03d900a800
parentparallelize tests at fixture level (diff)
parentFurther work to improve constant time in OAEP. (diff)
downloadBouncyCastle.NET-ed25519-ecb090130c0e8cb79c9a977a01bb0290b4854f52.tar.xz
merge from master
-rw-r--r--crypto/NBuild.build2
-rw-r--r--crypto/Readme.html12
-rw-r--r--crypto/crypto.csproj15
-rw-r--r--crypto/src/asn1/cmp/PollRepContent.cs19
-rw-r--r--crypto/src/cms/CMSSignedDataGenerator.cs10
-rw-r--r--crypto/src/cms/CMSSignedDataStreamGenerator.cs16
-rw-r--r--crypto/src/cms/CMSSignedGenerator.cs14
-rw-r--r--crypto/src/crypto/encodings/OaepEncoding.cs15
-rw-r--r--crypto/src/crypto/operators/Asn1Signature.cs49
-rw-r--r--crypto/src/crypto/tls/DefaultTlsClient.cs22
-rw-r--r--crypto/src/crypto/tls/DefaultTlsDHVerifier.cs101
-rw-r--r--crypto/src/crypto/tls/DefaultTlsServer.cs4
-rw-r--r--crypto/src/crypto/tls/PskTlsClient.cs17
-rw-r--r--crypto/src/crypto/tls/PskTlsServer.cs2
-rw-r--r--crypto/src/crypto/tls/ServerDHParams.cs61
-rw-r--r--crypto/src/crypto/tls/TlsDHKeyExchange.cs32
-rw-r--r--crypto/src/crypto/tls/TlsDHUtilities.cs43
-rw-r--r--crypto/src/crypto/tls/TlsDHVerifier.cs15
-rw-r--r--crypto/src/crypto/tls/TlsDheKeyExchange.cs11
-rw-r--r--crypto/src/crypto/tls/TlsPskKeyExchange.cs15
-rw-r--r--crypto/src/pkcs/Pkcs10CertificationRequest.cs56
-rw-r--r--crypto/src/x509/store/X509CertStoreSelector.cs15
-rw-r--r--crypto/test/src/crypto/test/OAEPTest.cs79
23 files changed, 411 insertions, 214 deletions
diff --git a/crypto/NBuild.build b/crypto/NBuild.build
index 89c557702..dd63df279 100644
--- a/crypto/NBuild.build
+++ b/crypto/NBuild.build
@@ -16,7 +16,7 @@
   <property name="dist-path" value="./dist"/>
 
   <!-- Version -->
-  <property name="version" value="1.8.2"/>
+  <property name="version" value="1.8.3"/>
   <property name="name" value="BouncyCastle.Crypto"/>
 
   <property name="OPTIONAL_STRONG_NAME" value="" />
diff --git a/crypto/Readme.html b/crypto/Readme.html
index 9f4705f00..72e97516f 100644
--- a/crypto/Readme.html
+++ b/crypto/Readme.html
@@ -294,7 +294,17 @@ We state, where EC MQV has not otherwise been disabled or removed:
 		<hr style="WIDTH: 100%; HEIGHT: 2px">
 		<h3><a class="mozTocH3" name="mozTocId3413"></a>Notes:</h3>
 
-        <h4><a class="mozTocH4" name="mozTocId85317"></a>Release 1.8.3, TBD</h4>
+        <h4><a class="mozTocH4" name="mozTocId85317"></a>Release 1.8.3, Saturday August 11, 2018</h4>
+
+        <h5>IMPORTANT</h5>
+        <ul>
+            <li>
+                In this release, the TLS library has moved to a whitelisting approach for client-side validation of server-presented
+                Diffie-Hellman (DH) parameters. In the default configuration, if a ciphersuite using ephemeral DH is selected by the
+                server, the client will abort the handshake if the proposed DH group is not one of those specified in RFC 3526 or RFC 7919,
+                or if the DH prime is < 2048 bits. The client therefore no longer offers DH ciphersuites by default.
+            </li>
+        </ul>
 
         <h5>Additional Features and Functionality</h5>
         <ul>
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index 7cd8de821..b6dfb3963 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -4869,6 +4869,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\tls\DefaultTlsDHVerifier.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\tls\DefaultTlsEncryptionCredentials.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -5084,11 +5089,6 @@
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "src\crypto\tls\ServerDHParams.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
                     RelPath = "src\crypto\tls\ServerSrpParams.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -5249,6 +5249,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\tls\TlsDHVerifier.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\tls\TlsDsaSigner.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
diff --git a/crypto/src/asn1/cmp/PollRepContent.cs b/crypto/src/asn1/cmp/PollRepContent.cs
index f8bb098a2..ff75d7d6d 100644
--- a/crypto/src/asn1/cmp/PollRepContent.cs
+++ b/crypto/src/asn1/cmp/PollRepContent.cs
@@ -33,6 +33,25 @@ namespace Org.BouncyCastle.Asn1.Cmp
             throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), "obj");
 		}
 
+	    public PollRepContent(
+	        DerInteger certReqId,
+	        DerInteger checkAfter)
+	    {
+	        this.certReqId = certReqId;
+	        this.checkAfter = checkAfter;
+	        this.reason = null;
+	    }
+
+        public PollRepContent(
+	        DerInteger certReqId,
+	        DerInteger checkAfter,
+	        PkiFreeText reason)
+	    {
+	        this.certReqId = certReqId;
+	        this.checkAfter = checkAfter;
+	        this.reason = reason;
+	    }
+
 		public virtual DerInteger CertReqID
 		{
 			get { return certReqId; }
diff --git a/crypto/src/cms/CMSSignedDataGenerator.cs b/crypto/src/cms/CMSSignedDataGenerator.cs
index f63ed874e..5aa5f92ab 100644
--- a/crypto/src/cms/CMSSignedDataGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataGenerator.cs
@@ -513,15 +513,19 @@ namespace Org.BouncyCastle.Cms
 
 			if (_certs.Count != 0)
 			{
-				certificates = CmsUtilities.CreateBerSetFromList(_certs);
+				certificates = UseDerForCerts
+                    ?   CmsUtilities.CreateDerSetFromList(_certs)
+                    :   CmsUtilities.CreateBerSetFromList(_certs);
 			}
 
 			Asn1Set certrevlist = null;
 
 			if (_crls.Count != 0)
 			{
-				certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
-			}
+                certrevlist = UseDerForCrls
+                    ?   CmsUtilities.CreateDerSetFromList(_crls)
+                    :   CmsUtilities.CreateBerSetFromList(_crls);
+            }
 
 			Asn1OctetString octs = null;
 			if (encapsulate)
diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
index 55fde90df..1c8fac22b 100644
--- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
@@ -836,16 +836,20 @@ namespace Org.BouncyCastle.Cms
 
                 outer._digests.Clear();    // clear the current preserved digest state
 
-                if (outer._certs.Count > 0)
-                {
-                    Asn1Set certs = CmsUtilities.CreateBerSetFromList(outer._certs);
+				if (outer._certs.Count > 0)
+				{
+					Asn1Set certs = outer.UseDerForCerts
+                        ?   CmsUtilities.CreateDerSetFromList(outer._certs)
+                        :   CmsUtilities.CreateBerSetFromList(outer._certs);
 
                     WriteToGenerator(_sigGen, new BerTaggedObject(false, 0, certs));
                 }
 
-                if (outer._crls.Count > 0)
-                {
-                    Asn1Set crls = CmsUtilities.CreateBerSetFromList(outer._crls);
+				if (outer._crls.Count > 0)
+				{
+                    Asn1Set crls = outer.UseDerForCrls
+                        ?   CmsUtilities.CreateDerSetFromList(outer._crls)
+                        :   CmsUtilities.CreateBerSetFromList(outer._crls);
 
                     WriteToGenerator(_sigGen, new BerTaggedObject(false, 1, crls));
                 }
diff --git a/crypto/src/cms/CMSSignedGenerator.cs b/crypto/src/cms/CMSSignedGenerator.cs
index eec2e875b..249d70499 100644
--- a/crypto/src/cms/CMSSignedGenerator.cs
+++ b/crypto/src/cms/CMSSignedGenerator.cs
@@ -147,6 +147,8 @@ namespace Org.BouncyCastle.Cms
         internal IList _crls = Platform.CreateArrayList();
         internal IList _signers = Platform.CreateArrayList();
         internal IDictionary _digests = Platform.CreateHashtable();
+        internal bool _useDerForCerts = false;
+        internal bool _useDerForCrls = false;
 
         protected readonly SecureRandom rand;
 
@@ -251,6 +253,18 @@ namespace Org.BouncyCastle.Cms
             return Platform.CreateHashtable(_digests);
         }
 
+        public bool UseDerForCerts
+        {
+            get { return _useDerForCerts; }
+            set { this._useDerForCerts = value; }
+        }
+
+        public bool UseDerForCrls
+        {
+            get { return _useDerForCrls; }
+            set { this._useDerForCrls = value; }
+        }
+
         internal virtual void AddSignerCallback(
             SignerInformation si)
         {
diff --git a/crypto/src/crypto/encodings/OaepEncoding.cs b/crypto/src/crypto/encodings/OaepEncoding.cs
index 287876f12..92001589c 100644
--- a/crypto/src/crypto/encodings/OaepEncoding.cs
+++ b/crypto/src/crypto/encodings/OaepEncoding.cs
@@ -212,10 +212,17 @@ namespace Org.BouncyCastle.Crypto.Encodings
             // on encryption, we need to make sure our decrypted block comes back
             // the same size.
             //
+            bool wrongData = (block.Length < (2 * defHash.Length) + 1);
 
-            Array.Copy(data, 0, block, block.Length - data.Length, data.Length);
-
-            bool shortData = (block.Length < (2 * defHash.Length) + 1);
+            if (data.Length <= block.Length)
+            {
+                Array.Copy(data, 0, block, block.Length - data.Length, data.Length);
+            }
+            else
+            {
+                Array.Copy(data, 0, block, 0, block.Length);
+                wrongData = true;
+            }
 
             //
             // unmask the seed.
@@ -269,7 +276,7 @@ namespace Org.BouncyCastle.Crypto.Encodings
 
             start++;
 
-            if (defHashWrong | shortData | dataStartWrong)
+            if (defHashWrong | wrongData | dataStartWrong)
             {
                 Arrays.Fill(block, 0);
                 throw new InvalidCipherTextException("data wrong");
diff --git a/crypto/src/crypto/operators/Asn1Signature.cs b/crypto/src/crypto/operators/Asn1Signature.cs
index e023c1d18..373ba0cee 100644
--- a/crypto/src/crypto/operators/Asn1Signature.cs
+++ b/crypto/src/crypto/operators/Asn1Signature.cs
@@ -325,7 +325,8 @@ namespace Org.BouncyCastle.Crypto.Operators
     /// Calculator factory class for signature generation in ASN.1 based profiles that use an AlgorithmIdentifier to preserve
     /// signature algorithm details.
     /// </summary>
-	public class Asn1SignatureFactory: ISignatureFactory
+	public class Asn1SignatureFactory
+        : ISignatureFactory
 	{
 		private readonly AlgorithmIdentifier algID;
         private readonly string algorithm;
@@ -337,7 +338,8 @@ namespace Org.BouncyCastle.Crypto.Operators
         /// </summary>
         /// <param name="algorithm">The name of the signature algorithm to use.</param>
         /// <param name="privateKey">The private key to be used in the signing operation.</param>
-		public Asn1SignatureFactory (string algorithm, AsymmetricKeyParameter privateKey): this(algorithm, privateKey, null)
+		public Asn1SignatureFactory (string algorithm, AsymmetricKeyParameter privateKey)
+            : this(algorithm, privateKey, null)
 		{
 		}
 
@@ -347,14 +349,21 @@ namespace Org.BouncyCastle.Crypto.Operators
         /// <param name="algorithm">The name of the signature algorithm to use.</param>
         /// <param name="privateKey">The private key to be used in the signing operation.</param>
         /// <param name="random">The source of randomness to be used in signature calculation.</param>
-		public Asn1SignatureFactory (string algorithm, AsymmetricKeyParameter privateKey, SecureRandom random)
+		public Asn1SignatureFactory(string algorithm, AsymmetricKeyParameter privateKey, SecureRandom random)
 		{
-			DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid (algorithm);
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+            if (privateKey == null)
+                throw new ArgumentNullException("privateKey");
+            if (!privateKey.IsPrivate)
+                throw new ArgumentException("Key for signing must be private", "privateKey");
+
+			DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid(algorithm);
 
             this.algorithm = algorithm;
             this.privateKey = privateKey;
             this.random = random;
-			this.algID = X509Utilities.GetSigAlgID (sigOid, algorithm);
+			this.algID = X509Utilities.GetSigAlgID(sigOid, algorithm);
 		}
 
 		public Object AlgorithmDetails
@@ -365,16 +374,12 @@ namespace Org.BouncyCastle.Crypto.Operators
         public IStreamCalculator CreateCalculator()
         {
             ISigner sig = SignerUtilities.GetSigner(algorithm);
-
+            ICipherParameters cp = privateKey;
             if (random != null)
             {
-                sig.Init(true, new ParametersWithRandom(privateKey, random));
+                cp = new ParametersWithRandom(cp, random);
             }
-            else
-            {
-                sig.Init(true, privateKey);
-            }
-
+            sig.Init(true, cp);
             return new SigCalculator(sig);
         }
 
@@ -437,7 +442,8 @@ namespace Org.BouncyCastle.Crypto.Operators
     /// Verifier class for signature verification in ASN.1 based profiles that use an AlgorithmIdentifier to preserve
     /// signature algorithm details.
     /// </summary>
-    public class Asn1VerifierFactory: IVerifierFactory
+    public class Asn1VerifierFactory
+        : IVerifierFactory
 	{
 		private readonly AlgorithmIdentifier algID;
         private readonly AsymmetricKeyParameter publicKey;
@@ -447,15 +453,22 @@ namespace Org.BouncyCastle.Crypto.Operators
         /// </summary>
         /// <param name="algorithm">The name of the signature algorithm to use.</param>
         /// <param name="publicKey">The public key to be used in the verification operation.</param>
-        public Asn1VerifierFactory (String algorithm, AsymmetricKeyParameter publicKey)
+        public Asn1VerifierFactory(string algorithm, AsymmetricKeyParameter publicKey)
 		{
-			DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid (algorithm);
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+            if (publicKey == null)
+                throw new ArgumentNullException("publicKey");
+            if (publicKey.IsPrivate)
+                throw new ArgumentException("Key for verifying must be public", "publicKey");
+
+			DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid(algorithm);
 
             this.publicKey = publicKey;
-			this.algID = X509Utilities.GetSigAlgID (sigOid, algorithm);
+			this.algID = X509Utilities.GetSigAlgID(sigOid, algorithm);
 		}
 
-		public Asn1VerifierFactory (AlgorithmIdentifier algorithm, AsymmetricKeyParameter publicKey)
+		public Asn1VerifierFactory(AlgorithmIdentifier algorithm, AsymmetricKeyParameter publicKey)
 		{
             this.publicKey = publicKey;
 			this.algID = algorithm;
@@ -540,7 +553,7 @@ namespace Org.BouncyCastle.Crypto.Operators
 
 		public IVerifierFactory CreateVerifierFactory(Object algorithmDetails)
 		{
-            return new Asn1VerifierFactory ((AlgorithmIdentifier)algorithmDetails, publicKey);
+            return new Asn1VerifierFactory((AlgorithmIdentifier)algorithmDetails, publicKey);
 		}
 
 		/// <summary>
diff --git a/crypto/src/crypto/tls/DefaultTlsClient.cs b/crypto/src/crypto/tls/DefaultTlsClient.cs
index 32a86e503..64d29863b 100644
--- a/crypto/src/crypto/tls/DefaultTlsClient.cs
+++ b/crypto/src/crypto/tls/DefaultTlsClient.cs
@@ -14,14 +14,22 @@ namespace Org.BouncyCastle.Crypto.Tls
     public abstract class DefaultTlsClient
         :   AbstractTlsClient
     {
+        protected TlsDHVerifier mDHVerifier;
+
         public DefaultTlsClient()
-            :   base()
+            : this(new DefaultTlsCipherFactory())
         {
         }
 
         public DefaultTlsClient(TlsCipherFactory cipherFactory)
-            :   base(cipherFactory)
+            : this(cipherFactory, new DefaultTlsDHVerifier())
+        {
+        }
+
+        public DefaultTlsClient(TlsCipherFactory cipherFactory, TlsDHVerifier dhVerifier)
+            : base(cipherFactory)
         {
+            this.mDHVerifier = dhVerifier;
         }
 
         public override int[] GetCipherSuites()
@@ -34,12 +42,6 @@ namespace Org.BouncyCastle.Crypto.Tls
                 CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                 CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
                 CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
-                CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
-                CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
-                CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
-                CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
-                CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
-                CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
                 CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
                 CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256,
                 CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
@@ -85,12 +87,12 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange)
         {
-            return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null);
+            return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mDHVerifier, null);
         }
 
         protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange)
         {
-            return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null);
+            return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mDHVerifier, null);
         }
 
         protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange)
diff --git a/crypto/src/crypto/tls/DefaultTlsDHVerifier.cs b/crypto/src/crypto/tls/DefaultTlsDHVerifier.cs
new file mode 100644
index 000000000..ae26d04c3
--- /dev/null
+++ b/crypto/src/crypto/tls/DefaultTlsDHVerifier.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class DefaultTlsDHVerifier
+        : TlsDHVerifier
+    {
+        public static readonly int DefaultMinimumPrimeBits = 2048;
+
+        protected static readonly IList DefaultGroups = Platform.CreateArrayList();
+
+        private static void AddDefaultGroup(DHParameters dhParameters)
+        {
+            DefaultGroups.Add(dhParameters);
+        }
+
+        static DefaultTlsDHVerifier()
+        {
+            AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe2048);
+            AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe3072);
+            AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe4096);
+            AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe6144);
+            AddDefaultGroup(DHStandardGroups.rfc7919_ffdhe8192);
+
+            AddDefaultGroup(DHStandardGroups.rfc3526_1536);
+            AddDefaultGroup(DHStandardGroups.rfc3526_2048);
+            AddDefaultGroup(DHStandardGroups.rfc3526_3072);
+            AddDefaultGroup(DHStandardGroups.rfc3526_4096);
+            AddDefaultGroup(DHStandardGroups.rfc3526_6144);
+            AddDefaultGroup(DHStandardGroups.rfc3526_8192);
+        }
+
+        // IList is (DHParameters)
+        protected readonly IList mGroups;
+        protected readonly int mMinimumPrimeBits;
+
+        /// <summary>Accept various standard DH groups with 'P' at least <c>DefaultMinimumPrimeBits</c> bits.</summary>
+        public DefaultTlsDHVerifier()
+            : this(DefaultMinimumPrimeBits)
+        {
+        }
+
+        /// <summary>Accept various standard DH groups with 'P' at least the specified number of bits.</summary>
+        public DefaultTlsDHVerifier(int minimumPrimeBits)
+            : this(DefaultGroups, minimumPrimeBits)
+        {
+        }
+
+        /// <summary>Accept a custom set of group parameters, subject to a minimum bitlength for 'P'.</summary>
+        /// <param name="groups">An <c>IList</c> of acceptable <c>DHParameters</c>.</param>
+        /// <param name="minimumPrimeBits">The minimum acceptable bitlength of the 'P' parameter.</param>
+        public DefaultTlsDHVerifier(IList groups, int minimumPrimeBits)
+        {
+            this.mGroups = groups;
+            this.mMinimumPrimeBits = minimumPrimeBits;
+        }
+
+        public virtual bool Accept(DHParameters dhParameters)
+        {
+            return CheckMinimumPrimeBits(dhParameters) && CheckGroup(dhParameters);
+        }
+
+        public virtual int MinimumPrimeBits
+        {
+            get { return mMinimumPrimeBits; }
+        }
+
+        protected virtual bool AreGroupsEqual(DHParameters a, DHParameters b)
+        {
+            return a == b || (AreParametersEqual(a.P, b.P) && AreParametersEqual(a.G, b.G));
+        }
+
+        protected virtual bool AreParametersEqual(BigInteger a, BigInteger b)
+        {
+            return a == b || a.Equals(b);
+        }
+
+        protected virtual bool CheckGroup(DHParameters dhParameters)
+        {
+            foreach (DHParameters group in mGroups)
+            {
+                if (AreGroupsEqual(dhParameters, group))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        protected virtual bool CheckMinimumPrimeBits(DHParameters dhParameters)
+        {
+            return dhParameters.P.BitLength >= MinimumPrimeBits;
+        }
+    }
+}
diff --git a/crypto/src/crypto/tls/DefaultTlsServer.cs b/crypto/src/crypto/tls/DefaultTlsServer.cs
index 97eaa079d..90f357687 100644
--- a/crypto/src/crypto/tls/DefaultTlsServer.cs
+++ b/crypto/src/crypto/tls/DefaultTlsServer.cs
@@ -138,12 +138,12 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange)
         {
-            return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, GetDHParameters());
+            return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, GetDHParameters());
         }
 
         protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange)
         {
-            return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, GetDHParameters());
+            return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, GetDHParameters());
         }
 
         protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange)
diff --git a/crypto/src/crypto/tls/PskTlsClient.cs b/crypto/src/crypto/tls/PskTlsClient.cs
index 2ef80dcfd..d5fa43543 100644
--- a/crypto/src/crypto/tls/PskTlsClient.cs
+++ b/crypto/src/crypto/tls/PskTlsClient.cs
@@ -6,16 +6,23 @@ namespace Org.BouncyCastle.Crypto.Tls
     public class PskTlsClient
         :   AbstractTlsClient
     {
+        protected TlsDHVerifier mDHVerifier;
         protected TlsPskIdentity mPskIdentity;
 
         public PskTlsClient(TlsPskIdentity pskIdentity)
-            :   this(new DefaultTlsCipherFactory(), pskIdentity)
+            : this(new DefaultTlsCipherFactory(), pskIdentity)
         {
         }
 
         public PskTlsClient(TlsCipherFactory cipherFactory, TlsPskIdentity pskIdentity)
-            :   base(cipherFactory)
+            : this(cipherFactory, new DefaultTlsDHVerifier(), pskIdentity)
         {
+        }
+
+        public PskTlsClient(TlsCipherFactory cipherFactory, TlsDHVerifier dhVerifier, TlsPskIdentity pskIdentity)
+            : base(cipherFactory)
+        {
+            this.mDHVerifier = dhVerifier;
             this.mPskIdentity = pskIdentity;
         }
 
@@ -25,8 +32,6 @@ namespace Org.BouncyCastle.Crypto.Tls
             {
                 CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
                 CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
-                CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
-                CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA
             };
         }
 
@@ -63,8 +68,8 @@ namespace Org.BouncyCastle.Crypto.Tls
 
         protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange)
         {
-            return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, null, mNamedCurves,
-                mClientECPointFormats, mServerECPointFormats);
+            return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, mDHVerifier, null,
+                mNamedCurves, mClientECPointFormats, mServerECPointFormats);
         }
     }
 }
diff --git a/crypto/src/crypto/tls/PskTlsServer.cs b/crypto/src/crypto/tls/PskTlsServer.cs
index b0fb67c04..a3778420d 100644
--- a/crypto/src/crypto/tls/PskTlsServer.cs
+++ b/crypto/src/crypto/tls/PskTlsServer.cs
@@ -87,7 +87,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange)
         {
             return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null, mPskIdentityManager,
-                GetDHParameters(), mNamedCurves, mClientECPointFormats, mServerECPointFormats);
+                null, GetDHParameters(), mNamedCurves, mClientECPointFormats, mServerECPointFormats);
         }
     }
 }
diff --git a/crypto/src/crypto/tls/ServerDHParams.cs b/crypto/src/crypto/tls/ServerDHParams.cs
deleted file mode 100644
index b09262771..000000000
--- a/crypto/src/crypto/tls/ServerDHParams.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-using System.IO;
-
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
-
-namespace Org.BouncyCastle.Crypto.Tls
-{
-    public class ServerDHParams
-    {
-        protected readonly DHPublicKeyParameters mPublicKey;
-
-        public ServerDHParams(DHPublicKeyParameters publicKey)
-        {
-            if (publicKey == null)
-                throw new ArgumentNullException("publicKey");
-
-            this.mPublicKey = publicKey;
-        }
-
-        public virtual DHPublicKeyParameters PublicKey
-        {
-            get { return mPublicKey; }
-        }
-
-        /**
-         * Encode this {@link ServerDHParams} to a {@link Stream}.
-         * 
-         * @param output
-         *            the {@link Stream} to encode to.
-         * @throws IOException
-         */
-        public virtual void Encode(Stream output)
-        {
-            DHParameters dhParameters = mPublicKey.Parameters;
-            BigInteger Ys = mPublicKey.Y;
-
-            TlsDHUtilities.WriteDHParameter(dhParameters.P, output);
-            TlsDHUtilities.WriteDHParameter(dhParameters.G, output);
-            TlsDHUtilities.WriteDHParameter(Ys, output);
-        }
-
-        /**
-         * Parse a {@link ServerDHParams} from a {@link Stream}.
-         * 
-         * @param input
-         *            the {@link Stream} to parse from.
-         * @return a {@link ServerDHParams} object.
-         * @throws IOException
-         */
-        public static ServerDHParams Parse(Stream input)
-        {
-            BigInteger p = TlsDHUtilities.ReadDHParameter(input);
-            BigInteger g = TlsDHUtilities.ReadDHParameter(input);
-            BigInteger Ys = TlsDHUtilities.ReadDHParameter(input);
-
-            return new ServerDHParams(
-                TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Ys, new DHParameters(p, g))));
-        }
-    }
-}
diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
index d179068bb..59d52265b 100644
--- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
@@ -4,7 +4,6 @@ using System.IO;
 
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 
 namespace Org.BouncyCastle.Crypto.Tls
@@ -14,6 +13,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         :   AbstractTlsKeyExchange
     {
         protected TlsSigner mTlsSigner;
+        protected TlsDHVerifier mDHVerifier;
         protected DHParameters mDHParameters;
 
         protected AsymmetricKeyParameter mServerPublicKey;
@@ -22,7 +22,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected DHPrivateKeyParameters mDHAgreePrivateKey;
         protected DHPublicKeyParameters mDHAgreePublicKey;
 
-        public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
+        public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters)
             :   base(keyExchange, supportedSignatureAlgorithms)
         {
             switch (keyExchange)
@@ -42,6 +42,7 @@ namespace Org.BouncyCastle.Crypto.Tls
                 throw new InvalidOperationException("unsupported key exchange algorithm");
             }
 
+            this.mDHVerifier = dhVerifier;
             this.mDHParameters = dhParameters;
         }
 
@@ -84,8 +85,8 @@ namespace Org.BouncyCastle.Crypto.Tls
             {
                 try
                 {
-                    this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey);
-                    this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
+                    this.mDHAgreePublicKey = (DHPublicKeyParameters)this.mServerPublicKey;
+                    this.mDHParameters = mDHAgreePublicKey.Parameters;
                 }
                 catch (InvalidCastException e)
                 {
@@ -143,10 +144,8 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             // DH_anon is handled here, DHE_* in a subclass
 
-            ServerDHParams dhParams = ServerDHParams.Parse(input);
-
-            this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey);
-            this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
+            this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, input);
+            this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
         }
 
         public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
@@ -223,9 +222,7 @@ namespace Org.BouncyCastle.Crypto.Tls
                 return;
             }
 
-            BigInteger Yc = TlsDHUtilities.ReadDHParameter(input);
-
-            this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters));
+            this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
         }
 
         public override byte[] GeneratePremasterSecret()
@@ -242,18 +239,5 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             throw new TlsFatalAlert(AlertDescription.internal_error);
         }
-
-        protected virtual int MinimumPrimeBits
-        {
-            get { return 1024; }
-        }
-
-        protected virtual DHParameters ValidateDHParameters(DHParameters parameters)
-        {
-            if (parameters.P.BitLength < MinimumPrimeBits)
-                throw new TlsFatalAlert(AlertDescription.insufficient_security);
-
-            return TlsDHUtilities.ValidateDHParameters(parameters);
-        }
     }
 }
diff --git a/crypto/src/crypto/tls/TlsDHUtilities.cs b/crypto/src/crypto/tls/TlsDHUtilities.cs
index 6df61cbed..9567ee062 100644
--- a/crypto/src/crypto/tls/TlsDHUtilities.cs
+++ b/crypto/src/crypto/tls/TlsDHUtilities.cs
@@ -417,46 +417,43 @@ namespace Org.BouncyCastle.Crypto.Tls
             AsymmetricCipherKeyPair kp = GenerateDHKeyPair(random, dhParams);
 
             DHPublicKeyParameters dhPublic = (DHPublicKeyParameters)kp.Public;
-            new ServerDHParams(dhPublic).Encode(output);
+            WriteDHParameters(dhParams, output);
+            WriteDHParameter(dhPublic.Y, output);
 
             return (DHPrivateKeyParameters)kp.Private;
         }
 
-        public static DHParameters ValidateDHParameters(DHParameters parameters)
+        public static BigInteger ReadDHParameter(Stream input)
         {
-            BigInteger p = parameters.P;
-            BigInteger g = parameters.G;
-
-            if (!p.IsProbablePrime(2))
-                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
-            if (g.CompareTo(Two) < 0 || g.CompareTo(p.Subtract(Two)) > 0)
-                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
-
-
-            return parameters;
+            return new BigInteger(1, TlsUtilities.ReadOpaque16(input));
         }
 
-        public static DHPublicKeyParameters ValidateDHPublicKey(DHPublicKeyParameters key)
+        public static DHParameters ReadDHParameters(Stream input)
         {
-            DHParameters parameters = ValidateDHParameters(key.Parameters);
-
-            BigInteger Y = key.Y;
-            if (Y.CompareTo(Two) < 0 || Y.CompareTo(parameters.P.Subtract(Two)) > 0)
-                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            BigInteger p = ReadDHParameter(input);
+            BigInteger g = ReadDHParameter(input);
 
-            // TODO See RFC 2631 for more discussion of Diffie-Hellman validation
-
-            return key;
+            return new DHParameters(p, g);
         }
 
-        public static BigInteger ReadDHParameter(Stream input)
+        public static DHParameters ReceiveDHParameters(TlsDHVerifier dhVerifier, Stream input)
         {
-            return new BigInteger(1, TlsUtilities.ReadOpaque16(input));
+            DHParameters dhParameters = ReadDHParameters(input);
+            if (!dhVerifier.Accept(dhParameters))
+                throw new TlsFatalAlert(AlertDescription.insufficient_security);
+
+            return dhParameters;
         }
 
         public static void WriteDHParameter(BigInteger x, Stream output)
         {
             TlsUtilities.WriteOpaque16(BigIntegers.AsUnsignedByteArray(x), output);
         }
+
+        public static void WriteDHParameters(DHParameters dhParameters, Stream output)
+        {
+            WriteDHParameter(dhParameters.P, output);
+            WriteDHParameter(dhParameters.G, output);
+        }
     }
 }
diff --git a/crypto/src/crypto/tls/TlsDHVerifier.cs b/crypto/src/crypto/tls/TlsDHVerifier.cs
new file mode 100644
index 000000000..867403c3c
--- /dev/null
+++ b/crypto/src/crypto/tls/TlsDHVerifier.cs
@@ -0,0 +1,15 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>An interface for verifying that Diffie-Hellman parameters are acceptable.</summary>
+    public interface TlsDHVerifier
+    {
+        /// <summary>Verify that the given <c>DHParameters</c> are acceptable.</summary>
+        /// <param name="dhParameters">The <c>DHParameters</c> to verify.</param>
+        /// <returns>true if (and only if) the specified parameters are acceptable.</returns>
+        bool Accept(DHParameters dhParameters);
+    }
+}
diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
index cdd629247..402c74720 100644
--- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
@@ -3,7 +3,6 @@ using System.Collections;
 using System.IO;
 
 using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Utilities.IO;
 
@@ -14,8 +13,8 @@ namespace Org.BouncyCastle.Crypto.Tls
     {
         protected TlsSignerCredentials mServerCredentials = null;
 
-        public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
-            :   base(keyExchange, supportedSignatureAlgorithms, dhParameters)
+        public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters)
+            :   base(keyExchange, supportedSignatureAlgorithms, dhVerifier, dhParameters)
         {
         }
 
@@ -69,7 +68,8 @@ namespace Org.BouncyCastle.Crypto.Tls
             SignerInputBuffer buf = new SignerInputBuffer();
             Stream teeIn = new TeeInputStream(input, buf);
 
-            ServerDHParams dhParams = ServerDHParams.Parse(teeIn);
+            this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, teeIn);
+            this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(teeIn), mDHParameters);
 
             DigitallySigned signed_params = ParseSignature(input);
 
@@ -77,9 +77,6 @@ namespace Org.BouncyCastle.Crypto.Tls
             buf.UpdateSigner(signer);
             if (!signer.VerifySignature(signed_params.Signature))
                 throw new TlsFatalAlert(AlertDescription.decrypt_error);
-
-            this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey);
-            this.mDHParameters = ValidateDHParameters(mDHAgreePublicKey.Parameters);
         }
 
         protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm,
diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
index 0af7f7a69..36ef09e85 100644
--- a/crypto/src/crypto/tls/TlsPskKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
@@ -4,7 +4,6 @@ using System.IO;
 
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.IO;
@@ -18,6 +17,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected TlsPskIdentity mPskIdentity;
         protected TlsPskIdentityManager mPskIdentityManager;
 
+        protected TlsDHVerifier mDHVerifier;
         protected DHParameters mDHParameters;
         protected int[] mNamedCurves;
         protected byte[] mClientECPointFormats, mServerECPointFormats;
@@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected byte[] mPremasterSecret;
 
         public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity,
-            TlsPskIdentityManager pskIdentityManager, DHParameters dhParameters, int[] namedCurves,
+            TlsPskIdentityManager pskIdentityManager, TlsDHVerifier dhVerifier, DHParameters dhParameters, int[] namedCurves,
             byte[] clientECPointFormats, byte[] serverECPointFormats)
             :   base(keyExchange, supportedSignatureAlgorithms)
         {
@@ -54,6 +54,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             this.mPskIdentity = pskIdentity;
             this.mPskIdentityManager = pskIdentityManager;
+            this.mDHVerifier = dhVerifier;
             this.mDHParameters = dhParameters;
             this.mNamedCurves = namedCurves;
             this.mClientECPointFormats = clientECPointFormats;
@@ -162,10 +163,8 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
             {
-                ServerDHParams serverDHParams = ServerDHParams.Parse(input);
-
-                this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(serverDHParams.PublicKey);
-                this.mDHParameters = mDHAgreePublicKey.Parameters;
+                this.mDHParameters = TlsDHUtilities.ReceiveDHParameters(mDHVerifier, input);
+                this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
             }
             else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
             {
@@ -240,9 +239,7 @@ namespace Org.BouncyCastle.Crypto.Tls
 
             if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
             {
-                BigInteger Yc = TlsDHUtilities.ReadDHParameter(input);
-
-                this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(new DHPublicKeyParameters(Yc, mDHParameters));
+                this.mDHAgreePublicKey = new DHPublicKeyParameters(TlsDHUtilities.ReadDHParameter(input), mDHParameters);
             }
             else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
             {
diff --git a/crypto/src/pkcs/Pkcs10CertificationRequest.cs b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
index 24dc9b1cc..34bda3815 100644
--- a/crypto/src/pkcs/Pkcs10CertificationRequest.cs
+++ b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
@@ -210,71 +210,73 @@ namespace Org.BouncyCastle.Pkcs
         /// <param name="publicKey">Public Key to be included in cert reqest.</param>
         /// <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>
-        [Obsolete("Use constructor with an ISignatureFactory")]
         public Pkcs10CertificationRequest(
 			string					signatureAlgorithm,
 			X509Name				subject,
 			AsymmetricKeyParameter	publicKey,
 			Asn1Set					attributes,
 			AsymmetricKeyParameter	signingKey)
+            : this(new Asn1SignatureFactory(signatureAlgorithm, signingKey), subject, publicKey, attributes)
 		{
-			if (signatureAlgorithm == null)
-				throw new ArgumentNullException("signatureAlgorithm");
-			if (subject == null)
-				throw new ArgumentNullException("subject");
-			if (publicKey == null)
-				throw new ArgumentNullException("publicKey");
-			if (publicKey.IsPrivate)
-				throw new ArgumentException("expected public key", "publicKey");
-			if (!signingKey.IsPrivate)
-				throw new ArgumentException("key for signing must be private", "signingKey");
-
-            init(new Asn1SignatureFactory(signatureAlgorithm, signingKey), subject, publicKey, attributes, signingKey);
 		}
 
         /// <summary>
         /// Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
         /// </summary>
-        ///<param name="signatureCalculatorFactory">The factory for signature calculators to sign the PKCS#10 request with.</param>
+        ///<param name="signatureFactory">The factory for signature calculators to sign the PKCS#10 request with.</param>
         /// <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
         /// <param name="publicKey">Public Key to be included in cert reqest.</param>
         /// <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>
+        /// <param name="signingKey">Ignored.</param>
+        [Obsolete("Use constructor without 'signingKey' parameter (ignored here)")]
         public Pkcs10CertificationRequest(
-            ISignatureFactory signatureCalculatorFactory,
+            ISignatureFactory signatureFactory,
             X509Name subject,
             AsymmetricKeyParameter publicKey,
             Asn1Set attributes,
             AsymmetricKeyParameter signingKey)
+            : this(signatureFactory, subject, publicKey, attributes)
         {
-            if (signatureCalculatorFactory == null)
-                throw new ArgumentNullException("signatureCalculator");
+        }
+
+        /// <summary>
+        /// Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
+        /// </summary>
+        ///<param name="signatureFactory">The factory for signature calculators to sign the PKCS#10 request with.</param>
+        /// <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
+        /// <param name="publicKey">Public Key to be included in cert reqest.</param>
+        /// <param name="attributes">ASN1Set of Attributes.</param>
+        public Pkcs10CertificationRequest(
+            ISignatureFactory signatureFactory,
+            X509Name subject,
+            AsymmetricKeyParameter publicKey,
+            Asn1Set attributes)
+        {
+            if (signatureFactory == null)
+                throw new ArgumentNullException("signatureFactory");
             if (subject == null)
                 throw new ArgumentNullException("subject");
             if (publicKey == null)
                 throw new ArgumentNullException("publicKey");
             if (publicKey.IsPrivate)
                 throw new ArgumentException("expected public key", "publicKey");
-            if (!signingKey.IsPrivate)
-                throw new ArgumentException("key for signing must be private", "signingKey");
 
-            init(signatureCalculatorFactory, subject, publicKey, attributes, signingKey);
+            Init(signatureFactory, subject, publicKey, attributes);
         }
 
-        private void init(
-            ISignatureFactory signatureCalculator, 
+        private void Init(
+            ISignatureFactory signatureFactory, 
             X509Name subject,
             AsymmetricKeyParameter publicKey,
-            Asn1Set attributes,
-            AsymmetricKeyParameter signingKey)
+            Asn1Set attributes)
         {
-            this.sigAlgId = (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails;
+            this.sigAlgId = (AlgorithmIdentifier)signatureFactory.AlgorithmDetails;
 
             SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
 
             this.reqInfo = new CertificationRequestInfo(subject, pubInfo, attributes);
 
-            IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator();
+            IStreamCalculator streamCalculator = signatureFactory.CreateCalculator();
 
             byte[] reqInfoData = reqInfo.GetDerEncoded();
 
diff --git a/crypto/src/x509/store/X509CertStoreSelector.cs b/crypto/src/x509/store/X509CertStoreSelector.cs
index 3874edf1d..f92a4ac03 100644
--- a/crypto/src/x509/store/X509CertStoreSelector.cs
+++ b/crypto/src/x509/store/X509CertStoreSelector.cs
@@ -21,6 +21,7 @@ namespace Org.BouncyCastle.X509.Store
 		private X509Certificate certificate;
 		private DateTimeObject certificateValid;
 		private ISet extendedKeyUsage;
+        private bool ignoreX509NameOrdering;
 		private X509Name issuer;
 		private bool[] keyUsage;
 		private ISet policy;
@@ -43,6 +44,7 @@ namespace Org.BouncyCastle.X509.Store
 			this.certificate = o.Certificate;
 			this.certificateValid = o.CertificateValid;
 			this.extendedKeyUsage = o.ExtendedKeyUsage;
+            this.ignoreX509NameOrdering = o.IgnoreX509NameOrdering;
 			this.issuer = o.Issuer;
 			this.keyUsage = o.KeyUsage;
 			this.policy = o.Policy;
@@ -95,6 +97,12 @@ namespace Org.BouncyCastle.X509.Store
 			set { extendedKeyUsage = CopySet(value); }
 		}
 
+        public bool IgnoreX509NameOrdering
+        {
+            get { return ignoreX509NameOrdering; }
+            set { this.ignoreX509NameOrdering = value; }
+        }
+
 		public X509Name Issuer
 		{
 			get { return issuer; }
@@ -140,7 +148,8 @@ namespace Org.BouncyCastle.X509.Store
 			set { subject = value; }
 		}
 
-		public string SubjectAsString
+        [Obsolete("Avoid working with X509Name objects in string form")]
+        public string SubjectAsString
 		{
 			get { return subject != null ? subject.ToString() : null; }
 		}
@@ -212,7 +221,7 @@ namespace Org.BouncyCastle.X509.Store
 				}
 			}
 
-			if (issuer != null && !issuer.Equivalent(c.IssuerDN, true))
+			if (issuer != null && !issuer.Equivalent(c.IssuerDN, !ignoreX509NameOrdering))
 				return false;
 
 			if (keyUsage != null)
@@ -277,7 +286,7 @@ namespace Org.BouncyCastle.X509.Store
 			if (serialNumber != null && !serialNumber.Equals(c.SerialNumber))
 				return false;
 
-			if (subject != null && !subject.Equivalent(c.SubjectDN, true))
+            if (subject != null && !subject.Equivalent(c.SubjectDN, !ignoreX509NameOrdering))
 				return false;
 
 			if (!MatchExtension(subjectKeyIdentifier, c, X509Extensions.SubjectKeyIdentifier))
diff --git a/crypto/test/src/crypto/test/OAEPTest.cs b/crypto/test/src/crypto/test/OAEPTest.cs
index 39af21137..781e92ba5 100644
--- a/crypto/test/src/crypto/test/OAEPTest.cs
+++ b/crypto/test/src/crypto/test/OAEPTest.cs
@@ -8,6 +8,7 @@ using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto.Digests;
 using Org.BouncyCastle.Crypto.Encodings;
 using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
@@ -780,8 +781,10 @@ namespace Org.BouncyCastle.Crypto.Tests
             OaepVecTest(1027, 5, pubParam, privParam, seed_1027_5, input_1027_5, output_1027_5);
             OaepVecTest(1027, 6, pubParam, privParam, seed_1027_6, input_1027_6, output_1027_6);
 
+            TestForHighByteError("invalidCiphertextOaepTest 1024", 1024);
+
             //
-            // OAEP - public encrypt, private decrypt  differring hashes
+            // OAEP - public encrypt, private decrypt, differing hashes
             //
             IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), new byte[10]);
 
@@ -822,8 +825,78 @@ namespace Org.BouncyCastle.Crypto.Tests
             }
         }
 
-        public static void MainOld(
-            string[] args)
+        private void TestForHighByteError(string label, int keySizeBits)
+        {
+            // draw a key of the size asked
+            BigInteger e = BigInteger.One.ShiftLeft(16).Add(BigInteger.One);
+
+            IAsymmetricCipherKeyPairGenerator kpGen = new RsaKeyPairGenerator();
+
+            kpGen.Init(new RsaKeyGenerationParameters(e, new SecureRandom(), keySizeBits, 100));
+
+            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();
+
+            IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine());
+
+            // obtain a known good ciphertext
+            cipher.Init(true, new ParametersWithRandom(kp.Public, new VecRand(seed)));
+            byte[] m = { 42 };
+            byte[] c = cipher.ProcessBlock(m, 0, m.Length);
+            int keySizeBytes = (keySizeBits + 7) / 8;
+            if (c.Length != keySizeBytes)
+            {
+                Fail(label + " failed ciphertext size");
+            }
+
+            BigInteger n = ((RsaPrivateCrtKeyParameters)kp.Private).Modulus;
+
+            // decipher
+            cipher.Init(false, kp.Private);
+            byte[] r = cipher.ProcessBlock(c, 0, keySizeBytes);
+            if (r.Length != 1 || r[0] != 42)
+            {
+                Fail(label + " failed first decryption of test message");
+            }
+
+            // decipher again
+            r = cipher.ProcessBlock(c, 0, keySizeBytes);
+            if (r.Length != 1 || r[0] != 42)
+            {
+                Fail(label + " failed second decryption of test message");
+            }
+
+            // check hapazard incorrect ciphertexts
+            for (int i = keySizeBytes * 8; --i >= 0; )
+            {
+                c[i / 8] ^= (byte)(1 << (i & 7));
+                bool ko = true;
+                try
+                {
+                    BigInteger cV = new BigInteger(1, c);
+
+                    // don't pass in c if it will be rejected trivially
+                    if (cV.CompareTo(n) < 0)
+                    {
+                        r = cipher.ProcessBlock(c, 0, keySizeBytes);
+                    }
+                    else
+                    {
+                        ko = false; // size errors are picked up at start
+                    }
+                }
+                catch (InvalidCipherTextException)
+                {
+                    ko = false;
+                }
+                if (ko)
+                {
+                    Fail(label + " invalid ciphertext caused no exception");
+                }
+                c[i / 8] ^= (byte)(1 << (i & 7));
+            }
+        }
+
+        public static void MainOld(string[] args)
         {
             RunTest(new OaepTest());
         }