summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Hook <dgh@bouncycastle.org>2015-10-16 09:30:29 +1100
committerDavid Hook <dgh@bouncycastle.org>2015-10-16 09:30:29 +1100
commitb18da3a6bc82e3b0119edb7184db15ba3bc12c8a (patch)
treea0e0850341d707010999a6b5317a37eb9ac40242
parentClose files after reading (diff)
downloadBouncyCastle.NET-ed25519-b18da3a6bc82e3b0119edb7184db15ba3bc12c8a.tar.xz
Further work of signature/verification calculators.
Added IBlockResult and IVerifier
Added verifier provider verify methods to X.509 PKCS#10 classes.
-rw-r--r--crypto/src/crypto/IBlockResult.cs24
-rw-r--r--crypto/src/crypto/ISignatureCalculator.cs27
-rw-r--r--crypto/src/crypto/ISignatureVerifier.cs34
-rw-r--r--crypto/src/crypto/IStreamCalculator.cs23
-rw-r--r--crypto/src/crypto/IVerifier.cs25
-rw-r--r--crypto/src/crypto/operators/Asn1Signature.cs283
-rw-r--r--crypto/src/pkcs/Pkcs10CertificationRequest.cs84
-rw-r--r--crypto/src/x509/X509Certificate.cs35
-rw-r--r--crypto/src/x509/X509Crl.cs51
-rw-r--r--crypto/src/x509/X509V1CertificateGenerator.cs10
-rw-r--r--crypto/src/x509/X509V2AttributeCertificate.cs42
-rw-r--r--crypto/src/x509/X509V2AttributeCertificateGenerator.cs8
-rw-r--r--crypto/src/x509/X509V2CRLGenerator.cs8
-rw-r--r--crypto/src/x509/X509V3CertificateGenerator.cs8
14 files changed, 430 insertions, 232 deletions
diff --git a/crypto/src/crypto/IBlockResult.cs b/crypto/src/crypto/IBlockResult.cs
new file mode 100644
index 000000000..c12bdaa1d
--- /dev/null
+++ b/crypto/src/crypto/IBlockResult.cs
@@ -0,0 +1,24 @@
+
+namespace Org.BouncyCastle.Crypto
+{
+    /// <summary>
+    /// Operators that reduce their input to a single block return an object
+    /// of this type.
+    /// </summary>
+    public interface IBlockResult
+    {
+        /// <summary>
+        /// Return the final result of the operation.
+        /// </summary>
+        /// <returns>A block of bytes, representing the result of an operation.</returns>
+        byte[] DoFinal();
+
+        /// <summary>
+        /// Store the final result of the operation by copying it into the destination array.
+        /// </summary>
+        /// <returns>The number of bytes copied into destination.</returns>
+        /// <param name="destination">The byte array to copy the result into.</param>
+        /// <param name="offset">The offset into destination to start copying the result at.</param>
+        int DoFinal(byte[] destination, int offset);
+    }
+}
diff --git a/crypto/src/crypto/ISignatureCalculator.cs b/crypto/src/crypto/ISignatureCalculator.cs
index 3d7f935b2..bb733818d 100644
--- a/crypto/src/crypto/ISignatureCalculator.cs
+++ b/crypto/src/crypto/ISignatureCalculator.cs
@@ -1,5 +1,4 @@
 using System;
-using System.IO;
 
 namespace Org.BouncyCastle.Crypto
 {
@@ -11,28 +10,14 @@ namespace Org.BouncyCastle.Crypto
         /// <summary>The algorithm details object for this calculator.</summary>
         Object AlgorithmDetails { get ; }
 
-        /// <summary>Return a "bucket" stream which only exists to update the calculator.</summary>
-        /// <returns>A stream to write to in order to update the calculator.</returns>
-        Stream GetSignatureUpdater (); // returns writable stream
-
         /// <summary>
-        /// Return a stream that wraps the passed in stream, the data written/read to 
-        /// the returned stream will update the calculator as well as being passed through.
+        /// Create a stream calculator for this signature calculator. The stream
+        /// calculator is used for the actual operation of entering the data to be signed
+        /// and producing the signature block.
         /// </summary>
-        /// <param name="stream">The stream to be wrapped, must be either readable or writeable, but not both</param>
-        /// <returns>A wrapped version of stream which updates the calculator.</returns>
-        Stream GetSignatureUpdatingStream (Stream stream);
-
-        /// <summary>Calculate the signature and return it as a byte array.</summary>
-        /// <returns>The calculated signature.</returns>
-        byte[] Signature();
-
-        /// <summary>Calculate the signature and save it in the passed in byte array.</summary>
-        /// <param name="destination">The destination array to store the signature in.</param>
-        /// <param name="off">The offset into destination to start writing the signature.</param>
-        /// <returns>The number of bytes written to destination.</returns>
-        int Signature(byte[] destination, int off);
-	}
+        /// <returns>A calculator producing an IBlockResult with a signature in it.</returns>
+        IStreamCalculator CreateCalculator();
+    }
 }
 
 
