summary refs log tree commit diff
path: root/Crypto/src/crypto/signers/DsaDigestSigner.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/crypto/signers/DsaDigestSigner.cs')
-rw-r--r--Crypto/src/crypto/signers/DsaDigestSigner.cs145
1 files changed, 145 insertions, 0 deletions
diff --git a/Crypto/src/crypto/signers/DsaDigestSigner.cs b/Crypto/src/crypto/signers/DsaDigestSigner.cs
new file mode 100644
index 000000000..aee713450
--- /dev/null
+++ b/Crypto/src/crypto/signers/DsaDigestSigner.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+	public class DsaDigestSigner
+		: ISigner
+	{
+		private readonly IDigest digest;
+		private readonly IDsa dsaSigner;
+		private bool forSigning;
+
+		public DsaDigestSigner(
+			IDsa	signer,
+			IDigest	digest)
+		{
+			this.digest = digest;
+			this.dsaSigner = signer;
+		}
+
+		public string AlgorithmName
+		{
+			get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; }
+		}
+
+		public void Init(
+			bool							forSigning,
+			ICipherParameters	parameters)
+		{
+			this.forSigning = forSigning;
+
+			AsymmetricKeyParameter k;
+
+			if (parameters is ParametersWithRandom)
+			{
+				k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters;
+			}
+			else
+			{
+				k = (AsymmetricKeyParameter)parameters;
+			}
+
+			if (forSigning && !k.IsPrivate)
+				throw new InvalidKeyException("Signing Requires Private Key.");
+
+			if (!forSigning && k.IsPrivate)
+				throw new InvalidKeyException("Verification Requires Public Key.");
+
+			Reset();
+
+			dsaSigner.Init(forSigning, parameters);
+		}
+
+		/**
+		 * update the internal digest with the byte b
+		 */
+		public void Update(
+			byte input)
+		{
+			digest.Update(input);
+		}
+
+		/**
+		 * update the internal digest with the byte array in
+		 */
+		public void BlockUpdate(
+			byte[]	input,
+			int			inOff,
+			int			length)
+		{
+			digest.BlockUpdate(input, inOff, length);
+		}
+
+		/**
+		 * Generate a signature for the message we've been loaded with using
+		 * the key we were initialised with.
+     */
+		public byte[] GenerateSignature()
+		{
+			if (!forSigning)
+				throw new InvalidOperationException("DSADigestSigner not initialised for signature generation.");
+
+			byte[] hash = new byte[digest.GetDigestSize()];
+			digest.DoFinal(hash, 0);
+
+			BigInteger[] sig = dsaSigner.GenerateSignature(hash);
+
+			return DerEncode(sig[0], sig[1]);
+		}
+
+		/// <returns>true if the internal state represents the signature described in the passed in array.</returns>
+		public bool VerifySignature(
+			byte[] signature)
+		{
+			if (forSigning)
+				throw new InvalidOperationException("DSADigestSigner not initialised for verification");
+
+			byte[] hash = new byte[digest.GetDigestSize()];
+			digest.DoFinal(hash, 0);
+
+			try
+			{
+				BigInteger[] sig = DerDecode(signature);
+				return dsaSigner.VerifySignature(hash, sig[0], sig[1]);
+			}
+			catch (IOException)
+			{
+				return false;
+			}
+		}
+
+		/// <summary>Reset the internal state</summary>
+		public void Reset()
+		{
+			digest.Reset();
+		}
+
+		private byte[] DerEncode(
+			BigInteger	r,
+			BigInteger	s)
+		{
+			return new DerSequence(new DerInteger(r), new DerInteger(s)).GetDerEncoded();
+		}
+
+		private BigInteger[] DerDecode(
+			byte[] encoding)
+		{
+			Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding);
+
+			return new BigInteger[]
+			{
+				((DerInteger) s[0]).Value,
+				((DerInteger) s[1]).Value
+			};
+		}
+	}
+}