summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2014-04-16 17:44:04 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2014-04-16 17:44:04 +0700
commit2a06b4ddeee29bc839fc5429c50c8eff3d453c85 (patch)
tree54ace1fda7422ef260ccc34d099d467344ab979a
parentAdd low-weight guard to ECKeyPairGenerator (diff)
downloadBouncyCastle.NET-ed25519-2a06b4ddeee29bc839fc5429c50c8eff3d453c85.tar.xz
Set the SecureRandom more intelligently
Change access modifiers to support subclassing
-rw-r--r--crypto/src/crypto/signers/DsaSigner.cs247
-rw-r--r--crypto/src/crypto/signers/ECDsaSigner.cs38
2 files changed, 141 insertions, 144 deletions
diff --git a/crypto/src/crypto/signers/DsaSigner.cs b/crypto/src/crypto/signers/DsaSigner.cs
index 419b1972e..fc0780a91 100644
--- a/crypto/src/crypto/signers/DsaSigner.cs
+++ b/crypto/src/crypto/signers/DsaSigner.cs
@@ -8,129 +8,126 @@ using Org.BouncyCastle.Crypto.Parameters;
 
 namespace Org.BouncyCastle.Crypto.Signers
 {
-	/**
-	 * The Digital Signature Algorithm - as described in "Handbook of Applied
-	 * Cryptography", pages 452 - 453.
-	 */
-	public class DsaSigner
-		: IDsa
-	{
-		private DsaKeyParameters key;
-		private SecureRandom random;
-
-		public string AlgorithmName
-		{
-			get { return "DSA"; }
-		}
-
-		public void Init(
-			bool				forSigning,
-			ICipherParameters	parameters)
-		{
-			if (forSigning)
-			{
-				if (parameters is ParametersWithRandom)
-				{
-					ParametersWithRandom rParam = (ParametersWithRandom)parameters;
-
-					this.random = rParam.Random;
-					parameters = rParam.Parameters;
-				}
-				else
-				{
-					this.random = new SecureRandom();
-				}
-
-				if (!(parameters is DsaPrivateKeyParameters))
-					throw new InvalidKeyException("DSA private key required for signing");
-
-				this.key = (DsaPrivateKeyParameters) parameters;
-			}
-			else
-			{
-				if (!(parameters is DsaPublicKeyParameters))
-					throw new InvalidKeyException("DSA public key required for verification");
-
-				this.key = (DsaPublicKeyParameters) parameters;
-			}
-		}
-
-		/**
-		 * Generate a signature for the given message using the key we were
-		 * initialised with. For conventional DSA the message should be a SHA-1
-		 * hash of the message of interest.
-		 *
-		 * @param message the message that will be verified later.
-		 */
-		public BigInteger[] GenerateSignature(
-			byte[] message)
-		{
-			DsaParameters parameters = key.Parameters;
-			BigInteger q = parameters.Q;
-			BigInteger m = calculateE(q, message);
-			BigInteger k;
-
-			do
-			{
-				k = new BigInteger(q.BitLength, random);
-			}
-			while (k.CompareTo(q) >= 0);
-
-			BigInteger r = parameters.G.ModPow(k, parameters.P).Mod(q);
-
-			k = k.ModInverse(q).Multiply(
-				m.Add(((DsaPrivateKeyParameters)key).X.Multiply(r)));
-
-			BigInteger s = k.Mod(q);
-
-			return new BigInteger[]{ r, s };
-		}
-
-		/**
-		 * return true if the value r and s represent a DSA signature for
-		 * the passed in message for standard DSA the message should be a
-		 * SHA-1 hash of the real message to be verified.
-		 */
-		public bool VerifySignature(
-			byte[]		message,
-			BigInteger	r,
-			BigInteger	s)
-		{
-			DsaParameters parameters = key.Parameters;
-			BigInteger q = parameters.Q;
-			BigInteger m = calculateE(q, message);
-
-			if (r.SignValue <= 0 || q.CompareTo(r) <= 0)
-			{
-				return false;
-			}
-
-			if (s.SignValue <= 0 || q.CompareTo(s) <= 0)
-			{
-				return false;
-			}
-
-			BigInteger w = s.ModInverse(q);
-
-			BigInteger u1 = m.Multiply(w).Mod(q);
-			BigInteger u2 = r.Multiply(w).Mod(q);
-
-			BigInteger p = parameters.P;
-			u1 = parameters.G.ModPow(u1, p);
-			u2 = ((DsaPublicKeyParameters)key).Y.ModPow(u2, p);
-
-			BigInteger v = u1.Multiply(u2).Mod(p).Mod(q);
-
-			return v.Equals(r);
-		}
-
-		private BigInteger calculateE(
-			BigInteger	n,
-			byte[]		message)
-		{
-			int length = System.Math.Min(message.Length, n.BitLength / 8);
-
-			return new BigInteger(1, message, 0, length);
-		}
-	}
+    /**
+     * The Digital Signature Algorithm - as described in "Handbook of Applied
+     * Cryptography", pages 452 - 453.
+     */
+    public class DsaSigner
+        : IDsa
+    {
+        protected DsaKeyParameters key = null;
+        protected SecureRandom random = null;
+
+        public virtual string AlgorithmName
+        {
+            get { return "DSA"; }
+        }
+
+        public virtual void Init(bool forSigning, ICipherParameters	parameters)
+        {
+            SecureRandom providedRandom = null;
+
+            if (forSigning)
+            {
+                if (parameters is ParametersWithRandom)
+                {
+                    ParametersWithRandom rParam = (ParametersWithRandom)parameters;
+
+                    providedRandom = rParam.Random;
+                    parameters = rParam.Parameters;
+                }
+
+                if (!(parameters is DsaPrivateKeyParameters))
+                    throw new InvalidKeyException("DSA private key required for signing");
+
+                this.key = (DsaPrivateKeyParameters)parameters;
+            }
+            else
+            {
+                if (!(parameters is DsaPublicKeyParameters))
+                    throw new InvalidKeyException("DSA public key required for verification");
+
+                this.key = (DsaPublicKeyParameters)parameters;
+            }
+
+            this.random = InitSecureRandom(forSigning, providedRandom);
+        }
+
+        /**
+         * Generate a signature for the given message using the key we were
+         * initialised with. For conventional DSA the message should be a SHA-1
+         * hash of the message of interest.
+         *
+         * @param message the message that will be verified later.
+         */
+        public virtual BigInteger[] GenerateSignature(byte[] message)
+        {
+            DsaParameters parameters = key.Parameters;
+            BigInteger q = parameters.Q;
+            BigInteger m = CalculateE(q, message);
+            BigInteger k;
+
+            do
+            {
+                k = new BigInteger(q.BitLength, random);
+            }
+            while (k.CompareTo(q) >= 0);
+
+            BigInteger r = parameters.G.ModPow(k, parameters.P).Mod(q);
+
+            k = k.ModInverse(q).Multiply(
+                m.Add(((DsaPrivateKeyParameters)key).X.Multiply(r)));
+
+            BigInteger s = k.Mod(q);
+
+            return new BigInteger[]{ r, s };
+        }
+
+        /**
+         * return true if the value r and s represent a DSA signature for
+         * the passed in message for standard DSA the message should be a
+         * SHA-1 hash of the real message to be verified.
+         */
+        public virtual bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
+        {
+            DsaParameters parameters = key.Parameters;
+            BigInteger q = parameters.Q;
+            BigInteger m = CalculateE(q, message);
+
+            if (r.SignValue <= 0 || q.CompareTo(r) <= 0)
+            {
+                return false;
+            }
+
+            if (s.SignValue <= 0 || q.CompareTo(s) <= 0)
+            {
+                return false;
+            }
+
+            BigInteger w = s.ModInverse(q);
+
+            BigInteger u1 = m.Multiply(w).Mod(q);
+            BigInteger u2 = r.Multiply(w).Mod(q);
+
+            BigInteger p = parameters.P;
+            u1 = parameters.G.ModPow(u1, p);
+            u2 = ((DsaPublicKeyParameters)key).Y.ModPow(u2, p);
+
+            BigInteger v = u1.Multiply(u2).Mod(p).Mod(q);
+
+            return v.Equals(r);
+        }
+
+        protected virtual BigInteger CalculateE(BigInteger n, byte[] message)
+        {
+            int length = System.Math.Min(message.Length, n.BitLength / 8);
+
+            return new BigInteger(1, message, 0, length);
+        }
+
+        protected virtual SecureRandom InitSecureRandom(bool needed, SecureRandom provided)
+        {
+            return !needed ? null : (provided != null) ? provided : new SecureRandom();
+        }
+    }
 }
