summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/crypto.csproj55
-rw-r--r--crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs50
-rw-r--r--crypto/src/bcpg/BcpgOutputStream.cs1
-rw-r--r--crypto/src/bcpg/LiteralDataPacket.cs6
-rw-r--r--crypto/src/cms/CMSAuthenticatedDataGenerator.cs2
-rw-r--r--crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs2
-rw-r--r--crypto/src/cms/CMSEnvelopedHelper.cs2
-rw-r--r--crypto/src/cms/CMSSignedDataGenerator.cs3
-rw-r--r--crypto/src/cms/CMSSignedDataStreamGenerator.cs2
-rw-r--r--crypto/src/cms/DigOutputStream.cs28
-rw-r--r--crypto/src/cms/MacOutputStream.cs28
-rw-r--r--crypto/src/cms/SigOutputStream.cs43
-rw-r--r--crypto/src/cms/SignerInfoGenerator.cs4
-rw-r--r--crypto/src/cms/SignerInformation.cs14
-rw-r--r--crypto/src/crypto/IRsa.cs16
-rw-r--r--crypto/src/crypto/engines/RSABlindedEngine.cs13
-rw-r--r--crypto/src/crypto/engines/RSABlindingEngine.cs12
-rw-r--r--crypto/src/crypto/engines/RSACoreEngine.cs29
-rw-r--r--crypto/src/crypto/engines/RsaEngine.cs24
-rw-r--r--crypto/src/crypto/generators/OpenBsdBCrypt.cs4
-rw-r--r--crypto/src/crypto/io/DigestSink.cs35
-rw-r--r--crypto/src/crypto/io/MacSink.cs35
-rw-r--r--crypto/src/crypto/io/SignerSink.cs35
-rw-r--r--crypto/src/crypto/operators/Asn1Signature.cs194
-rw-r--r--crypto/src/crypto/operators/DefaultSignatureCalculator.cs28
-rw-r--r--crypto/src/crypto/operators/DefaultSignatureResult.cs27
-rw-r--r--crypto/src/crypto/operators/DefaultVerifierCalculator.cs28
-rw-r--r--crypto/src/crypto/operators/DefaultVerifierResult.cs29
-rw-r--r--crypto/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs178
-rw-r--r--crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs3
-rw-r--r--crypto/src/crypto/parameters/X448PrivateKeyParameters.cs3
-rw-r--r--crypto/src/crypto/prng/ThreadedSeedGenerator.cs153
-rw-r--r--crypto/src/crypto/signers/Ed25519Signer.cs17
-rw-r--r--crypto/src/crypto/signers/Ed25519ctxSigner.cs17
-rw-r--r--crypto/src/crypto/signers/Ed25519phSigner.cs1
-rw-r--r--crypto/src/crypto/signers/Ed448Signer.cs25
-rw-r--r--crypto/src/crypto/signers/Ed448phSigner.cs1
-rw-r--r--crypto/src/crypto/signers/RsaDigestSigner.cs13
-rw-r--r--crypto/src/crypto/tls/TlsDHKeyExchange.cs6
-rw-r--r--crypto/src/crypto/tls/TlsDheKeyExchange.cs6
-rw-r--r--crypto/src/crypto/tls/TlsPskKeyExchange.cs9
-rw-r--r--crypto/src/math/ec/rfc7748/X25519.cs15
-rw-r--r--crypto/src/math/ec/rfc7748/X448.cs25
-rw-r--r--crypto/src/math/ec/rfc8032/Ed25519.cs7
-rw-r--r--crypto/src/math/ec/rfc8032/Ed448.cs27
-rw-r--r--crypto/src/openpgp/PgpUtilities.cs2
-rw-r--r--crypto/src/pkcs/Pkcs12Store.cs4
-rw-r--r--crypto/src/security/ParameterUtilities.cs9
-rw-r--r--crypto/src/security/SignerUtilities.cs12
-rw-r--r--crypto/src/util/Arrays.cs10
50 files changed, 705 insertions, 587 deletions
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index d0f672e8e..c6dd131e7 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -2869,11 +2869,6 @@
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "src\cms\DigOutputStream.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
                     RelPath = "src\cms\IDigestCalculator.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -2909,11 +2904,6 @@
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "src\cms\MacOutputStream.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
                     RelPath = "src\cms\OriginatorId.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -2989,11 +2979,6 @@
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "src\cms\SigOutputStream.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
                     RelPath = "src\cms\SimpleAttributeTableGenerator.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -3139,6 +3124,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\IRsa.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\ISignatureFactory.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -3989,16 +3979,31 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\io\DigestSink.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\io\DigestStream.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\io\MacSink.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\io\MacStream.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\io\SignerSink.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\io\SignerStream.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -4184,6 +4189,26 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\crypto\operators\DefaultSignatureCalculator.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\crypto\operators\DefaultSignatureResult.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\crypto\operators\DefaultVerifierCalculator.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\crypto\operators\DefaultVerifierResult.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\crypto\paddings\BlockCipherPadding.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
diff --git a/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs b/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs
index 721299105..738a97eb4 100644
--- a/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs
+++ b/crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs
@@ -9,14 +9,14 @@ namespace Org.BouncyCastle.Asn1.Pkcs
     public class RsaPrivateKeyStructure
         : Asn1Encodable
     {
-        private readonly BigInteger	modulus;
-        private readonly BigInteger	publicExponent;
-        private readonly BigInteger	privateExponent;
-        private readonly BigInteger	prime1;
-        private readonly BigInteger	prime2;
-        private readonly BigInteger	exponent1;
-        private readonly BigInteger	exponent2;
-        private readonly BigInteger	coefficient;
+        private readonly BigInteger modulus;
+        private readonly BigInteger publicExponent;
+        private readonly BigInteger privateExponent;
+        private readonly BigInteger prime1;
+        private readonly BigInteger prime2;
+        private readonly BigInteger exponent1;
+        private readonly BigInteger exponent2;
+        private readonly BigInteger coefficient;
 
         public static RsaPrivateKeyStructure GetInstance(Asn1TaggedObject obj, bool isExplicit)
         {
@@ -33,14 +33,14 @@ namespace Org.BouncyCastle.Asn1.Pkcs
         }
 
         public RsaPrivateKeyStructure(
-            BigInteger	modulus,
-            BigInteger	publicExponent,
-            BigInteger	privateExponent,
-            BigInteger	prime1,
-            BigInteger	prime2,
-            BigInteger	exponent1,
-            BigInteger	exponent2,
-            BigInteger	coefficient)
+            BigInteger modulus,
+            BigInteger publicExponent,
+            BigInteger privateExponent,
+            BigInteger prime1,
+            BigInteger prime2,
+            BigInteger exponent1,
+            BigInteger exponent2,
+            BigInteger coefficient)
         {
             this.modulus = modulus;
             this.publicExponent = publicExponent;
@@ -56,18 +56,18 @@ namespace Org.BouncyCastle.Asn1.Pkcs
         public RsaPrivateKeyStructure(
             Asn1Sequence seq)
         {
-            BigInteger version = ((DerInteger) seq[0]).Value;
+            BigInteger version = ((DerInteger)seq[0]).Value;
             if (version.IntValue != 0)
                 throw new ArgumentException("wrong version for RSA private key");
 
-            modulus = ((DerInteger) seq[1]).Value;
-            publicExponent = ((DerInteger) seq[2]).Value;
-            privateExponent = ((DerInteger) seq[3]).Value;
-            prime1 = ((DerInteger) seq[4]).Value;
-            prime2 = ((DerInteger) seq[5]).Value;
-            exponent1 = ((DerInteger) seq[6]).Value;
-            exponent2 = ((DerInteger) seq[7]).Value;
-            coefficient = ((DerInteger) seq[8]).Value;
+            modulus = ((DerInteger)seq[1]).Value;
+            publicExponent = ((DerInteger)seq[2]).Value;
+            privateExponent = ((DerInteger)seq[3]).Value;
+            prime1 = ((DerInteger)seq[4]).Value;
+            prime2 = ((DerInteger)seq[5]).Value;
+            exponent1 = ((DerInteger)seq[6]).Value;
+            exponent2 = ((DerInteger)seq[7]).Value;
+            coefficient = ((DerInteger)seq[8]).Value;
         }
 
         public BigInteger Modulus
diff --git a/crypto/src/bcpg/BcpgOutputStream.cs b/crypto/src/bcpg/BcpgOutputStream.cs
index 7ab661edb..738c28211 100644
--- a/crypto/src/bcpg/BcpgOutputStream.cs
+++ b/crypto/src/bcpg/BcpgOutputStream.cs
@@ -376,6 +376,7 @@ namespace Org.BouncyCastle.Bcpg
             if (partialBuffer != null)
             {
                 PartialFlush(true);
+                Array.Clear(partialBuffer, 0, partialBuffer.Length);
                 partialBuffer = null;
             }
         }
