summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2014-08-20 21:00:10 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2014-08-20 21:00:10 +0700
commitc92b9a93053b3b4f3235cdace4f9472e59a38714 (patch)
tree9de590250b43474b7b65f257f5a5e812fb0b3e47
parentAdd Times utility class (diff)
downloadBouncyCastle.NET-ed25519-c92b9a93053b3b4f3235cdace4f9472e59a38714.tar.xz
Bring RsaDigestSigner uptodate with Java API
-rw-r--r--crypto/src/crypto/signers/RsaDigestSigner.cs192
-rw-r--r--crypto/src/security/SignerUtilities.cs2
2 files changed, 92 insertions, 102 deletions
diff --git a/crypto/src/crypto/signers/RsaDigestSigner.cs b/crypto/src/crypto/signers/RsaDigestSigner.cs
index f57bfc83d..9af4e7145 100644
--- a/crypto/src/crypto/signers/RsaDigestSigner.cs
+++ b/crypto/src/crypto/signers/RsaDigestSigner.cs
@@ -19,16 +19,16 @@ using Org.BouncyCastle.Utilities;
 namespace Org.BouncyCastle.Crypto.Signers
 {
     public class RsaDigestSigner
-		: ISigner
+        : ISigner
     {
         private readonly IAsymmetricBlockCipher rsaEngine = new Pkcs1Encoding(new RsaBlindedEngine());
         private readonly AlgorithmIdentifier algId;
-		private readonly IDigest digest;
-		private bool forSigning;
+        private readonly IDigest digest;
+        private bool forSigning;
 
-		private static readonly IDictionary oidMap = Platform.CreateHashtable();
+        private static readonly IDictionary oidMap = Platform.CreateHashtable();
 
-		/// <summary>
+        /// <summary>
         /// Load oid table.
         /// </summary>
         static RsaDigestSigner()
@@ -48,37 +48,37 @@ namespace Org.BouncyCastle.Crypto.Signers
             oidMap["MD5"] = PkcsObjectIdentifiers.MD5;
         }
 
-		public RsaDigestSigner(
-			IDigest digest)
+        public RsaDigestSigner(IDigest digest)
+            :   this(digest, (DerObjectIdentifier)oidMap[digest.AlgorithmName])
         {
-            this.digest = digest;
+        }
 
-			string algName = digest.AlgorithmName;
-			if (algName.Equals("NULL"))
-			{
-				this.algId = null;
-			}
-			else
-			{
-				this.algId = new AlgorithmIdentifier(
-					(DerObjectIdentifier)oidMap[digest.AlgorithmName], DerNull.Instance);
-			}
+        public RsaDigestSigner(IDigest digest, DerObjectIdentifier digestOid)
+            :   this(digest, new AlgorithmIdentifier(digestOid, DerNull.Instance))
+        {
         }
 
-		public string AlgorithmName
+        public RsaDigestSigner(IDigest digest, AlgorithmIdentifier algId)
+        {
+            this.digest = digest;
+            this.algId = algId;
+        }
+
+        [Obsolete]
+        public string AlgorithmName
         {
             get { return digest.AlgorithmName + "withRSA"; }
         }
 
-		/**
+        /**
          * Initialise the signer for signing or verification.
          *
          * @param forSigning true if for signing, false otherwise
          * @param param necessary parameters.
          */
         public void Init(
-			bool				forSigning,
-			ICipherParameters	parameters)
+            bool				forSigning,
+            ICipherParameters	parameters)
         {
             this.forSigning = forSigning;
             AsymmetricKeyParameter k;
@@ -95,10 +95,10 @@ namespace Org.BouncyCastle.Crypto.Signers
             if (forSigning && !k.IsPrivate)
                 throw new InvalidKeyException("Signing requires private key.");
 
-			if (!forSigning && k.IsPrivate)
+            if (!forSigning && k.IsPrivate)
                 throw new InvalidKeyException("Verification requires public key.");
 
-			Reset();
+            Reset();
 
             rsaEngine.Init(forSigning, parameters);
         }
@@ -107,7 +107,7 @@ namespace Org.BouncyCastle.Crypto.Signers
          * update the internal digest with the byte b
          */
         public void Update(
-			byte input)
+            byte input)
         {
             digest.Update(input);
         }
@@ -116,9 +116,9 @@ namespace Org.BouncyCastle.Crypto.Signers
          * update the internal digest with the byte array in
          */
         public void BlockUpdate(
-			byte[]	input,
-			int		inOff,
-			int		length)
+            byte[]	input,
+            int		inOff,
+            int		length)
         {
             digest.BlockUpdate(input, inOff, length);
         }
@@ -132,79 +132,69 @@ namespace Org.BouncyCastle.Crypto.Signers
             if (!forSigning)
                 throw new InvalidOperationException("RsaDigestSigner not initialised for signature generation.");
 