diff --git a/crypto/src/crypto/ISignatureVerifier.cs b/crypto/src/crypto/ISignatureVerifier.cs
index 1c6cd0e49..1f42a0256 100644
--- a/crypto/src/crypto/ISignatureVerifier.cs
+++ b/crypto/src/crypto/ISignatureVerifier.cs
@@ -1,5 +1,4 @@
 using System;
-using System.IO;
 
 namespace Org.BouncyCastle.Crypto
 {
@@ -11,33 +10,12 @@ namespace Org.BouncyCastle.Crypto
         /// <summary>The algorithm details object for this verifier.</summary>
         Object AlgorithmDetails { get ; }
 
-        /// <summary>Return a "bucket" stream which only exists to update the verifier.</summary>
-        /// <returns>A stream to write to in order to update the verifier.</returns>
-        Stream GetVerifierUpdater ();
-
-        /// <summary>
-        /// Return a stream that wraps the passed in stream, the data written/read to 
-        /// the returned stream will update the verifier as well as being passed through.
-        /// </summary>
-        /// <param name="stream">The stream to be wrapped, must be either readable or writeable, but not both</param>
-        /// <returns>A wrapped version of stream which updates the verifier.</returns>
-        Stream GetVerifierUpdatingStream (Stream stream);
-
-        /// <summary>
-        /// Return true if the passed in signature matches what is expected by the verifier.
-        /// </summary>
-        /// <param name="signature">The bytes representing the signature.</param>
-        /// <returns>true if the signature verifies, false otherwise.</returns>
-		bool IsVerified(byte[] signature);
-
         /// <summary>
-        /// Return true if the length bytes from off in the source array match the signature
-        /// expected by the verifier.
+        /// Create a stream calculator for this verifier. The stream
+        /// calculator is used for the actual operation of entering the data to be verified
+        /// and producing a result which can be used to verify the original signature.
         /// </summary>
-        /// <param name="source">Byte array containing the signature.</param>
-        /// <param name="off">The offset into the source array where the signature starts.</param>
-        /// <param name="length">The number of bytes in source making up the signature.</param>
-        /// <returns>true if the signature verifies, false otherwise.</returns>
-		bool IsVerified(byte[] source, int off, int length);
-	}
+        /// <returns>A calculator producing an IVerifier which can verify the signature.</returns>
+        IStreamCalculator CreateCalculator();
+    }
 }
