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(
|