diff --git a/crypto/src/bcpg/LiteralDataPacket.cs b/crypto/src/bcpg/LiteralDataPacket.cs
index 63a2c6d44..b4d28a201 100644
--- a/crypto/src/bcpg/LiteralDataPacket.cs
+++ b/crypto/src/bcpg/LiteralDataPacket.cs
@@ -23,7 +23,11 @@ namespace Org.BouncyCastle.Bcpg
 			fileName = new byte[len];
 			for (int i = 0; i != len; ++i)
             {
-                fileName[i] = (byte)bcpgIn.ReadByte();
+                int ch = bcpgIn.ReadByte();
+                if (ch < 0)
+                    throw new IOException("literal data truncated in header");
+
+                fileName[i] = (byte)ch;
             }
 
 			modDate = (((uint)bcpgIn.ReadByte() << 24)
diff --git a/crypto/src/cms/CMSAuthenticatedDataGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataGenerator.cs
index 131a4753f..addd14c7d 100644
--- a/crypto/src/cms/CMSAuthenticatedDataGenerator.cs
+++ b/crypto/src/cms/CMSAuthenticatedDataGenerator.cs
@@ -80,7 +80,7 @@ namespace Org.BouncyCastle.Cms
 				mac.Init(encKey);
 
 				MemoryStream bOut = new MemoryStream();
-				Stream mOut = new TeeOutputStream(bOut, new MacOutputStream(mac));
+				Stream mOut = new TeeOutputStream(bOut, new MacSink(mac));
 
 				content.Write(mOut);
 
diff --git a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
index 4d18d10d4..9d9e2450c 100644
--- a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
@@ -168,7 +168,7 @@ namespace Org.BouncyCastle.Cms
                 IMac mac = MacUtilities.GetMac(macAlgId.Algorithm);
 				// TODO Confirm no ParametersWithRandom needed
 	            mac.Init(cipherParameters);
-				Stream mOut = new TeeOutputStream(octetOutputStream, new MacOutputStream(mac));
+				Stream mOut = new TeeOutputStream(octetOutputStream, new MacSink(mac));
 
 				return new CmsAuthenticatedDataOutputStream(mOut, mac, cGen, authGen, eiGen);
 			}
diff --git a/crypto/src/cms/CMSEnvelopedHelper.cs b/crypto/src/cms/CMSEnvelopedHelper.cs
index 77d2da47a..930ffcbf1 100644
--- a/crypto/src/cms/CMSEnvelopedHelper.cs
+++ b/crypto/src/cms/CMSEnvelopedHelper.cs
@@ -223,7 +223,7 @@ namespace Org.BouncyCastle.Cms
 					return new CmsProcessableInputStream(
 						new TeeInputStream(
 							readable.GetInputStream(),
-							new MacOutputStream(this.mac)));
+							new MacSink(this.mac)));
 				}
 				catch (IOException e)
 				{
diff --git a/crypto/src/cms/CMSSignedDataGenerator.cs b/crypto/src/cms/CMSSignedDataGenerator.cs
index 5aa5f92ab..f2676a440 100644
--- a/crypto/src/cms/CMSSignedDataGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataGenerator.cs
@@ -6,6 +6,7 @@ using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Cms;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Security.Certificates;
 using Org.BouncyCastle.Utilities;
@@ -128,7 +129,7 @@ namespace Org.BouncyCastle.Cms
                     IDigest dig = Helper.GetDigestInstance(digestName);
                     if (content != null)
                     {
-                        content.Write(new DigOutputStream(dig));
+                        content.Write(new DigestSink(dig));
                     }
                     hash = DigestUtilities.DoFinal(dig);
                     outer._digests.Add(digestOID, hash.Clone());
diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
index 1c8fac22b..29411e132 100644
--- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
@@ -746,7 +746,7 @@ namespace Org.BouncyCastle.Cms
 			Stream result = s;
 			foreach (IDigest digest in digests)
 			{
-				result = GetSafeTeeOutputStream(result, new DigOutputStream(digest));
+				result = GetSafeTeeOutputStream(result, new DigestSink(digest));
 			}
 			return result;
 		}
diff --git a/crypto/src/cms/DigOutputStream.cs b/crypto/src/cms/DigOutputStream.cs
deleted file mode 100644
index 103b45cac..000000000
--- a/crypto/src/cms/DigOutputStream.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Utilities.IO;
-
-namespace Org.BouncyCastle.Cms
-{
-	internal class DigOutputStream
-		: BaseOutputStream
-	{
-		private readonly IDigest dig;
-
-		internal DigOutputStream(IDigest dig)
-		{
-			this.dig = dig;
-		}
-
-		public override void WriteByte(byte b)
-		{
-			dig.Update(b);
-		}
-
-		public override void Write(byte[] b, int off, int len)
-		{
-			dig.BlockUpdate(b, off, len);
-		}
-	}
-}
diff --git a/crypto/src/cms/MacOutputStream.cs b/crypto/src/cms/MacOutputStream.cs
deleted file mode 100644
index 8891dbc2c..000000000
--- a/crypto/src/cms/MacOutputStream.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Utilities.IO;
-
-namespace Org.BouncyCastle.Cms
-{
-	internal class MacOutputStream
-		: BaseOutputStream
-	{
-		private readonly IMac mac;
-
-		internal MacOutputStream(IMac mac)
-		{
-			this.mac = mac;
-		}
-
-		public override void Write(byte[] b, int off, int len)
-		{
-			mac.BlockUpdate(b, off, len);
-		}
-
-		public override void WriteByte(byte b)
-		{
-			mac.Update(b);
-		}
-	}
-}
diff --git a/crypto/src/cms/SigOutputStream.cs b/crypto/src/cms/SigOutputStream.cs
deleted file mode 100644
index a807fa7fc..000000000
--- a/crypto/src/cms/SigOutputStream.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using System;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Utilities.IO;
-using Org.BouncyCastle.Security;
-
-namespace Org.BouncyCastle.Cms
-{
-	internal class SigOutputStream
-		: BaseOutputStream
-	{
-		private readonly ISigner sig;
-
-		internal SigOutputStream(ISigner sig)
-		{
-			this.sig = sig;
-		}
-
-		public override void WriteByte(byte b)
-		{
-			try
-			{
-				sig.Update(b);
-			}
-			catch (SignatureException e)
-			{
-				throw new CmsStreamException("signature problem: " + e);
-			}
-		}
-
-		public override void Write(byte[] b, int off, int len)
-		{
-			try
-			{
-				sig.BlockUpdate(b, off, len);
-			}
-			catch (SignatureException e)
-			{
-				throw new CmsStreamException("signature problem: " + e);
-			}
-		}
-	}
-}
\ No newline at end of file
diff --git a/crypto/src/cms/SignerInfoGenerator.cs b/crypto/src/cms/SignerInfoGenerator.cs
index 7b9318cc9..df8d1d0a1 100644
--- a/crypto/src/cms/SignerInfoGenerator.cs
+++ b/crypto/src/cms/SignerInfoGenerator.cs
@@ -110,10 +110,10 @@ namespace Org.BouncyCastle.Cms
         }
 
         /**
-         * Build a generator with the passed in certHolder issuer and serial number as the signerIdentifier.
+         * Build a generator with the passed in X.509 certificate issuer and serial number as the signerIdentifier.
          *
          * @param contentSigner  operator for generating the final signature in the SignerInfo with.
-         * @param certHolder  carrier for the X.509 certificate related to the contentSigner.
+         * @param certificate  X.509 certificate related to the contentSigner.
          * @return  a SignerInfoGenerator
          * @throws OperatorCreationException   if the generator cannot be built.
          */
diff --git a/crypto/src/cms/SignerInformation.cs b/crypto/src/cms/SignerInformation.cs
index 39ecfa6d3..c262806a8 100644
--- a/crypto/src/cms/SignerInformation.cs
+++ b/crypto/src/cms/SignerInformation.cs
@@ -8,6 +8,7 @@ using Org.BouncyCastle.Asn1.Cms;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.IO;
 using Org.BouncyCastle.Crypto.Signers;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Utilities;
@@ -387,7 +388,7 @@ namespace Org.BouncyCastle.Cms
 				{
 					if (content != null)
 					{
-						content.Write(new DigOutputStream(digest));
+						content.Write(new DigestSink(digest));
 					}
 					else if (signedAttributeSet == null)
 					{
@@ -485,8 +486,15 @@ namespace Org.BouncyCastle.Cms
 					}
 					else if (content != null)
 					{
-						// TODO Use raw signature of the hash value instead
-						content.Write(new SigOutputStream(sig));
+                        try
+                        {
+                            // TODO Use raw signature of the hash value instead
+                            content.Write(new SignerSink(sig));
+                        }
+                        catch (SignatureException e)
+                        {
+                            throw new CmsStreamException("signature problem: " + e);
+                        }
 					}
 				}
 				else