diff --git a/crypto/src/crypto/IStreamCalculator.cs b/crypto/src/crypto/IStreamCalculator.cs
new file mode 100644
index 000000000..19a542845
--- /dev/null
+++ b/crypto/src/crypto/IStreamCalculator.cs
@@ -0,0 +1,23 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /// <summary>
+    /// Base interface for cryptographic operations such as Hashes, MACs, and Signatures which reduce a stream of data
+    /// to a single value.
+    /// </summary>
+    public interface IStreamCalculator
+    {
+        /// <summary>Return a "sink" stream which only exists to update the implementing object.</summary>
+        /// <returns>A stream to write to in order to update the implementing object.</returns>
+        Stream Stream { get; }
+
+        /// <summary>
+        /// Return the result of processing the stream. This value is only available once the stream
+        /// has been closed.
+        /// </summary>
+        /// <returns>The result of processing the stream.</returns>
+        Object GetResult();
+    }
+}
diff --git a/crypto/src/crypto/IVerifier.cs b/crypto/src/crypto/IVerifier.cs
new file mode 100644
index 000000000..560cabf8e
--- /dev/null
+++ b/crypto/src/crypto/IVerifier.cs
@@ -0,0 +1,25 @@
+namespace Org.BouncyCastle.Crypto
+{
+    /// <summary>
+    /// Operators that reduce their input to the validation of a signature produce this type.
+    /// </summary>
+    public interface IVerifier
+    {
+        /// <summary>
+        /// Return true if the passed in data matches what is expected by the verification result.
+        /// </summary>
+        /// <param name="data">The bytes representing the signature.</param>
+        /// <returns>true if the signature verifies, false otherwise.</returns>
+        bool IsVerified(byte[] data);
+
+        /// <summary>
+        /// Return true if the length bytes from off in the source array match the signature
+        /// expected by the verification result.
+        /// </summary>
+        /// <param name="source">Byte array containing the signature.</param>
+        /// <param name="off">The offset into the source array where the signature starts.</param>
+        /// <param name="length">The number of bytes in source making up the signature.</param>
+        /// <returns>true if the signature verifies, false otherwise.</returns>
+        bool IsVerified(byte[] source, int off, int length);
+    }
+}
diff --git a/crypto/src/crypto/operators/Asn1Signature.cs b/crypto/src/crypto/operators/Asn1Signature.cs
index cc1b7f2eb..0fd37b275 100644
--- a/crypto/src/crypto/operators/Asn1Signature.cs
+++ b/crypto/src/crypto/operators/Asn1Signature.cs
@@ -20,7 +20,9 @@ namespace Org.BouncyCastle.Crypto.Operators
 {
 	internal class X509Utilities
 	{
-		private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        private static readonly Asn1Null derNull = DerNull.Instance;
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
 		private static readonly IDictionary exParams = Platform.CreateHashtable();
 		private static readonly ISet        noParams = new HashSet();
 
@@ -109,7 +111,83 @@ namespace Org.BouncyCastle.Crypto.Operators
 			exParams.Add("SHA512WITHRSAANDMGF1", CreatePssParams(sha512AlgId, 64));
 		}
 
-		private static RsassaPssParameters CreatePssParams(
+        /**
+		 * Return the digest algorithm using one of the standard JCA string
+		 * representations rather than the algorithm identifier (if possible).
+		 */
+        private static string GetDigestAlgName(
+            DerObjectIdentifier digestAlgOID)
+        {
+            if (PkcsObjectIdentifiers.MD5.Equals(digestAlgOID))
+            {
+                return "MD5";
+            }
+            else if (OiwObjectIdentifiers.IdSha1.Equals(digestAlgOID))
+            {
+                return "SHA1";
+            }
+            else if (NistObjectIdentifiers.IdSha224.Equals(digestAlgOID))
+            {
+                return "SHA224";
+            }
+            else if (NistObjectIdentifiers.IdSha256.Equals(digestAlgOID))
+            {
+                return "SHA256";
+            }
+            else if (NistObjectIdentifiers.IdSha384.Equals(digestAlgOID))
+            {
+                return "SHA384";
+            }
+            else if (NistObjectIdentifiers.IdSha512.Equals(digestAlgOID))
+            {
+                return "SHA512";
+            }
+            else if (TeleTrusTObjectIdentifiers.RipeMD128.Equals(digestAlgOID))
+            {
+                return "RIPEMD128";
+            }
+            else if (TeleTrusTObjectIdentifiers.RipeMD160.Equals(digestAlgOID))
+            {
+                return "RIPEMD160";
+            }
+            else if (TeleTrusTObjectIdentifiers.RipeMD256.Equals(digestAlgOID))
+            {
+                return "RIPEMD256";
+            }
+            else if (CryptoProObjectIdentifiers.GostR3411.Equals(digestAlgOID))
+            {
+                return "GOST3411";
+            }
+            else
+            {
+                return digestAlgOID.Id;
+            }
+        }
+
+        internal static string GetSignatureName(AlgorithmIdentifier sigAlgId)
+        {
+            Asn1Encodable parameters = sigAlgId.Parameters;
+
+            if (parameters != null && !derNull.Equals(parameters))
+            {
+                if (sigAlgId.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss))
+                {
+                    RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(parameters);
+
+                    return GetDigestAlgName(rsaParams.HashAlgorithm.ObjectID) + "withRSAandMGF1";
+                }
+                if (sigAlgId.ObjectID.Equals(X9ObjectIdentifiers.ECDsaWithSha2))
+                {
+                    Asn1Sequence ecDsaParams = Asn1Sequence.GetInstance(parameters);
+
+                    return GetDigestAlgName((DerObjectIdentifier)ecDsaParams[0]) + "withECDSA";
+                }
+            }
+
+            return sigAlgId.ObjectID.Id;
+        }
+
+        private static RsassaPssParameters CreatePssParams(
 			AlgorithmIdentifier	hashAlgId,
 			int					saltSize)
 		{
@@ -254,14 +332,16 @@ namespace Org.BouncyCastle.Crypto.Operators
 	public class Asn1SignatureCalculator: ISignatureCalculator
 	{
 		private readonly AlgorithmIdentifier algID;
-		private readonly ISigner sig;
+        private readonly string algorithm;
+        private readonly AsymmetricKeyParameter privateKey;
+        private readonly SecureRandom random;
 
         /// <summary>
         /// Base constructor.
         /// </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 Asn1SignatureCalculator (String algorithm, AsymmetricKeyParameter privateKey): this(algorithm, privateKey, null)
+		public Asn1SignatureCalculator (string algorithm, AsymmetricKeyParameter privateKey): this(algorithm, privateKey, null)
 		{
 		}
 
@@ -271,21 +351,13 @@ 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 Asn1SignatureCalculator (String algorithm, AsymmetricKeyParameter privateKey, SecureRandom random)
+		public Asn1SignatureCalculator (string algorithm, AsymmetricKeyParameter privateKey, SecureRandom random)
 		{
 			DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid (algorithm);
 
-			this.sig = SignerUtilities.GetSigner(algorithm);
-
-			if (random != null)
-			{
-				sig.Init(true, new ParametersWithRandom(privateKey, random));
-			}
-			else
-			{
-				sig.Init(true, privateKey);
-			}
-
+            this.algorithm = algorithm;
+            this.privateKey = privateKey;
+            this.random = random;
 			this.algID = X509Utilities.GetSigAlgID (sigOid, algorithm);
 		}
 
@@ -294,44 +366,74 @@ namespace Org.BouncyCastle.Crypto.Operators
 			get { return this.algID; }
 		}
 
-		public Stream GetSignatureUpdater ()
-		{
-			return new SignerBucket (sig);
-		}
+        public IStreamCalculator CreateCalculator()
+        {
+            ISigner sig = SignerUtilities.GetSigner(algorithm);
+
+            if (random != null)
+            {
+                sig.Init(true, new ParametersWithRandom(privateKey, random));
+            }
+            else
+            {
+                sig.Init(true, privateKey);
+            }
+
+            return new SigCalculator(sig);
+        }
 
-		public Stream GetSignatureUpdatingStream (Stream stream)
-		{
-			if (stream.CanRead && stream.CanWrite) {
-				throw new ArgumentException ("cannot use read/write stream");
-			}
+        /// <summary>
+        /// Allows enumeration of the signature names supported by the verifier provider.
+        /// </summary>
+        public static IEnumerable SignatureAlgNames
+        {
+            get { return X509Utilities.GetAlgNames(); }
+        }
+    }
 
-			if (stream.CanRead) {
-				return new SignerStream (stream, sig, null);
-			} else {
-				return new SignerStream (stream, null, sig);
-			}
-		}
+    internal class SigCalculator : IStreamCalculator
+    {
+        private readonly ISigner sig;
+        private readonly Stream stream;
 
-		public byte[] Signature()
-		{
-			return sig.GenerateSignature ();
-		}
+        internal SigCalculator(ISigner sig)
+        {
+            this.sig = sig;
+            this.stream = new SignerBucket(sig);
+        }
 
-		public int Signature(byte[] destination, int off)
-		{
-			byte[] sigBytes = Signature ();
+        public Stream Stream
+        {
+            get { return stream; }
+        }
 
-			Array.Copy (sigBytes, 0, destination, off, sigBytes.Length);
+        public object GetResult()
+        {
+            return new SigResult(sig);
+        }
+    }
 
-			return sigBytes.Length;
-		}
+    internal class SigResult : IBlockResult
+    {
+        private readonly ISigner sig;
 
-        /// <summary>
-        /// Allows enumeration of the signature names supported by the verifier provider.
-        /// </summary>
-        public static IEnumerable SignatureAlgNames
+        internal SigResult(ISigner sig)
         {
-            get { return X509Utilities.GetAlgNames(); }
+            this.sig = sig;
+        }
+
+        public byte[] DoFinal()
+        {
+            return sig.GenerateSignature();
+        }
+
+        public int DoFinal(byte[] destination, int offset)
+        {
+            byte[] signature = DoFinal();
+
+            Array.Copy(signature, 0, destination, offset, signature.Length);
+
+            return signature.Length;
         }
     }
 
@@ -342,7 +444,7 @@ namespace Org.BouncyCastle.Crypto.Operators
     public class Asn1SignatureVerifier: ISignatureVerifier
 	{
 		private readonly AlgorithmIdentifier algID;
-		private readonly ISigner sig;
+        private readonly AsymmetricKeyParameter publicKey;
 
         /// <summary>
         /// Base constructor.
@@ -353,21 +455,13 @@ namespace Org.BouncyCastle.Crypto.Operators
 		{
 			DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid (algorithm);
 
-			this.sig = SignerUtilities.GetSigner(algorithm);
-
-			sig.Init(false, publicKey);
-
+            this.publicKey = publicKey;
 			this.algID = X509Utilities.GetSigAlgID (sigOid, algorithm);
 		}
 
 		public Asn1SignatureVerifier (AlgorithmIdentifier algorithm, AsymmetricKeyParameter publicKey)
 		{
-			DerObjectIdentifier sigOid = algorithm.Algorithm;
-
-			this.sig = SignerUtilities.GetSigner(sigOid);
-
-			sig.Init(false, publicKey);
-
+            this.publicKey = publicKey;
 			this.algID = algorithm;
 		}
 
@@ -376,38 +470,61 @@ namespace Org.BouncyCastle.Crypto.Operators
 			get { return this.algID; }
 		}
 
-		public Stream GetVerifierUpdater ()
-		{
-			return new SignerBucket (sig);
-		}
+        public IStreamCalculator CreateCalculator()
+        {
+            ISigner sig = SignerUtilities.GetSigner(X509Utilities.GetSignatureName(algID));
 
-		public Stream GetVerifierUpdatingStream (Stream stream)
-		{
-			if (stream.CanRead && stream.CanWrite) {
-				throw new ArgumentException ("cannot use read/write stream");
-			}
+            sig.Init(false, publicKey);
+          
+            return new VerifierCalculator(sig);
+        }
+    }
 
-			if (stream.CanRead) {
-				return new SignerStream (stream, sig, null);
-			} else {
-				return new SignerStream (stream, null, sig);
-			}
-		}
+    internal class VerifierCalculator : IStreamCalculator
+    {
+        private readonly ISigner sig;
+        private readonly Stream stream;
 
-		public bool IsVerified(byte[] signature)
-		{
-			return sig.VerifySignature(signature);
-		}
+        internal VerifierCalculator(ISigner sig)
+        {
+            this.sig = sig;
+            this.stream = new SignerBucket(sig);
+        }
 
-		public bool IsVerified(byte[] signature, int off, int length)
-		{
-			byte[] sigBytes = new byte[length];
+        public Stream Stream
+        {
+            get { return stream; }
+        }
 
-			Array.Copy (signature, 0, sigBytes, off, sigBytes.Length);
+        public object GetResult()
+        {
+            return new VerifierResult(sig);
+        }
+    }
 
-			return sig.VerifySignature(signature);
-		}
-	}
+    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);
+
+            return sig.VerifySignature(signature);
+        }
+    }
 
     /// <summary>
     /// Provider class which supports dynamic creation of signature verifiers.