diff --git a/crypto/src/crypto/signers/ECDsaSigner.cs b/crypto/src/crypto/signers/ECDsaSigner.cs
index 508335149..867520535 100644
--- a/crypto/src/crypto/signers/ECDsaSigner.cs
+++ b/crypto/src/crypto/signers/ECDsaSigner.cs
@@ -15,44 +15,42 @@ namespace Org.BouncyCastle.Crypto.Signers
     public class ECDsaSigner
         : IDsa
     {
-        private ECKeyParameters key;
-        private SecureRandom random;
+        protected ECKeyParameters key = null;
+        protected SecureRandom random = null;
 
-        public string AlgorithmName
+        public virtual string AlgorithmName
         {
             get { return "ECDSA"; }
         }
 
-        public void Init(
-            bool				forSigning,
-            ICipherParameters	parameters)
+        public virtual void Init(bool forSigning, ICipherParameters parameters)
         {
+            SecureRandom providedRandom = null;
+
             if (forSigning)
             {
                 if (parameters is ParametersWithRandom)
                 {
-                    ParametersWithRandom rParam = (ParametersWithRandom) parameters;
+                    ParametersWithRandom rParam = (ParametersWithRandom)parameters;
 
-                    this.random = rParam.Random;
+                    providedRandom = rParam.Random;
                     parameters = rParam.Parameters;
                 }
-                else
-                {
-                    this.random = new SecureRandom();
-                }
 
                 if (!(parameters is ECPrivateKeyParameters))
                     throw new InvalidKeyException("EC private key required for signing");
 
-                this.key = (ECPrivateKeyParameters) parameters;
+                this.key = (ECPrivateKeyParameters)parameters;
             }
             else
             {
                 if (!(parameters is ECPublicKeyParameters))
                     throw new InvalidKeyException("EC public key required for verification");
 
-                this.key = (ECPublicKeyParameters) parameters;
+                this.key = (ECPublicKeyParameters)parameters;
             }
+
+            this.random = InitSecureRandom(forSigning, providedRandom);
         }
 
         // 5.3 pg 28
@@ -63,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Signers
          *
          * @param message the message that will be verified later.
          */
-        public BigInteger[] GenerateSignature(byte[] message)
+        public virtual BigInteger[] GenerateSignature(byte[] message)
         {
             ECDomainParameters ec = key.Parameters;
             BigInteger n = ec.N;
@@ -106,10 +104,7 @@ namespace Org.BouncyCastle.Crypto.Signers
          * the passed in message (for standard DSA the message should be
          * a SHA-1 hash of the real message to be verified).
          */
-        public bool VerifySignature(
-            byte[]		message,
-            BigInteger	r,
-            BigInteger	s)
+        public virtual bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
         {
             BigInteger n = key.Parameters.N;
 
@@ -156,5 +151,10 @@ namespace Org.BouncyCastle.Crypto.Signers
         {
             return new FixedPointCombMultiplier();
         }
+
+        protected virtual SecureRandom InitSecureRandom(bool needed, SecureRandom provided)
+        {
+            return !needed ? null : (provided != null) ? provided : new SecureRandom();
+        }
     }
 }