summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2020-04-05 19:27:29 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2020-04-05 19:27:29 +0700
commit3b56fd1d415c38933127056e3948934c2a86f650 (patch)
tree4f03fa9b533b0bfe34191efd13c558135c338357
parentReset after wrong-length failure (diff)
downloadBouncyCastle.NET-ed25519-3b56fd1d415c38933127056e3948934c2a86f650.tar.xz
Keccak refactoring/performance
-rw-r--r--crypto/src/crypto/digests/KeccakDigest.cs79
-rw-r--r--crypto/src/crypto/digests/SHA3Digest.cs2
-rw-r--r--crypto/src/crypto/digests/ShakeDigest.cs2
3 files changed, 46 insertions, 37 deletions
diff --git a/crypto/src/crypto/digests/KeccakDigest.cs b/crypto/src/crypto/digests/KeccakDigest.cs
index 3cb5e8957..5db13886a 100644
--- a/crypto/src/crypto/digests/KeccakDigest.cs
+++ b/crypto/src/crypto/digests/KeccakDigest.cs
@@ -68,7 +68,7 @@ namespace Org.BouncyCastle.Crypto.Digests
 
         public virtual void Update(byte input)
         {
-            Absorb(new byte[]{ input }, 0, 1);
+            Absorb(input);
         }
 
         public virtual void BlockUpdate(byte[] input, int inOff, int len)
@@ -147,6 +147,21 @@ namespace Org.BouncyCastle.Crypto.Digests
             this.fixedOutputLength = (1600 - rate) >> 1;
         }
 
+        protected void Absorb(byte data)
+        {
+            if ((bitsInQueue & 7) != 0)
+                throw new InvalidOperationException("attempt to absorb with odd length queue");
+            if (squeezing)
+                throw new InvalidOperationException("attempt to absorb while squeezing");
+
+            dataQueue[bitsInQueue >> 3] = data;
+            if ((bitsInQueue += 8) == rate)
+            {
+                KeccakAbsorb(dataQueue, 0);
+                bitsInQueue = 0;
+            }
+        }
+
         protected void Absorb(byte[] data, int off, int len)
         {
             if ((bitsInQueue & 7) != 0)
@@ -157,35 +172,31 @@ namespace Org.BouncyCastle.Crypto.Digests
             int bytesInQueue = bitsInQueue >> 3;
             int rateBytes = rate >> 3;
 
-            int count = 0;
-            while (count < len)
+            if (len < (rateBytes - bytesInQueue))
             {
-                if (bytesInQueue == 0 && count <= (len - rateBytes))
-                {
-                    do
-                    {
-                        KeccakAbsorb(data, off + count);
-                        count += rateBytes;
-                    }
-                    while (count <= (len - rateBytes));
-                }
-                else
-                {
-                    int partialBlock = System.Math.Min(rateBytes - bytesInQueue, len - count);
-                    Array.Copy(data, off + count, dataQueue, bytesInQueue, partialBlock);
+                Array.Copy(data, off, dataQueue, bytesInQueue, len);
+                this.bitsInQueue += len << 3;
+                return;
+            }
 
-                    bytesInQueue += partialBlock;
-                    count += partialBlock;
+            int count = 0;
+            if (bytesInQueue > 0)
+            {
+                int available = rateBytes - bytesInQueue;
+                Array.Copy(data, off, dataQueue, bytesInQueue, available);
+                count += available;
+                KeccakAbsorb(dataQueue, 0);
+            }
 
-                    if (bytesInQueue == rateBytes)
-                    {
-                        KeccakAbsorb(dataQueue, 0);
-                        bytesInQueue = 0;
-                    }
-                }
+            int remaining;
+            while ((remaining = (len - count)) >= rateBytes)
+            {
+                KeccakAbsorb(data, off + count);
+                count += rateBytes;
             }
 
-            bitsInQueue = bytesInQueue << 3;
+            Array.Copy(data, off + count, dataQueue, 0, remaining);
+            this.bitsInQueue = remaining << 3;
         }
 
         protected void AbsorbBits(int data, int bits)
@@ -208,14 +219,13 @@ namespace Org.BouncyCastle.Crypto.Digests
         {
             Debug.Assert(bitsInQueue < rate);
 
-            dataQueue[bitsInQueue >> 3] |= (byte)(1U << (bitsInQueue & 7));
+            dataQueue[bitsInQueue >> 3] |= (byte)(1 << (bitsInQueue & 7));
 
             if (++bitsInQueue == rate)
             {
                 KeccakAbsorb(dataQueue, 0);
-                bitsInQueue = 0;
             }
-
+            else
             {
                 int full = bitsInQueue >> 6, partial = bitsInQueue & 63;
                 int off = 0;
@@ -229,14 +239,11 @@ namespace Org.BouncyCastle.Crypto.Digests
                     ulong mask = (1UL << partial) - 1UL;
                     state[full] ^= Pack.LE_To_UInt64(dataQueue, off) & mask;
                 }
-                state[(rate - 1) >> 6] ^= (1UL << 63);
             }
 
-            KeccakPermutation();
-
-            KeccakExtract();
-            bitsInQueue = rate;
+            state[(rate - 1) >> 6] ^= (1UL << 63);
 
+            bitsInQueue = 0;
             squeezing = true;
         }
 
@@ -254,9 +261,7 @@ namespace Org.BouncyCastle.Crypto.Digests
             {
                 if (bitsInQueue == 0)
                 {
-                    KeccakPermutation();
                     KeccakExtract();
-                    bitsInQueue = rate;
                 }
                 int partialBlock = (int)System.Math.Min((long)bitsInQueue, outputLength - i);
                 Array.Copy(dataQueue, (rate - bitsInQueue) >> 3, output, offset + (int)(i >> 3), partialBlock >> 3);
@@ -279,7 +284,11 @@ namespace Org.BouncyCastle.Crypto.Digests
 
         private void KeccakExtract()
         {
+            KeccakPermutation();
+
             Pack.UInt64_To_LE(state, 0, rate >> 6, dataQueue, 0);
+
+            this.bitsInQueue = rate;
         }
 
         private void KeccakPermutation()
diff --git a/crypto/src/crypto/digests/SHA3Digest.cs b/crypto/src/crypto/digests/SHA3Digest.cs
index 4683af5b3..3dc63a6ed 100644
--- a/crypto/src/crypto/digests/SHA3Digest.cs
+++ b/crypto/src/crypto/digests/SHA3Digest.cs
@@ -69,7 +69,7 @@ namespace Org.BouncyCastle.Crypto.Digests
 
             if (finalBits >= 8)
             {
-                Absorb(new byte[]{ (byte)finalInput }, 0, 1);
+                Absorb((byte)finalInput);
                 finalBits -= 8;
                 finalInput >>= 8;
             }
diff --git a/crypto/src/crypto/digests/ShakeDigest.cs b/crypto/src/crypto/digests/ShakeDigest.cs
index e58452c36..c913ce08b 100644
--- a/crypto/src/crypto/digests/ShakeDigest.cs
+++ b/crypto/src/crypto/digests/ShakeDigest.cs
@@ -94,7 +94,7 @@ namespace Org.BouncyCastle.Crypto.Digests
 
             if (finalBits >= 8)
             {
-                Absorb(new byte[]{ (byte)finalInput }, 0, 1);
+                Absorb((byte)finalInput);
                 finalBits -= 8;
                 finalInput >>= 8;
             }