diff --git a/crypto/src/pkcs/Pkcs10CertificationRequest.cs b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
index 878cb61d3..b68979cad 100644
--- a/crypto/src/pkcs/Pkcs10CertificationRequest.cs
+++ b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
@@ -273,14 +273,16 @@ namespace Org.BouncyCastle.Pkcs
 
             this.reqInfo = new CertificationRequestInfo(subject, pubInfo, attributes);
 
-            Stream sigStream = signatureCalculator.GetSignatureUpdater();
+            IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator();
 
             byte[] reqInfoData = reqInfo.GetDerEncoded();
 
-            sigStream.Write(reqInfoData, 0, reqInfoData.Length);
+            streamCalculator.Stream.Write(reqInfoData, 0, reqInfoData.Length);
+
+            streamCalculator.Stream.Close();
 
             // Generate Signature.
-            sigBits = new DerBitString(signatureCalculator.Signature());
+            sigBits = new DerBitString(((IBlockResult)streamCalculator.GetResult()).DoFinal());
         }
 
         //        internal Pkcs10CertificationRequest(
@@ -320,55 +322,47 @@ namespace Org.BouncyCastle.Pkcs
 		public bool Verify(
 			AsymmetricKeyParameter publicKey)
 		{
-			ISigner sig;
+            return Verify(new Asn1SignatureVerifierProvider(publicKey));
+		}
 