-			byte[] hash = new byte[digest.GetDigestSize()];
+            byte[] hash = new byte[digest.GetDigestSize()];
             digest.DoFinal(hash, 0);
 
-			byte[] data = DerEncode(hash);
+            byte[] data = DerEncode(hash);
             return rsaEngine.ProcessBlock(data, 0, data.Length);
         }
 
-		/**
+        /**
          * return true if the internal state represents the signature described
          * in the passed in array.
          */
         public bool VerifySignature(
-			byte[] signature)
+            byte[] signature)
         {
-			if (forSigning)
-				throw new InvalidOperationException("RsaDigestSigner not initialised for verification");
-
-			byte[] hash = new byte[digest.GetDigestSize()];
-			digest.DoFinal(hash, 0);
-
-			byte[] sig;
-			byte[] expected;
-
-			try
-			{
-				sig = rsaEngine.ProcessBlock(signature, 0, signature.Length);
-				expected = DerEncode(hash);
-			}
-			catch (Exception)
-			{
-				return false;
-			}
-
-			if (sig.Length == expected.Length)
-			{
-				for (int i = 0; i < sig.Length; i++)
-				{
-					if (sig[i] != expected[i])
-					{
-						return false;
-					}
-				}
-			}
-			else if (sig.Length == expected.Length - 2)  // NULL left out
-			{
-				int sigOffset = sig.Length - hash.Length - 2;
-				int expectedOffset = expected.Length - hash.Length - 2;
-
-				expected[1] -= 2;      // adjust lengths
-				expected[3] -= 2;
-
-				for (int i = 0; i < hash.Length; i++)
-				{
-					if (sig[sigOffset + i] != expected[expectedOffset + i])  // check hash
-					{
-						return false;
-					}
-				}
-
-				for (int i = 0; i < sigOffset; i++)
-				{
-					if (sig[i] != expected[i])  // check header less NULL
-					{
-						return false;
-					}
-				}
-			}
-			else
-			{
-				return false;
-			}
-
-			return true;
+            if (forSigning)
+                throw new InvalidOperationException("RsaDigestSigner not initialised for verification");
+
+            byte[] hash = new byte[digest.GetDigestSize()];
+            digest.DoFinal(hash, 0);
+
+            byte[] sig;
+            byte[] expected;
+
+            try
+            {
+                sig = rsaEngine.ProcessBlock(signature, 0, signature.Length);
+                expected = DerEncode(hash);
+            }
+            catch (Exception)
+            {
+                return false;
+            }
+
+            if (sig.Length == expected.Length)
+            {
+                return Arrays.ConstantTimeAreEqual(sig, expected);
+            }
+            else if (sig.Length == expected.Length - 2)  // NULL left out
+            {
+                int sigOffset = sig.Length - hash.Length - 2;
+                int expectedOffset = expected.Length - hash.Length - 2;
+
+                expected[1] -= 2;      // adjust lengths
+                expected[3] -= 2;
+
+                int nonEqual = 0;
+
+                for (int i = 0; i < hash.Length; i++)
+                {
+                    nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]);
+                }
+
+                for (int i = 0; i < sigOffset; i++)
+                {
+                    nonEqual |= (sig[i] ^ expected[i]);  // check header less NULL
+                }
+
+                return nonEqual == 0;
+            }
+            else
+            {
+                return false;
+            }
         }
 
         public void Reset()
@@ -212,17 +202,17 @@ namespace Org.BouncyCastle.Crypto.Signers
             digest.Reset();
         }
 
-		private byte[] DerEncode(byte[] hash)
-		{
-			if (algId == null)
-			{
-				// For raw RSA, the DigestInfo must be prepared externally
-				return hash;
-			}
+        private byte[] DerEncode(byte[] hash)
+        {
+            if (algId == null)
+            {
+                // For raw RSA, the DigestInfo must be prepared externally
+                return hash;
+            }
 
-			DigestInfo dInfo = new DigestInfo(algId, hash);
+            DigestInfo dInfo = new DigestInfo(algId, hash);
 
-			return dInfo.GetDerEncoded();
-		}
+            return dInfo.GetDerEncoded();
+        }
     }
 }
diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs
index edae3b095..0cf113f65 100644
--- a/crypto/src/security/SignerUtilities.cs
+++ b/crypto/src/security/SignerUtilities.cs
@@ -357,7 +357,7 @@ namespace Org.BouncyCastle.Security
 
             if (mechanism.Equals("RSA"))
             {
-                return (new RsaDigestSigner(new NullDigest()));
+                return (new RsaDigestSigner(new NullDigest(), (AlgorithmIdentifier)null));
             }
             if (mechanism.Equals("MD2withRSA"))
             {