diff --git a/crypto/src/crypto/IRsa.cs b/crypto/src/crypto/IRsa.cs
new file mode 100644
index 000000000..f7bcc9e5a
--- /dev/null
+++ b/crypto/src/crypto/IRsa.cs
@@ -0,0 +1,16 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto
+{
+    public interface IRsa
+    {
+        void Init(bool forEncryption, ICipherParameters parameters);
+        int GetInputBlockSize();
+        int GetOutputBlockSize();
+        BigInteger ConvertInput(byte[] buf, int off, int len);
+        BigInteger ProcessBlock(BigInteger input);
+        byte[] ConvertOutput(BigInteger result);
+    }
+}
diff --git a/crypto/src/crypto/engines/RSABlindedEngine.cs b/crypto/src/crypto/engines/RSABlindedEngine.cs
index f95f145f6..7b928c5fb 100644
--- a/crypto/src/crypto/engines/RSABlindedEngine.cs
+++ b/crypto/src/crypto/engines/RSABlindedEngine.cs
@@ -13,10 +13,21 @@ namespace Org.BouncyCastle.Crypto.Engines
     public class RsaBlindedEngine
         : IAsymmetricBlockCipher
     {
-        private readonly RsaCoreEngine core = new RsaCoreEngine();
+        private readonly IRsa core;
+
         private RsaKeyParameters key;
         private SecureRandom random;
 
+        public RsaBlindedEngine()
+            : this(new RsaCoreEngine())
+        {
+        }
+
+        public RsaBlindedEngine(IRsa rsa)
+        {
+            this.core = rsa;
+        }
+
         public virtual string AlgorithmName
         {
             get { return "RSA"; }
diff --git a/crypto/src/crypto/engines/RSABlindingEngine.cs b/crypto/src/crypto/engines/RSABlindingEngine.cs
index c636627bf..1289456a6 100644
--- a/crypto/src/crypto/engines/RSABlindingEngine.cs
+++ b/crypto/src/crypto/engines/RSABlindingEngine.cs
@@ -14,13 +14,23 @@ namespace Org.BouncyCastle.Crypto.Engines
 	public class RsaBlindingEngine
 		: IAsymmetricBlockCipher
 	{
-		private readonly RsaCoreEngine core = new RsaCoreEngine();
+		private readonly IRsa core;
 
 		private RsaKeyParameters key;
 		private BigInteger blindingFactor;
 
 		private bool forEncryption;
 
+        public RsaBlindingEngine()
+            : this(new RsaCoreEngine())
+        {
+        }
+
+        public RsaBlindingEngine(IRsa rsa)
+        {
+            this.core = rsa;
+        }
+
         public virtual string AlgorithmName
 		{
 			get { return "RSA"; }
diff --git a/crypto/src/crypto/engines/RSACoreEngine.cs b/crypto/src/crypto/engines/RSACoreEngine.cs
index fd44e3cc1..5f6e98eea 100644
--- a/crypto/src/crypto/engines/RSACoreEngine.cs
+++ b/crypto/src/crypto/engines/RSACoreEngine.cs
@@ -9,13 +9,20 @@ namespace Org.BouncyCastle.Crypto.Engines
 	/**
 	* this does your basic RSA algorithm.
 	*/
-	class RsaCoreEngine
+	public class RsaCoreEngine
+        : IRsa
 	{
 		private RsaKeyParameters	key;
 		private bool				forEncryption;
 		private int					bitSize;
 
-		/**
+        private void CheckInitialised()
+        {
+            if (key == null)
+                throw new InvalidOperationException("RSA engine not initialised");
+        }
+
+        /**
 		* initialise the RSA engine.
 		*
 		* @param forEncryption true if we are encrypting, false otherwise.
@@ -47,6 +54,8 @@ namespace Org.BouncyCastle.Crypto.Engines
 		*/
         public virtual int GetInputBlockSize()
 		{
+            CheckInitialised();
+
 			if (forEncryption)
 			{
 				return (bitSize - 1) / 8;
@@ -64,7 +73,9 @@ namespace Org.BouncyCastle.Crypto.Engines
 		*/
         public virtual int GetOutputBlockSize()
 		{
-			if (forEncryption)
+            CheckInitialised();
+
+            if (forEncryption)
 			{
 				return (bitSize + 7) / 8;
 			}
@@ -77,7 +88,9 @@ namespace Org.BouncyCastle.Crypto.Engines
 			int		inOff,
 			int		inLen)
 		{
-			int maxLength = (bitSize + 7) / 8;
+            CheckInitialised();
+
+            int maxLength = (bitSize + 7) / 8;
 
 			if (inLen > maxLength)
 				throw new DataLengthException("input too large for RSA cipher.");
@@ -93,7 +106,9 @@ namespace Org.BouncyCastle.Crypto.Engines
         public virtual byte[] ConvertOutput(
 			BigInteger result)
 		{
-			byte[] output = result.ToByteArrayUnsigned();
+            CheckInitialised();
+
+            byte[] output = result.ToByteArrayUnsigned();
 
 			if (forEncryption)
 			{
@@ -115,7 +130,9 @@ namespace Org.BouncyCastle.Crypto.Engines
         public virtual BigInteger ProcessBlock(
 			BigInteger input)
 		{
-			if (key is RsaPrivateCrtKeyParameters)
+            CheckInitialised();
+
+            if (key is RsaPrivateCrtKeyParameters)
 			{
 				//
 				// we have the extra factors, use the Chinese Remainder Theorem - the author
diff --git a/crypto/src/crypto/engines/RsaEngine.cs b/crypto/src/crypto/engines/RsaEngine.cs
index 4399b4409..95bfb2371 100644
--- a/crypto/src/crypto/engines/RsaEngine.cs
+++ b/crypto/src/crypto/engines/RsaEngine.cs
@@ -1,5 +1,7 @@
 using System;
 
+using Org.BouncyCastle.Math;
+
 namespace Org.BouncyCastle.Crypto.Engines
 {
     /**
@@ -8,7 +10,17 @@ namespace Org.BouncyCastle.Crypto.Engines
     public class RsaEngine
 		: IAsymmetricBlockCipher
     {
-		private RsaCoreEngine core;
+		private readonly IRsa core;
+
+        public RsaEngine()
+            : this(new RsaCoreEngine())
+        {
+        }
+
+        public RsaEngine(IRsa rsa)
+        {
+            this.core = rsa;
+        }
 
         public virtual string AlgorithmName
         {
@@ -25,9 +37,6 @@ namespace Org.BouncyCastle.Crypto.Engines
             bool				forEncryption,
             ICipherParameters	parameters)
         {
-			if (core == null)
-				core = new RsaCoreEngine();
-
 			core.Init(forEncryption, parameters);
 		}
 
@@ -69,10 +78,9 @@ namespace Org.BouncyCastle.Crypto.Engines
             int		inOff,
             int		inLen)
         {
-			if (core == null)
-				throw new InvalidOperationException("RSA engine not initialised");
-
-			return core.ConvertOutput(core.ProcessBlock(core.ConvertInput(inBuf, inOff, inLen)));
+            BigInteger input = core.ConvertInput(inBuf, inOff, inLen);
+            BigInteger output = core.ProcessBlock(input);
+			return core.ConvertOutput(output);
         }
     }
 }
diff --git a/crypto/src/crypto/generators/OpenBsdBCrypt.cs b/crypto/src/crypto/generators/OpenBsdBCrypt.cs
index 49f79f95b..da6e2b952 100644
--- a/crypto/src/crypto/generators/OpenBsdBCrypt.cs
+++ b/crypto/src/crypto/generators/OpenBsdBCrypt.cs
@@ -174,7 +174,11 @@ namespace Org.BouncyCastle.Crypto.Generators
             }
             catch (Exception nfe)
             {
+#if PORTABLE
+                throw new ArgumentException("Invalid cost factor: " + bcryptString.Substring(4, 2), "bcryptString");
+#else
                 throw new ArgumentException("Invalid cost factor: " + bcryptString.Substring(4, 2), "bcryptString", nfe);
+#endif
             }
             if (cost < 4 || cost > 31)
                 throw new ArgumentException("Invalid cost factor: " + cost + ", 4 < cost < 31 expected.");
diff --git a/crypto/src/crypto/io/DigestSink.cs b/crypto/src/crypto/io/DigestSink.cs
new file mode 100644
index 000000000..98307e5f7
--- /dev/null
+++ b/crypto/src/crypto/io/DigestSink.cs
@@ -0,0 +1,35 @@
+using System;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.IO
+{
+    public class DigestSink
+        : BaseOutputStream
+    {
+        private readonly IDigest mDigest;
+
+        public DigestSink(IDigest digest)
+        {
+            this.mDigest = digest;
+        }
+
+        public virtual IDigest Digest
+        {
+            get { return mDigest; }
+        }
+
+        public override void WriteByte(byte b)
+        {
+            mDigest.Update(b);
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            if (len > 0)
+            {
+                mDigest.BlockUpdate(buf, off, len);
+            }
+        }
+    }
+}
diff --git a/crypto/src/crypto/io/MacSink.cs b/crypto/src/crypto/io/MacSink.cs
new file mode 100644
index 000000000..c4fe7169a
--- /dev/null
+++ b/crypto/src/crypto/io/MacSink.cs
@@ -0,0 +1,35 @@
+using System;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.IO
+{
+    public class MacSink
+        : BaseOutputStream
+    {
+        private readonly IMac mMac;
+
+        public MacSink(IMac mac)
+        {
+            this.mMac = mac;
+        }
+
+        public virtual IMac Mac
+        {
+            get { return mMac; }
+        }
+
+        public override void WriteByte(byte b)
+        {
+            mMac.Update(b);
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            if (len > 0)
+            {
+                mMac.BlockUpdate(buf, off, len);
+            }
+        }
+    }
+}
diff --git a/crypto/src/crypto/io/SignerSink.cs b/crypto/src/crypto/io/SignerSink.cs
new file mode 100644
index 000000000..c9bd8b9c8
--- /dev/null
+++ b/crypto/src/crypto/io/SignerSink.cs
@@ -0,0 +1,35 @@
+using System;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.IO
+{
+    public class SignerSink
+		: BaseOutputStream
+	{
+		private readonly ISigner mSigner;
+
+        public SignerSink(ISigner signer)
+		{
+            this.mSigner = signer;
+		}
+
+        public virtual ISigner Signer
+        {
+            get { return mSigner; }
+        }
+
+		public override void WriteByte(byte b)
+		{
+            mSigner.Update(b);
+		}
+
+		public override void Write(byte[] buf, int off, int len)
+		{
+			if (len > 0)
+			{
+				mSigner.BlockUpdate(buf, off, len);
+			}
+		}
+	}
+}
diff --git a/crypto/src/crypto/operators/Asn1Signature.cs b/crypto/src/crypto/operators/Asn1Signature.cs
index 373ba0cee..3fa193273 100644
--- a/crypto/src/crypto/operators/Asn1Signature.cs
+++ b/crypto/src/crypto/operators/Asn1Signature.cs
@@ -236,91 +236,6 @@ namespace Org.BouncyCastle.Crypto.Operators
 		}
 	}
 
-	internal class SignerBucket
-		: Stream
-	{
-		protected readonly ISigner signer;
-
-		public SignerBucket(
-			ISigner	signer)
-		{
-			this.signer = signer;
-		}
-
-		public override int Read(
-			byte[]	buffer,
-			int		offset,
-			int		count)
-		{
-			throw new NotImplementedException ();
-		}
-
-		public override int ReadByte()
-		{
-			throw new NotImplementedException ();
-		}
-
-		public override void Write(
-			byte[]	buffer,
-			int		offset,
-			int		count)
-		{
-			if (count > 0)
-			{
-				signer.BlockUpdate(buffer, offset, count);
-			}
-		}
-
-		public override void WriteByte(
-			byte b)
-		{
-			signer.Update(b);
-		}
-
-		public override bool CanRead
-		{
-			get { return false; }
-		}
-
-		public override bool CanWrite
-		{
-			get { return true; }
-		}
-
-		public override bool CanSeek
-		{
-			get { return false; }
-		}
-
-		public override long Length
-		{
-			get { return 0; }
-		}
-
-		public override long Position
-		{
-			get { throw new NotImplementedException (); }
-			set { throw new NotImplementedException (); }
-		}
-
-        public override void Flush()
-		{
-		}
-
-		public override long Seek(
-			long		offset,
-			SeekOrigin	origin)
-		{
-			throw new NotImplementedException ();
-		}
-
-		public override void SetLength(
-			long length)
-		{
-			throw new NotImplementedException ();
-		}
-	}
-
     /// <summary>
     /// Calculator factory class for signature generation in ASN.1 based profiles that use an AlgorithmIdentifier to preserve
     /// signature algorithm details.
@@ -373,14 +288,9 @@ namespace Org.BouncyCastle.Crypto.Operators
 
         public IStreamCalculator CreateCalculator()
         {
-            ISigner sig = SignerUtilities.GetSigner(algorithm);
-            ICipherParameters cp = privateKey;
-            if (random != null)
-            {
-                cp = new ParametersWithRandom(cp, random);
-            }
-            sig.Init(true, cp);
-            return new SigCalculator(sig);
+            ISigner signer = SignerUtilities.InitSigner(algorithm, true, privateKey, random);
+
+            return new DefaultSignatureCalculator(signer);
         }
 
         /// <summary>
@@ -392,52 +302,6 @@ namespace Org.BouncyCastle.Crypto.Operators
         }
     }
 
-    internal class SigCalculator : IStreamCalculator
-    {
-        private readonly ISigner sig;
-        private readonly Stream stream;
-
-        internal SigCalculator(ISigner sig)
-        {
-            this.sig = sig;
-            this.stream = new SignerBucket(sig);
-        }
-
-        public Stream Stream
-        {
-            get { return stream; }
-        }
-
-        public object GetResult()
-        {
-            return new SigResult(sig);
-        }
-    }
-
-    internal class SigResult : IBlockResult
-    {
-        private readonly ISigner sig;
-
-        internal SigResult(ISigner sig)
-        {
-            this.sig = sig;
-        }
-
-        public byte[] Collect()
-        {
-            return sig.GenerateSignature();
-        }
-
-        public int Collect(byte[] destination, int offset)
-        {
-            byte[] signature = Collect();
-
-            Array.Copy(signature, 0, destination, offset, signature.Length);
-
-            return signature.Length;
-        }
-    }
-
     /// <summary>
     /// Verifier class for signature verification in ASN.1 based profiles that use an AlgorithmIdentifier to preserve
     /// signature algorithm details.
@@ -481,57 +345,9 @@ namespace Org.BouncyCastle.Crypto.Operators
 
         public IStreamCalculator CreateCalculator()
         {
-            ISigner sig = SignerUtilities.GetSigner(X509Utilities.GetSignatureName(algID));
-
-            sig.Init(false, publicKey);
-          
-            return new VerifierCalculator(sig);
-        }
-    }
-
-    internal class VerifierCalculator : IStreamCalculator
-    {
-        private readonly ISigner sig;
-        private readonly Stream stream;
-
-        internal VerifierCalculator(ISigner sig)
-        {
-            this.sig = sig;
-            this.stream = new SignerBucket(sig);
-        }
-
-        public Stream Stream
-        {
-            get { return stream; }
-        }
-
-        public object GetResult()
-        {
-            return new VerifierResult(sig);
-        }
-    }
-
-    internal class VerifierResult : IVerifier
-    {
-        private readonly ISigner sig;
-
-        internal VerifierResult(ISigner sig)
-        {
-            this.sig = sig;
-        }
-
-        public bool IsVerified(byte[] signature)
-        {
-            return sig.VerifySignature(signature);
-        }
-
-        public bool IsVerified(byte[] signature, int off, int length)
-        {
-            byte[] sigBytes = new byte[length];
-
-            Array.Copy(signature, 0, sigBytes, off, sigBytes.Length);
+            ISigner verifier = SignerUtilities.InitSigner(X509Utilities.GetSignatureName(algID), false, publicKey, null);
 
-            return sig.VerifySignature(signature);
+            return new DefaultVerifierCalculator(verifier);
         }
     }
 
diff --git a/crypto/src/crypto/operators/DefaultSignatureCalculator.cs b/crypto/src/crypto/operators/DefaultSignatureCalculator.cs
new file mode 100644
index 000000000..8ca1c01d9
--- /dev/null
+++ b/crypto/src/crypto/operators/DefaultSignatureCalculator.cs
@@ -0,0 +1,28 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.IO;
+
+namespace Org.BouncyCastle.Crypto.Operators
+{
+    public class DefaultSignatureCalculator
+        : IStreamCalculator
+    {
+        private readonly SignerSink mSignerSink;
+
+        public DefaultSignatureCalculator(ISigner signer)
+        {
+            this.mSignerSink = new SignerSink(signer);
+        }
+
+        public Stream Stream
+        {
+            get { return mSignerSink; }
+        }
+
+        public object GetResult()
+        {
+            return new DefaultSignatureResult(mSignerSink.Signer);
+        }
+    }
+}
diff --git a/crypto/src/crypto/operators/DefaultSignatureResult.cs b/crypto/src/crypto/operators/DefaultSignatureResult.cs
new file mode 100644
index 000000000..615f67dcb
--- /dev/null
+++ b/crypto/src/crypto/operators/DefaultSignatureResult.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Operators
+{
+    public class DefaultSignatureResult
+        : IBlockResult
+    {
+        private readonly ISigner mSigner;
+
+        public DefaultSignatureResult(ISigner signer)
+        {
+            this.mSigner = signer;
+        }
+
+        public byte[] Collect()
+        {
+            return mSigner.GenerateSignature();
+        }
+
+        public int Collect(byte[] sig, int sigOff)
+        {
+            byte[] signature = Collect();
+            signature.CopyTo(sig, sigOff);
+            return signature.Length;
+        }
+    }
+}
diff --git a/crypto/src/crypto/operators/DefaultVerifierCalculator.cs b/crypto/src/crypto/operators/DefaultVerifierCalculator.cs
new file mode 100644
index 000000000..c985e81a5
--- /dev/null
+++ b/crypto/src/crypto/operators/DefaultVerifierCalculator.cs
@@ -0,0 +1,28 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.IO;
+
+namespace Org.BouncyCastle.Crypto.Operators
+{
+    public class DefaultVerifierCalculator
+        : IStreamCalculator
+    {
+        private readonly SignerSink mSignerSink;
+
+        public DefaultVerifierCalculator(ISigner signer)
+        {
+            this.mSignerSink = new SignerSink(signer);
+        }
+
+        public Stream Stream
+        {
+            get { return mSignerSink; }
+        }
+
+        public object GetResult()
+        {
+            return new DefaultVerifierResult(mSignerSink.Signer);
+        }
+    }
+}
diff --git a/crypto/src/crypto/operators/DefaultVerifierResult.cs b/crypto/src/crypto/operators/DefaultVerifierResult.cs
new file mode 100644
index 000000000..fb259c8f8
--- /dev/null
+++ b/crypto/src/crypto/operators/DefaultVerifierResult.cs
@@ -0,0 +1,29 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Operators
+{
+    public class DefaultVerifierResult
+        : IVerifier
+    {
+        private readonly ISigner mSigner;
+
+        public DefaultVerifierResult(ISigner signer)
+        {
+            this.mSigner = signer;
+        }
+
+        public bool IsVerified(byte[] signature)
+        {
+            return mSigner.VerifySignature(signature);
+        }
+
+        public bool IsVerified(byte[] sig, int sigOff, int sigLen)
+        {
+            byte[] signature = Arrays.CopyOfRange(sig, sigOff, sigOff + sigLen);
+
+            return IsVerified(signature);
+        }
+    }
+}
diff --git a/crypto/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs b/crypto/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs
index 7bd8abd76..557ee94e2 100644
--- a/crypto/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs
+++ b/crypto/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs
@@ -2,33 +2,34 @@ using System;
 
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Asn1.Pkcs;
 
 namespace Org.BouncyCastle.Crypto.Parameters
 {
     public class RsaPrivateCrtKeyParameters
-		: RsaKeyParameters
+        : RsaKeyParameters
     {
         private readonly BigInteger e, p, q, dP, dQ, qInv;
 
-		public RsaPrivateCrtKeyParameters(
-            BigInteger	modulus,
-            BigInteger	publicExponent,
-            BigInteger	privateExponent,
-            BigInteger	p,
-            BigInteger	q,
-            BigInteger	dP,
-            BigInteger	dQ,
-            BigInteger	qInv)
-			: base(true, modulus, privateExponent)
+        public RsaPrivateCrtKeyParameters(
+            BigInteger modulus,
+            BigInteger publicExponent,
+            BigInteger privateExponent,
+            BigInteger p,
+            BigInteger q,
+            BigInteger dP,
+            BigInteger dQ,
+            BigInteger qInv)
+            : base(true, modulus, privateExponent)
         {
-			ValidateValue(publicExponent, "publicExponent", "exponent");
-			ValidateValue(p, "p", "P value");
-			ValidateValue(q, "q", "Q value");
-			ValidateValue(dP, "dP", "DP value");
-			ValidateValue(dQ, "dQ", "DQ value");
-			ValidateValue(qInv, "qInv", "InverseQ value");
-
-			this.e = publicExponent;
+            ValidateValue(publicExponent, "publicExponent", "exponent");
+            ValidateValue(p, "p", "P value");
+            ValidateValue(q, "q", "Q value");
+            ValidateValue(dP, "dP", "DP value");
+            ValidateValue(dQ, "dQ", "DQ value");
+            ValidateValue(qInv, "qInv", "InverseQ value");
+
+            this.e = publicExponent;
             this.p = p;
             this.q = q;
             this.dP = dP;
@@ -36,69 +37,82 @@ namespace Org.BouncyCastle.Crypto.Parameters
             this.qInv = qInv;
         }
 
-		public BigInteger PublicExponent
+        public RsaPrivateCrtKeyParameters(RsaPrivateKeyStructure rsaPrivateKey)
+            : this(
+                rsaPrivateKey.Modulus,
+                rsaPrivateKey.PublicExponent,
+                rsaPrivateKey.PrivateExponent,
+                rsaPrivateKey.Prime1,
+                rsaPrivateKey.Prime2,
+                rsaPrivateKey.Exponent1,
+                rsaPrivateKey.Exponent2,
+                rsaPrivateKey.Coefficient)
+        {
+        }
+
+        public BigInteger PublicExponent
         {
             get { return e; }
-		}
-
-		public BigInteger P
-		{
-			get { return p; }
-		}
-
-		public BigInteger Q
-		{
-			get { return q; }
-		}
-
-		public BigInteger DP
-		{
-			get { return dP; }
-		}
-
-		public BigInteger DQ
-		{
-			get { return dQ; }
-		}
-
-		public BigInteger QInv
-		{
-			get { return qInv; }
-		}
-
-		public override bool Equals(
-			object obj)
-		{
-			if (obj == this)
-				return true;
-
-			RsaPrivateCrtKeyParameters kp = obj as RsaPrivateCrtKeyParameters;
-
-			if (kp == null)
-				return false;
-
-			return kp.DP.Equals(dP)
-				&& kp.DQ.Equals(dQ)
-				&& kp.Exponent.Equals(this.Exponent)
-				&& kp.Modulus.Equals(this.Modulus)
-				&& kp.P.Equals(p)
-				&& kp.Q.Equals(q)
-				&& kp.PublicExponent.Equals(e)
-				&& kp.QInv.Equals(qInv);
-		}
-
-		public override int GetHashCode()
-		{
-			return DP.GetHashCode() ^ DQ.GetHashCode() ^ Exponent.GetHashCode() ^ Modulus.GetHashCode()
-				^ P.GetHashCode() ^ Q.GetHashCode() ^ PublicExponent.GetHashCode() ^ QInv.GetHashCode();
-		}
-
-		private static void ValidateValue(BigInteger x, string name, string desc)
-		{
-			if (x == null)
-				throw new ArgumentNullException(name);
-			if (x.SignValue <= 0)
-				throw new ArgumentException("Not a valid RSA " + desc, name);
-		}
-	}
+        }
+
+        public BigInteger P
+        {
+            get { return p; }
+        }
+
+        public BigInteger Q
+        {
+            get { return q; }
+        }
+
+        public BigInteger DP
+        {
+            get { return dP; }
+        }
+
+        public BigInteger DQ
+        {
+            get { return dQ; }
+        }
+
+        public BigInteger QInv
+        {
+            get { return qInv; }
+        }
+
+        public override bool Equals(
+            object obj)
+        {
+            if (obj == this)
+                return true;
+
+            RsaPrivateCrtKeyParameters kp = obj as RsaPrivateCrtKeyParameters;
+
+            if (kp == null)
+                return false;
+
+            return kp.DP.Equals(dP)
+                && kp.DQ.Equals(dQ)
+                && kp.Exponent.Equals(this.Exponent)
+                && kp.Modulus.Equals(this.Modulus)
+                && kp.P.Equals(p)
+                && kp.Q.Equals(q)
+                && kp.PublicExponent.Equals(e)
+                && kp.QInv.Equals(qInv);
+        }
+
+        public override int GetHashCode()
+        {
+            return DP.GetHashCode() ^ DQ.GetHashCode() ^ Exponent.GetHashCode() ^ Modulus.GetHashCode()
+                ^ P.GetHashCode() ^ Q.GetHashCode() ^ PublicExponent.GetHashCode() ^ QInv.GetHashCode();
+        }
+
+        private static void ValidateValue(BigInteger x, string name, string desc)
+        {
+            if (x == null)
+                throw new ArgumentNullException(name);
+            if (x.SignValue <= 0)
+                throw new ArgumentException("Not a valid RSA " + desc, name);
+        }
+    }
 }
diff --git a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
index c25ab9364..fb49a02b3 100644
--- a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs
@@ -56,7 +56,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
         {
             byte[] encoded = new byte[X25519.PointSize];
             publicKey.Encode(encoded, 0);
-            X25519.ScalarMult(data, 0, encoded, 0, buf, off);
+            if (!X25519.CalculateAgreement(data, 0, encoded, 0, buf, off))
+                throw new InvalidOperationException("X25519 agreement failed");
         }
     }
 }
diff --git a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
index 291eac10f..d17aa7947 100644
--- a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs
@@ -56,7 +56,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
         {
             byte[] encoded = new byte[X448.PointSize];
             publicKey.Encode(encoded, 0);
-            X448.ScalarMult(data, 0, encoded, 0, buf, off);
+            if (!X448.CalculateAgreement(data, 0, encoded, 0, buf, off))
+                throw new InvalidOperationException("X448 agreement failed");
         }
     }
 }
diff --git a/crypto/src/crypto/prng/ThreadedSeedGenerator.cs b/crypto/src/crypto/prng/ThreadedSeedGenerator.cs
index 499aab267..f12b832ee 100644
--- a/crypto/src/crypto/prng/ThreadedSeedGenerator.cs
+++ b/crypto/src/crypto/prng/ThreadedSeedGenerator.cs
@@ -5,18 +5,20 @@ using System.Threading;
 using System.Threading.Tasks;
 #endif
 
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Crypto.Prng
 {
-	/**
-	 * A thread based seed generator - one source of randomness.
-	 * <p>
-	 * Based on an idea from Marcus Lippert.
-	 * </p>
-	 */
-	public class ThreadedSeedGenerator
-	{
-		private class SeedGenerator
-		{
+    /**
+     * A thread based seed generator - one source of randomness.
+     * <p>
+     * Based on an idea from Marcus Lippert.
+     * </p>
+     */
+    public class ThreadedSeedGenerator
+    {
+        private class SeedGenerator
+        {
 #if NETCF_1_0
 			// No volatile keyword, but all fields implicitly volatile anyway
 			private int		counter = 0;
@@ -26,18 +28,18 @@ namespace Org.BouncyCastle.Crypto.Prng
             private volatile bool stop = false;
 #endif
 
-			private void Run(object ignored)
-			{
-				while (!this.stop)
-				{
-					this.counter++;
-				}
-			}
+            private void Run(object ignored)
+            {
+                while (!this.stop)
+                {
+                    this.counter++;
+                }
+            }
 
-			public byte[] GenerateSeed(
+            public byte[] GenerateSeed(
                 int numBytes,
                 bool fast)
-			{
+            {
 #if SILVERLIGHT || PORTABLE
                 return DoGenerateSeed(numBytes, fast);
 #else
@@ -59,71 +61,84 @@ namespace Org.BouncyCastle.Crypto.Prng
                 bool fast)
             {
                 this.counter = 0;
-				this.stop = false;
+                this.stop = false;
 
-				byte[] result = new byte[numBytes];
-				int last = 0;
-				int end = fast ? numBytes : numBytes * 8;
+                byte[] result = new byte[numBytes];
+                int last = 0;
+                int end = fast ? numBytes : numBytes * 8;
 
 #if NO_THREADS
                 Task.Factory.StartNew(() => Run(null), TaskCreationOptions.None);
 #else
-				ThreadPool.QueueUserWorkItem(new WaitCallback(Run));
+                ThreadPool.QueueUserWorkItem(new WaitCallback(Run));
+#endif
+
+#if PORTABLE
+                AutoResetEvent autoResetEvent = new AutoResetEvent(false);
 #endif
 
-				for (int i = 0; i < end; i++)
-				{
-					while (this.counter == last)
-					{
-						try
-						{
+                try
+                {
+                    for (int i = 0; i < end; i++)
+                    {
+                        while (this.counter == last)
+                        {
+                            try
+                            {
 #if PORTABLE
-                            new AutoResetEvent(false).WaitOne(1);
+                                autoResetEvent.WaitOne(1);
 #else
- 							Thread.Sleep(1);
+                                Thread.Sleep(1);
 #endif
-						}
-						catch (Exception)
-						{
-							// ignore
-						}
-					}
+                            }
+                            catch (Exception)
+                            {
+                                // ignore
+                            }
+                        }
 
-					last = this.counter;
+                        last = this.counter;
 
-					if (fast)
-					{
-                        result[i] = (byte)last;
-					}
-					else
-					{
-						int bytepos = i / 8;
-                        result[bytepos] = (byte)((result[bytepos] << 1) | (last & 1));
-					}
-				}
+                        if (fast)
+                        {
+                            result[i] = (byte)last;
+                        }
+                        else
+                        {
+                            int bytepos = i / 8;
+                            result[bytepos] = (byte)((result[bytepos] << 1) | (last & 1));
+                        }
+                    }
+                }
+                finally
+                {
+#if PORTABLE
+                    autoResetEvent.Dispose();
+#endif
+                }
 
-				this.stop = true;
+                this.stop = true;
 
-				return result;
-			}
-		}
+                return result;
+            }
+        }
 
-		/**
-		 * Generate seed bytes. Set fast to false for best quality.
-		 * <p>
-		 * If fast is set to true, the code should be round about 8 times faster when
-		 * generating a long sequence of random bytes. 20 bytes of random values using
-		 * the fast mode take less than half a second on a Nokia e70. If fast is set to false,
-		 * it takes round about 2500 ms.
-		 * </p>
-		 * @param numBytes the number of bytes to generate
-		 * @param fast true if fast mode should be used
-		 */
-		public byte[] GenerateSeed(
+        /**
+         * Generate seed bytes. Set fast to false for best quality.
+         * <p>
+         * If fast is set to true, the code should be round about 8 times faster when
+         * generating a long sequence of random bytes. 20 bytes of random values using
+         * the fast mode take less than half a second on a Nokia e70. If fast is set to false,
+         * it takes round about 2500 ms.
+         * </p>
+         * @param numBytes the number of bytes to generate
+         * @param fast true if fast mode should be used
+         */
+        public byte[] GenerateSeed(
             int numBytes,
             bool fast)
-		{
-			return new SeedGenerator().GenerateSeed(numBytes, fast);
-		}
-	}
+        {
+            return new SeedGenerator().GenerateSeed(numBytes, fast);
+        }
+    }
 }
diff --git a/crypto/src/crypto/signers/Ed25519Signer.cs b/crypto/src/crypto/signers/Ed25519Signer.cs
index 437247c26..ef8714188 100644
--- a/crypto/src/crypto/signers/Ed25519Signer.cs
+++ b/crypto/src/crypto/signers/Ed25519Signer.cs
@@ -1,6 +1,5 @@
 using System;
 using System.IO;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
@@ -80,14 +79,9 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         private class Buffer : MemoryStream
         {
-            private readonly object lockObject = new object();
-
-            // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do
-            // Not available in lower .net standard versions
-            //[MethodImpl(MethodImplOptions.Synchronized)]
             internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey)
             {
-                lock (lockObject)
+                lock (this)
                 {
 #if PORTABLE
                     byte[] buf = ToArray();
@@ -103,10 +97,9 @@ namespace Org.BouncyCastle.Crypto.Signers
                 }
             }
 
-            //[MethodImpl(MethodImplOptions.Synchronized)]
             internal bool VerifySignature(Ed25519PublicKeyParameters publicKey, byte[] signature)
             {
-                lock (lockObject)
+                lock (this)
                 {
 #if PORTABLE
                     byte[] buf = ToArray();
@@ -122,16 +115,16 @@ namespace Org.BouncyCastle.Crypto.Signers
                 }
             }
 
-            //[MethodImpl(MethodImplOptions.Synchronized)]
             internal void Reset()
             {
-                lock (lockObject)
+                lock (this)
                 {
+                    long count = Position;
 #if PORTABLE
                     this.Position = 0L;
                     Streams.WriteZeroes(this, count);
 #else
-                    Array.Clear(GetBuffer(), 0, (int)Position);
+                    Array.Clear(GetBuffer(), 0, (int)count);
 #endif
                     this.Position = 0L;
                 }
diff --git a/crypto/src/crypto/signers/Ed25519ctxSigner.cs b/crypto/src/crypto/signers/Ed25519ctxSigner.cs
index 495898349..60c708019 100644
--- a/crypto/src/crypto/signers/Ed25519ctxSigner.cs
+++ b/crypto/src/crypto/signers/Ed25519ctxSigner.cs
@@ -1,6 +1,5 @@
 using System;
 using System.IO;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
@@ -82,14 +81,9 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         private class Buffer : MemoryStream
         {
-            private readonly object lockObject = new object();
-
-            // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do
-            // Not available in lower .net standard versions
-            //[MethodImpl(MethodImplOptions.Synchronized)]
             internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey, byte[] ctx)
             {
-                lock (lockObject)
+                lock (this)
                 {
 #if PORTABLE
                     byte[] buf = ToArray();
@@ -105,10 +99,9 @@ namespace Org.BouncyCastle.Crypto.Signers
                 }
             }
 
-            //[MethodImpl(MethodImplOptions.Synchronized)]
             internal bool VerifySignature(Ed25519PublicKeyParameters publicKey, byte[] ctx, byte[] signature)
             {
-                lock (lockObject)
+                lock (this)
                 {
 #if PORTABLE
                     byte[] buf = ToArray();
@@ -124,16 +117,16 @@ namespace Org.BouncyCastle.Crypto.Signers
                 }
             }
 
-            //[MethodImpl(MethodImplOptions.Synchronized)]
             internal void Reset()
             {
-                lock (lockObject)
+                lock (this)
                 {
+                    long count = Position;
 #if PORTABLE
                     this.Position = 0L;
                     Streams.WriteZeroes(this, count);
 #else
-                    Array.Clear(GetBuffer(), 0, (int)Position);
+                    Array.Clear(GetBuffer(), 0, (int)count);
 #endif
                     this.Position = 0L;
                 }
diff --git a/crypto/src/crypto/signers/Ed25519phSigner.cs b/crypto/src/crypto/signers/Ed25519phSigner.cs
index 3318f6438..548ca1f29 100644
--- a/crypto/src/crypto/signers/Ed25519phSigner.cs
+++ b/crypto/src/crypto/signers/Ed25519phSigner.cs
@@ -1,6 +1,5 @@
 using System;
 using System.IO;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
diff --git a/crypto/src/crypto/signers/Ed448Signer.cs b/crypto/src/crypto/signers/Ed448Signer.cs
index 455400d22..0863e5dd1 100644
--- a/crypto/src/crypto/signers/Ed448Signer.cs
+++ b/crypto/src/crypto/signers/Ed448Signer.cs
@@ -1,6 +1,5 @@
 using System;
 using System.IO;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
@@ -82,18 +81,13 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         private class Buffer : MemoryStream
         {
-            private readonly object lockObject = new object();
-
-            // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do
-            // Not available in lower .net standard versions
-            //[MethodImpl(MethodImplOptions.Synchronized)]
             internal byte[] GenerateSignature(Ed448PrivateKeyParameters privateKey, Ed448PublicKeyParameters publicKey, byte[] ctx)
             {
-                lock (lockObject)
+                lock (this)
                 {
 #if PORTABLE
-                    byte[] buf = ToArray();
-                    int count = buf.Length;
+                byte[] buf = ToArray();
+                int count = buf.Length;
 #else
                     byte[] buf = GetBuffer();
                     int count = (int)Position;
@@ -105,12 +99,9 @@ namespace Org.BouncyCastle.Crypto.Signers
                 }
             }
 
-            // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do
-            // Not available in lower .net standard versions
-            //[MethodImpl(MethodImplOptions.Synchronized)]
             internal bool VerifySignature(Ed448PublicKeyParameters publicKey, byte[] ctx, byte[] signature)
             {
-                lock (lockObject)
+                lock (this)
                 {
 #if PORTABLE
                     byte[] buf = ToArray();
@@ -126,18 +117,16 @@ namespace Org.BouncyCastle.Crypto.Signers
                 }
             }
 
-            // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do
-            // Not available in lower .net standard versions
-            //[MethodImpl(MethodImplOptions.Synchronized)]
             internal void Reset()
             {
-                lock (lockObject)
+                lock (this)
                 {
+                    long count = Position;
 #if PORTABLE
                     this.Position = 0L;
                     Streams.WriteZeroes(this, count);
 #else
-                    Array.Clear(GetBuffer(), 0, (int)Position);
+                    Array.Clear(GetBuffer(), 0, (int)count);
 #endif
                     this.Position = 0L;
                 }
diff --git a/crypto/src/crypto/signers/Ed448phSigner.cs b/crypto/src/crypto/signers/Ed448phSigner.cs
index b86d0855c..8f451f9e8 100644
--- a/crypto/src/crypto/signers/Ed448phSigner.cs
+++ b/crypto/src/crypto/signers/Ed448phSigner.cs
@@ -1,6 +1,5 @@
 using System;
 using System.IO;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math.EC.Rfc8032;
diff --git a/crypto/src/crypto/signers/RsaDigestSigner.cs b/crypto/src/crypto/signers/RsaDigestSigner.cs
index d9b19cf6b..b210de03e 100644
--- a/crypto/src/crypto/signers/RsaDigestSigner.cs
+++ b/crypto/src/crypto/signers/RsaDigestSigner.cs
@@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Signers
     public class RsaDigestSigner
         : ISigner
     {
-        private readonly IAsymmetricBlockCipher rsaEngine = new Pkcs1Encoding(new RsaBlindedEngine());
+        private readonly IAsymmetricBlockCipher rsaEngine;
         private readonly AlgorithmIdentifier algId;
         private readonly IDigest digest;
         private bool forSigning;
@@ -59,7 +59,18 @@ namespace Org.BouncyCastle.Crypto.Signers
         }
 
         public RsaDigestSigner(IDigest digest, AlgorithmIdentifier algId)
+            :   this(new RsaCoreEngine(), digest, algId)
         {
+        }
+
+        public RsaDigestSigner(IRsa rsa, IDigest digest, DerObjectIdentifier digestOid)
+            :   this(rsa, digest, new AlgorithmIdentifier(digestOid, DerNull.Instance))
+        {
+        }
+
+        public RsaDigestSigner(IRsa rsa, IDigest digest, AlgorithmIdentifier algId)
+        {
+            this.rsaEngine = new Pkcs1Encoding(new RsaBlindedEngine(rsa));
             this.digest = digest;
             this.algId = algId;
         }
diff --git a/crypto/src/crypto/tls/TlsDHKeyExchange.cs b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
index 59d52265b..7b922352d 100644
--- a/crypto/src/crypto/tls/TlsDHKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDHKeyExchange.cs
@@ -22,6 +22,12 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected DHPrivateKeyParameters mDHAgreePrivateKey;
         protected DHPublicKeyParameters mDHAgreePublicKey;
 
+        [Obsolete("Use constructor that takes a TlsDHVerifier")]
+        public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
+            :   this(keyExchange, supportedSignatureAlgorithms, new DefaultTlsDHVerifier(), dhParameters)
+        {
+        }
+
         public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters)
             :   base(keyExchange, supportedSignatureAlgorithms)
         {
diff --git a/crypto/src/crypto/tls/TlsDheKeyExchange.cs b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
index 402c74720..5007d7daa 100644
--- a/crypto/src/crypto/tls/TlsDheKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsDheKeyExchange.cs
@@ -13,6 +13,12 @@ namespace Org.BouncyCastle.Crypto.Tls
     {
         protected TlsSignerCredentials mServerCredentials = null;
 
+        [Obsolete("Use constructor that takes a TlsDHVerifier")]
+        public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
+            :   this(keyExchange, supportedSignatureAlgorithms, new DefaultTlsDHVerifier(), dhParameters)
+        {
+        }
+
         public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsDHVerifier dhVerifier, DHParameters dhParameters)
             :   base(keyExchange, supportedSignatureAlgorithms, dhVerifier, dhParameters)
         {
diff --git a/crypto/src/crypto/tls/TlsPskKeyExchange.cs b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
index 36ef09e85..31f4c002d 100644
--- a/crypto/src/crypto/tls/TlsPskKeyExchange.cs
+++ b/crypto/src/crypto/tls/TlsPskKeyExchange.cs
@@ -36,6 +36,15 @@ namespace Org.BouncyCastle.Crypto.Tls
         protected TlsEncryptionCredentials mServerCredentials = null;
         protected byte[] mPremasterSecret;
 
+        [Obsolete("Use constructor that takes a TlsDHVerifier")]
+        public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity,
+            TlsPskIdentityManager pskIdentityManager, DHParameters dhParameters, int[] namedCurves,
+            byte[] clientECPointFormats, byte[] serverECPointFormats)
+            :   this(keyExchange, supportedSignatureAlgorithms, pskIdentity, pskIdentityManager, new DefaultTlsDHVerifier(),
+                    dhParameters, namedCurves, clientECPointFormats, serverECPointFormats)
+        {
+        }
+
         public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity,
             TlsPskIdentityManager pskIdentityManager, TlsDHVerifier dhVerifier, DHParameters dhParameters, int[] namedCurves,
             byte[] clientECPointFormats, byte[] serverECPointFormats)
diff --git a/crypto/src/math/ec/rfc7748/X25519.cs b/crypto/src/math/ec/rfc7748/X25519.cs
index 9db3a24c6..d8db2527a 100644
--- a/crypto/src/math/ec/rfc7748/X25519.cs
+++ b/crypto/src/math/ec/rfc7748/X25519.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Diagnostics;
-using System.Runtime.CompilerServices;
+
+using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Math.EC.Rfc7748
 {
@@ -19,8 +20,15 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
         private static readonly int[] PsubS_x = { 0x03D48290, 0x02C7804D, 0x01207816, 0x028F5A68, 0x00881ED4, 0x00A2B71D,
             0x0217D1B7, 0x014CB523, 0x0088EC1A, 0x0042A264 };
 
+        private static readonly object precompLock = new object();
         private static int[] precompBase = null;
 
+        public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff)
+        {
+            ScalarMult(k, kOff, u, uOff, r, rOff);
+            return !Arrays.AreAllZeroes(r, rOff, PointSize);
+        }
+
         private static uint Decode32(byte[] bs, int off)
         {
             uint n = bs[off];
@@ -57,12 +65,9 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             X25519Field.Mul(z, A, z);
         }
 
-        // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do
-        // Not available in lower .net standard versions
-        //[MethodImpl(MethodImplOptions.Synchronized)]
         public static void Precompute()
         {
-            lock (typeof(X25519))
+            lock (precompLock)
             {
                 if (precompBase != null)
                     return;
diff --git a/crypto/src/math/ec/rfc7748/X448.cs b/crypto/src/math/ec/rfc7748/X448.cs
index cf581e9fc..63d34d1cf 100644
--- a/crypto/src/math/ec/rfc7748/X448.cs
+++ b/crypto/src/math/ec/rfc7748/X448.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Diagnostics;
-using System.Runtime.CompilerServices;
+
+using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Math.EC.Rfc7748
 {
@@ -22,8 +23,15 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             0x0643ACE1U, 0x03F1BD65U, 0x084C1F82U, 0x0954459DU, 0x081B9672U, 0x0DD1031CU, 0x0EB7BDACU, 0x03881AFFU, 0x0423ACF0U,
             0x05013244U, 0x0F0FAB72U };
 
+        private static readonly object precompLock = new object();
         private static uint[] precompBase = null;
 
+        public static bool CalculateAgreement(byte[] k, int kOff, byte[] u, int uOff, byte[] r, int rOff)
+        {
+            ScalarMult(k, kOff, u, uOff, r, rOff);
+            return !Arrays.AreAllZeroes(r, rOff, PointSize);
+        }
+
         private static uint Decode32(byte[] bs, int off)
         {
             uint n = bs[off];
@@ -61,12 +69,9 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
             X448Field.Mul(z, A, z);
         }
 
-        // https://stackoverflow.com/questions/2223656/what-does-methodimploptions-synchronized-do
-        // Not available in lower .net standard versions
-        //[MethodImpl(MethodImplOptions.Synchronized)]
         public static void Precompute()
         {
-            lock (typeof(X448))
+            lock (precompLock)
             {
                 if (precompBase != null)
                     return;
@@ -76,8 +81,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
                 uint[] xs = precompBase;
                 uint[] zs = new uint[X448Field.Size * 445];
 
-                uint[] x = X448Field.Create(); x[0] = 5;
-                uint[] z = X448Field.Create(); z[0] = 1;
+                uint[] x = X448Field.Create();     x[0] = 5;          
+                uint[] z = X448Field.Create();     z[0] = 1;
 
                 uint[] n = X448Field.Create();
                 uint[] d = X448Field.Create();
@@ -86,10 +91,10 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
                 X448Field.Add(x, z, n);
                 X448Field.Sub(x, z, d);
 
-                uint[] c = X448Field.Create(); X448Field.Copy(d, 0, c, 0);
+                uint[] c = X448Field.Create();     X448Field.Copy(d, 0, c, 0);
 
                 int off = 0;
-                for (; ; )
+                for (;;)
                 {
                     X448Field.Copy(n, 0, xs, off);
 
@@ -112,7 +117,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc7748
                 uint[] u = X448Field.Create();
                 X448Field.Inv(c, u);
 
-                for (; ; )
+                for (;;)
                 {
                     X448Field.Copy(xs, off, x, 0);
 
diff --git a/crypto/src/math/ec/rfc8032/Ed25519.cs b/crypto/src/math/ec/rfc8032/Ed25519.cs
index 1154a1021..403f11f50 100644
--- a/crypto/src/math/ec/rfc8032/Ed25519.cs
+++ b/crypto/src/math/ec/rfc8032/Ed25519.cs
@@ -1,6 +1,5 @@
 using System;
 using System.Diagnostics;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Digests;
@@ -61,6 +60,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
         private const int PrecompPoints = 1 << (PrecompTeeth - 1);
         private const int PrecompMask = PrecompPoints - 1;
 
+        private static readonly object precompLock = new object();
         // TODO[ed25519] Convert to PointPrecomp
         private static PointExt[] precompBaseTable = null;
         private static int[] precompBase = null;
@@ -631,10 +631,9 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             X25519Field.Zero(p.t);
         }
 
-        //[MethodImpl(MethodImplOptions.Synchronized)]
         public static void Precompute()
         {
-            lock (typeof(Ed25519))
+            lock (precompLock)
             {
                 if (precompBase != null)
                     return;
@@ -679,7 +678,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
                                 PointDouble(p);
                             }
                         }
-                }
+                    }
 
                     PointExt[] points = new PointExt[PrecompPoints];
                     int k = 0;
diff --git a/crypto/src/math/ec/rfc8032/Ed448.cs b/crypto/src/math/ec/rfc8032/Ed448.cs
index 12f69b676..10ebe8f15 100644
--- a/crypto/src/math/ec/rfc8032/Ed448.cs
+++ b/crypto/src/math/ec/rfc8032/Ed448.cs
@@ -1,6 +1,5 @@
 using System;
 using System.Diagnostics;
-using System.Runtime.CompilerServices;
 
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Digests;
@@ -70,6 +69,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
         private const int PrecompPoints = 1 << (PrecompTeeth - 1);
         private const int PrecompMask = PrecompPoints - 1;
 
+        private static readonly object precompLock = new object();
         // TODO[ed448] Convert to PointPrecomp
         private static PointExt[] precompBaseTable = null;
         private static uint[] precompBase = null;
@@ -463,12 +463,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             X448Field.Mul(p.y, r.y, D);
             X448Field.Mul(C, D, E);
             X448Field.Mul(E, -C_d, E);
-    //        X448Field.Apm(B, E, F, G);
+            //X448Field.Apm(B, E, F, G);
             X448Field.Add(B, E, f);
             X448Field.Sub(B, E, g);
             X448Field.Add(r.x, r.y, E);
             X448Field.Mul(H, E, H);
-    //        X448Field.Apm(D, C, B, E);
+            //X448Field.Apm(D, C, B, E);
             X448Field.Add(D, C, b);
             X448Field.Sub(D, C, e);
             X448Field.Carry(b);
@@ -495,13 +495,13 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             X448Field.Mul(p.y, r.y, D);
             X448Field.Mul(C, D, E);
             X448Field.Mul(E, -C_d, E);
-    //        X448Field.Apm(B, E, F, G);
+            //X448Field.Apm(B, E, F, G);
             X448Field.Add(B, E, F);
             X448Field.Sub(B, E, G);
             X448Field.Add(p.x, p.y, B);
             X448Field.Add(r.x, r.y, E);
             X448Field.Mul(B, E, H);
-    //        X448Field.Apm(D, C, B, E);
+            //X448Field.Apm(D, C, B, E);
             X448Field.Add(D, C, B);
             X448Field.Sub(D, C, E);
             X448Field.Carry(B);
@@ -592,10 +592,9 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             X448Field.One(p.z);
         }
 
-        //[MethodImpl(MethodImplOptions.Synchronized)]
         public static void Precompute()
         {
-            lock (typeof(Ed448))
+            lock (precompLock)
             {
                 if (precompBase != null)
                     return;
@@ -631,7 +630,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
                                 PointDouble(p);
                             }
                         }
-                }
+                    }
 
                     PointExt[] points = new PointExt[PrecompPoints];
                     int k = 0;
@@ -657,8 +656,8 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
                         X448Field.Mul(q.x, q.z, q.x);
                         X448Field.Mul(q.y, q.z, q.y);
 
-                        //                X448Field.Normalize(q.x);
-                        //                X448Field.Normalize(q.y);
+                        //X448Field.Normalize(q.x);
+                        //X448Field.Normalize(q.y);
 
                         X448Field.Copy(q.x, 0, precompBase, off); off += X448Field.Size;
                         X448Field.Copy(q.y, 0, precompBase, off); off += X448Field.Size;
@@ -734,7 +733,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             x21 += x31 * L4_6;                          // x21:55/53
             x22 += x31 * L4_7;                          // x22:57/53
 
-    //        x30 += (x29 >> 28); x29 &= M28UL;
+            //x30 += (x29 >> 28); x29 &= M28UL;
             x14 += x30 * L4_0;                          // x14:54/--
             x15 += x30 * L4_1;                          // x15:54/53
             x16 += x30 * L4_2;                          // x16:56/--
@@ -754,7 +753,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             x19 += x29 * L4_6;                          // x19:57/52
             x20 += x29 * L4_7;                          // x20:58/52
 
-    //        x28 += (x27 >> 28); x27 &= M28UL;
+            //x28 += (x27 >> 28); x27 &= M28UL;
             x12 += x28 * L4_0;                          // x12:54/--
             x13 += x28 * L4_1;                          // x13:54/53
             x14 += x28 * L4_2;                          // x14:56/--
@@ -774,7 +773,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             x17 += x27 * L4_6;                          // x17:58/56
             x18 += x27 * L4_7;                          // x18:59/--
 
-    //        x26 += (x25 >> 28); x25 &= M28UL;
+            //x26 += (x25 >> 28); x25 &= M28UL;
             x10 += x26 * L4_0;                          // x10:54/--
             x11 += x26 * L4_1;                          // x11:54/53
             x12 += x26 * L4_2;                          // x12:56/--
@@ -951,7 +950,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032
             Encode56(x10 | (x11 << 28), r, 35);
             Encode56(x12 | (x13 << 28), r, 42);
             Encode56(x14 | (x15 << 28), r, 49);
-    //        r[ScalarBytes - 1] = 0;
+            //r[ScalarBytes - 1] = 0;
             return r;
         }
 
diff --git a/crypto/src/openpgp/PgpUtilities.cs b/crypto/src/openpgp/PgpUtilities.cs
index 039aa5893..1a93cc78d 100644
--- a/crypto/src/openpgp/PgpUtilities.cs
+++ b/crypto/src/openpgp/PgpUtilities.cs
@@ -367,7 +367,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             byte[]		buffer)
         {
             PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator();
-            Stream pOut = lData.Open(output, fileType, file.Name, file.LastWriteTime, buffer);
+            Stream pOut = lData.Open(output, fileType, file.Name, file.LastWriteTime, Arrays.Clone(buffer));
 			PipeFileContents(file, pOut, buffer.Length);
         }
 
diff --git a/crypto/src/pkcs/Pkcs12Store.cs b/crypto/src/pkcs/Pkcs12Store.cs
index 52760f89b..7db264232 100644
--- a/crypto/src/pkcs/Pkcs12Store.cs
+++ b/crypto/src/pkcs/Pkcs12Store.cs
@@ -367,6 +367,10 @@ namespace Org.BouncyCastle.Pkcs
                         keyCerts[name] = certEntry;
                         keys[name] = unmarkedKeyEntry;
                     }
+                    else
+                    {
+                        keys["unmarked"] = unmarkedKeyEntry;
+                    }
                 }
                 else
                 {
diff --git a/crypto/src/security/ParameterUtilities.cs b/crypto/src/security/ParameterUtilities.cs
index 792067bba..dc6992833 100644
--- a/crypto/src/security/ParameterUtilities.cs
+++ b/crypto/src/security/ParameterUtilities.cs
@@ -299,6 +299,15 @@ namespace Org.BouncyCastle.Security
             throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised.");
         }
 
+        public static ICipherParameters WithRandom(ICipherParameters cp, SecureRandom random)
+        {
+            if (random != null)
+            {
+                cp = new ParametersWithRandom(cp, random);
+            }
+            return cp;
+        }
+
         private static Asn1OctetString CreateIVOctetString(
             SecureRandom	random,
             int				ivLength)
diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs
index a9045ae6e..6107bf878 100644
--- a/crypto/src/security/SignerUtilities.cs
+++ b/crypto/src/security/SignerUtilities.cs
@@ -602,5 +602,17 @@ namespace Org.BouncyCastle.Security
         {
             return (string) algorithms[oid.Id];
         }
+
+        public static ISigner InitSigner(DerObjectIdentifier algorithmOid, bool forSigning, AsymmetricKeyParameter privateKey, SecureRandom random)
+        {
+            return InitSigner(algorithmOid.Id, forSigning, privateKey, random);
+        }
+
+        public static ISigner InitSigner(string algorithm, bool forSigning, AsymmetricKeyParameter privateKey, SecureRandom random)
+        {
+            ISigner signer = SignerUtilities.GetSigner(algorithm);
+            signer.Init(forSigning, ParameterUtilities.WithRandom(privateKey, random));
+            return signer;
+        }
     }
 }
diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs
index 3df908240..a9a574dbf 100644
--- a/crypto/src/util/Arrays.cs
+++ b/crypto/src/util/Arrays.cs
@@ -11,6 +11,16 @@ namespace Org.BouncyCastle.Utilities
         public static readonly byte[] EmptyBytes = new byte[0];
         public static readonly int[] EmptyInts = new int[0];
 
+        public static bool AreAllZeroes(byte[] buf, int off, int len)
+        {
+            uint bits = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                bits |= buf[off + i];
+            }
+            return bits == 0;
+        }
+
         public static bool AreEqual(
             bool[]  a,
             bool[]  b)