-			try
-			{
-				sig = SignerUtilities.GetSigner(GetSignatureName(sigAlgId));
-			}
-			catch (Exception e)
-			{
-				// try an alternate
-				string alt = (string) oids[sigAlgId.ObjectID];
+        public bool Verify(
+            ISignatureVerifierProvider verifierProvider)
+        {
+            return Verify(verifierProvider.CreateSignatureVerifier(sigAlgId));
+        }
 
-				if (alt != null)
-				{
-					sig = SignerUtilities.GetSigner(alt);
-				}
-				else
-				{
-					throw e;
-				}
-			}
+        public bool Verify(
+            ISignatureVerifier verifier)
+        {
+            try
+            {
+                byte[] b = reqInfo.GetDerEncoded();
 
-			SetSignatureParameters(sig, sigAlgId.Parameters);
+                IStreamCalculator streamCalculator = verifier.CreateCalculator();
 
-			sig.Init(false, publicKey);
+                streamCalculator.Stream.Write(b, 0, b.Length);
 
-			try
-			{
-				byte[] b = reqInfo.GetDerEncoded();
-				sig.BlockUpdate(b, 0, b.Length);
-			}
-			catch (Exception e)
-			{
-				throw new SignatureException("exception encoding TBS cert request", e);
-			}
+                streamCalculator.Stream.Close();
 
-			return sig.VerifySignature(sigBits.GetBytes());
-		}
+                return ((IVerifier)streamCalculator.GetResult()).IsVerified(sigBits.GetBytes());
+            }
+            catch (Exception e)
+            {
+                throw new SignatureException("exception encoding TBS cert request", e);
+            }
+        }
+
+        //        /// <summary>
+        //        /// Get the Der Encoded Pkcs10 Certification Request.
+        //        /// </summary>
+        //        /// <returns>A byte array.</returns>
+        //        public byte[] GetEncoded()
+        //        {
+        //        	return new CertificationRequest(reqInfo, sigAlgId, sigBits).GetDerEncoded();
+        //        }
 
-//        /// <summary>
-//        /// Get the Der Encoded Pkcs10 Certification Request.
-//        /// </summary>
-//        /// <returns>A byte array.</returns>
-//        public byte[] GetEncoded()
-//        {
-//        	return new CertificationRequest(reqInfo, sigAlgId, sigBits).GetDerEncoded();
-//        }
-
-		// TODO Figure out how to set parameters on an ISigner
-		private void SetSignatureParameters(
+        // TODO Figure out how to set parameters on an ISigner
+        private void SetSignatureParameters(
 			ISigner			signature,
 			Asn1Encodable	asn1Params)
 		{
diff --git a/crypto/src/x509/X509Certificate.cs b/crypto/src/x509/X509Certificate.cs
index f156f3147..4487232f0 100644
--- a/crypto/src/x509/X509Certificate.cs
+++ b/crypto/src/x509/X509Certificate.cs
@@ -14,6 +14,7 @@ using Org.BouncyCastle.Security.Certificates;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Encoders;
 using Org.BouncyCastle.X509.Extension;
+using Org.BouncyCastle.Crypto.Operators;
 
 namespace Org.BouncyCastle.X509
 {
@@ -546,30 +547,38 @@ namespace Org.BouncyCastle.X509
 		public virtual void Verify(
 			AsymmetricKeyParameter key)
 		{
-			string sigName = X509SignatureUtilities.GetSignatureName(c.SignatureAlgorithm);
-			ISigner signature = SignerUtilities.GetSigner(sigName);
-
-			CheckSignature(key, signature);
+			CheckSignature(new Asn1SignatureVerifier(c.SignatureAlgorithm, key));
 		}
 
-		protected virtual void CheckSignature(
-			AsymmetricKeyParameter	publicKey,
-			ISigner					signature)
+        /// <summary>
+        /// Verify the certificate's signature using a verifier created using the passed in verifier provider.
+        /// </summary>
+        /// <param name="verifierProvider">An appropriate provider for verifying the certificate's signature.</param>
+        /// <returns>True if the signature is valid.</returns>
+        /// <exception cref="Exception">If verifier provider is not appropriate or the certificate algorithm is invalid.</exception>
+        public virtual void Verify(
+            ISignatureVerifierProvider verifierProvider)
+        {
+            CheckSignature(verifierProvider.CreateSignatureVerifier (c.SignatureAlgorithm));
+        }
+
+        protected virtual void CheckSignature(
+			ISignatureVerifier verifier)
 		{
 			if (!IsAlgIDEqual(c.SignatureAlgorithm, c.TbsCertificate.Signature))
 				throw new CertificateException("signature algorithm in TBS cert not same as outer cert");
 
 			Asn1Encodable parameters = c.SignatureAlgorithm.Parameters;
 
-			X509SignatureUtilities.SetSignatureParameters(signature, parameters);
-
-			signature.Init(false, publicKey);
+            IStreamCalculator streamCalculator = verifier.CreateCalculator();
 
 			byte[] b = this.GetTbsCertificate();
-			signature.BlockUpdate(b, 0, b.Length);
 
-			byte[] sig = this.GetSignature();
-			if (!signature.VerifySignature(sig))
+			streamCalculator.Stream.Write(b, 0, b.Length);
+
+            streamCalculator.Stream.Close();
+
+            if (!((IVerifier)streamCalculator.GetResult()).IsVerified(this.GetSignature()))
 			{
 				throw new InvalidKeyException("Public key presented not for certificate signature");
 			}
diff --git a/crypto/src/x509/X509Crl.cs b/crypto/src/x509/X509Crl.cs
index 7d0e7aa72..1746960fb 100644
--- a/crypto/src/x509/X509Crl.cs
+++ b/crypto/src/x509/X509Crl.cs
@@ -14,6 +14,7 @@ using Org.BouncyCastle.Utilities.Collections;
 using Org.BouncyCastle.Utilities.Date;
 using Org.BouncyCastle.Utilities.Encoders;
 using Org.BouncyCastle.X509.Extension;
+using Org.BouncyCastle.Crypto.Operators;
 
 namespace Org.BouncyCastle.X509
 {
@@ -83,24 +84,46 @@ namespace Org.BouncyCastle.X509
 		public virtual void Verify(
 			AsymmetricKeyParameter publicKey)
 		{
-			if (!c.SignatureAlgorithm.Equals(c.TbsCertList.Signature))
-			{
-				throw new CrlException("Signature algorithm on CertificateList does not match TbsCertList.");
-			}
+            Verify(new Asn1SignatureVerifierProvider(publicKey));
+		}
 
-			ISigner sig = SignerUtilities.GetSigner(SigAlgName);
-			sig.Init(false, publicKey);
+        /// <summary>
+        /// Verify the CRL's signature using a verifier created using the passed in verifier provider.
+        /// </summary>
+        /// <param name="verifierProvider">An appropriate provider for verifying the CRL's signature.</param>
+        /// <returns>True if the signature is valid.</returns>
+        /// <exception cref="Exception">If verifier provider is not appropriate or the CRL algorithm is invalid.</exception>
+        public virtual void Verify(
+            ISignatureVerifierProvider verifierProvider)
+        {
+            CheckSignature(verifierProvider.CreateSignatureVerifier(c.SignatureAlgorithm));
+        }
 
-			byte[] encoded = this.GetTbsCertList();
-			sig.BlockUpdate(encoded, 0, encoded.Length);
+        protected virtual void CheckSignature(
+            ISignatureVerifier verifier)
+        {
+            if (!c.SignatureAlgorithm.Equals(c.TbsCertList.Signature))
+            {
+                throw new CrlException("Signature algorithm on CertificateList does not match TbsCertList.");
+            }
 
-			if (!sig.VerifySignature(this.GetSignature()))
-			{
-				throw new SignatureException("CRL does not verify with supplied public key.");
-			}
-		}
+            Asn1Encodable parameters = c.SignatureAlgorithm.Parameters;
+
+            IStreamCalculator streamCalculator = verifier.CreateCalculator();
+
+            byte[] b = this.GetTbsCertList();
+
+            streamCalculator.Stream.Write(b, 0, b.Length);
+
+            streamCalculator.Stream.Close();
+
+            if (!((IVerifier)streamCalculator.GetResult()).IsVerified(this.GetSignature()))
+            {
+                throw new InvalidKeyException("CRL does not verify with supplied public key.");
+            }
+        }
 
-		public virtual int Version
+        public virtual int Version
 		{
 			get { return c.Version; }
 		}
diff --git a/crypto/src/x509/X509V1CertificateGenerator.cs b/crypto/src/x509/X509V1CertificateGenerator.cs
index 0ab6f4b77..a452df440 100644
--- a/crypto/src/x509/X509V1CertificateGenerator.cs
+++ b/crypto/src/x509/X509V1CertificateGenerator.cs
@@ -178,15 +178,15 @@ namespace Org.BouncyCastle.X509
 
 			TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate();
 
-			Stream sigStream = signatureCalculator.GetSignatureUpdater ();
+            IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator();
 
-			byte[] encoded = tbsCert.GetDerEncoded();
+            byte[] encoded = tbsCert.GetDerEncoded();
 
-			sigStream.Write (encoded, 0, encoded.Length);
+            streamCalculator.Stream.Write(encoded, 0, encoded.Length);
 
-			sigStream.Close ();
+            streamCalculator.Stream.Close();
 
-			return GenerateJcaObject(tbsCert, (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails, signatureCalculator.Signature());
+            return GenerateJcaObject(tbsCert, (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails, ((IBlockResult)streamCalculator.GetResult()).DoFinal());
 		}
 
 		private X509Certificate GenerateJcaObject(
diff --git a/crypto/src/x509/X509V2AttributeCertificate.cs b/crypto/src/x509/X509V2AttributeCertificate.cs
index 117ac4cc2..cc72c23bb 100644
--- a/crypto/src/x509/X509V2AttributeCertificate.cs
+++ b/crypto/src/x509/X509V2AttributeCertificate.cs
@@ -9,6 +9,7 @@ using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Security.Certificates;
 using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Crypto.Operators;
 
 namespace Org.BouncyCastle.X509
 {
@@ -151,29 +152,48 @@ namespace Org.BouncyCastle.X509
 			return cert.SignatureValue.GetBytes();
 		}
 
-		public virtual void Verify(
-			AsymmetricKeyParameter publicKey)
-		{
-			if (!cert.SignatureAlgorithm.Equals(cert.ACInfo.Signature))
+        public virtual void Verify(
+            AsymmetricKeyParameter key)
+        {
+            CheckSignature(new Asn1SignatureVerifier(cert.SignatureAlgorithm, key));
+        }
+
+        /// <summary>
+        /// Verify the certificate's signature using a verifier created using the passed in verifier provider.
+        /// </summary>
+        /// <param name="verifierProvider">An appropriate provider for verifying the certificate's signature.</param>
+        /// <returns>True if the signature is valid.</returns>
+        /// <exception cref="Exception">If verifier provider is not appropriate or the certificate algorithm is invalid.</exception>
+        public virtual void Verify(
+            ISignatureVerifierProvider verifierProvider)
+        {
+            CheckSignature(verifierProvider.CreateSignatureVerifier(cert.SignatureAlgorithm));
+        }
+
+        protected virtual void CheckSignature(
+            ISignatureVerifier verifier)
+        {
+            if (!cert.SignatureAlgorithm.Equals(cert.ACInfo.Signature))
 			{
 				throw new CertificateException("Signature algorithm in certificate info not same as outer certificate");
 			}
 
-			ISigner signature = SignerUtilities.GetSigner(cert.SignatureAlgorithm.ObjectID.Id);
-
-			signature.Init(false, publicKey);
+            IStreamCalculator streamCalculator = verifier.CreateCalculator();
 
 			try
 			{
-				byte[] b = cert.ACInfo.GetEncoded();
-				signature.BlockUpdate(b, 0, b.Length);
-			}
+                byte[] b = this.cert.ACInfo.GetEncoded();
+
+                streamCalculator.Stream.Write(b, 0, b.Length);
+
+                streamCalculator.Stream.Close();
+            }
 			catch (IOException e)
 			{
 				throw new SignatureException("Exception encoding certificate info object", e);
 			}
 
-			if (!signature.VerifySignature(this.GetSignature()))
+			if (!((IVerifier)streamCalculator.GetResult()).IsVerified(this.GetSignature()))
 			{
 				throw new InvalidKeyException("Public key presented not for certificate signature");
 			}
diff --git a/crypto/src/x509/X509V2AttributeCertificateGenerator.cs b/crypto/src/x509/X509V2AttributeCertificateGenerator.cs
index 33aa40c6e..138f2ec6f 100644
--- a/crypto/src/x509/X509V2AttributeCertificateGenerator.cs
+++ b/crypto/src/x509/X509V2AttributeCertificateGenerator.cs
@@ -168,11 +168,11 @@ namespace Org.BouncyCastle.X509
 
             byte[] encoded = acInfo.GetDerEncoded();
 
-            Stream sigStream = signatureCalculator.GetSignatureUpdater();
+            IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator();
 
-            sigStream.Write(encoded, 0, encoded.Length);
+            streamCalculator.Stream.Write(encoded, 0, encoded.Length);
 
-            sigStream.Close();
+            streamCalculator.Stream.Close();
 
             Asn1EncodableVector v = new Asn1EncodableVector();
 
@@ -180,7 +180,7 @@ namespace Org.BouncyCastle.X509
 
 			try
 			{
-				v.Add(new DerBitString(signatureCalculator.Signature()));
+				v.Add(new DerBitString(((IBlockResult)streamCalculator.GetResult()).DoFinal()));
 
 				return new X509V2AttributeCertificate(AttributeCertificate.GetInstance(new DerSequence(v)));
 			}
diff --git a/crypto/src/x509/X509V2CRLGenerator.cs b/crypto/src/x509/X509V2CRLGenerator.cs
index c7295f5db..c1cc8e824 100644
--- a/crypto/src/x509/X509V2CRLGenerator.cs
+++ b/crypto/src/x509/X509V2CRLGenerator.cs
@@ -235,15 +235,15 @@ namespace Org.BouncyCastle.X509
 
             TbsCertificateList tbsCertList = GenerateCertList();
 
-            Stream sigStream = signatureCalculator.GetSignatureUpdater();
+            IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator();
 
             byte[] encoded = tbsCertList.GetDerEncoded();
 
-            sigStream.Write(encoded, 0, encoded.Length);
+            streamCalculator.Stream.Write(encoded, 0, encoded.Length);
 
-            sigStream.Close();
+            streamCalculator.Stream.Close();
 
-            return GenerateJcaObject(tbsCertList, (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails, signatureCalculator.Signature());
+            return GenerateJcaObject(tbsCertList, (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails, ((IBlockResult)streamCalculator.GetResult()).DoFinal());
         }
 
         private TbsCertificateList GenerateCertList()
diff --git a/crypto/src/x509/X509V3CertificateGenerator.cs b/crypto/src/x509/X509V3CertificateGenerator.cs
index f3bcea5f0..a22cd9943 100644
--- a/crypto/src/x509/X509V3CertificateGenerator.cs
+++ b/crypto/src/x509/X509V3CertificateGenerator.cs
@@ -314,15 +314,15 @@ namespace Org.BouncyCastle.X509
 
             TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate();
 
-			Stream sigStream = signatureCalculator.GetSignatureUpdater ();
+			IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator();
 
 			byte[] encoded = tbsCert.GetDerEncoded();
 
-			sigStream.Write (encoded, 0, encoded.Length);
+			streamCalculator.Stream.Write (encoded, 0, encoded.Length);
 
-			sigStream.Close ();
+            streamCalculator.Stream.Close ();
 
-			return GenerateJcaObject(tbsCert, (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails, signatureCalculator.Signature());
+			return GenerateJcaObject(tbsCert, (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails, ((IBlockResult)streamCalculator.GetResult()).DoFinal());
 		}
 
 		private X509Certificate GenerateJcaObject(