summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2014-03-11 13:11:44 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2014-03-11 13:11:44 +0700
commit8ad240105db29a96e12e785ac5586c52f3fce9bb (patch)
treee990918e1ab065c6966ee8380b3f98ddef419a97
parentImprove SipHashTest to cover varying update methods (diff)
downloadBouncyCastle.NET-ed25519-8ad240105db29a96e12e785ac5586c52f3fce9bb.tar.xz
Optimization (faster at all input lengths, but especially for long block-aligned inputs)
-rw-r--r--crypto/src/crypto/macs/SipHash.cs56
1 files changed, 39 insertions, 17 deletions
diff --git a/crypto/src/crypto/macs/SipHash.cs b/crypto/src/crypto/macs/SipHash.cs
index ab8b1b06b..34b0ef090 100644
--- a/crypto/src/crypto/macs/SipHash.cs
+++ b/crypto/src/crypto/macs/SipHash.cs
@@ -23,8 +23,8 @@ namespace Org.BouncyCastle.Crypto.Macs
         protected long k0, k1;
         protected long v0, v1, v2, v3, v4;
 
-        protected byte[] buf = new byte[8];
-        protected int bufPos = 0;
+        protected long m = 0;
+        protected int wordPos = 0;
         protected int wordCount = 0;
 
         /// <summary>SipHash-2-4</summary>
@@ -69,34 +69,57 @@ namespace Org.BouncyCastle.Crypto.Macs
 
         public virtual void Update(byte input)
         {
-            buf[bufPos] = input;
-            if (++bufPos == buf.Length)
+            m = (long)(((ulong)m >> 8) | ((ulong)input << 56));
+
+            if (++wordPos == 8)
             {
                 ProcessMessageWord();
-                bufPos = 0;
+                wordPos = 0;
             }
         }
 
         public virtual void BlockUpdate(byte[] input, int offset, int length)
         {
-            for (int i = 0; i < length; ++i)
+            int i = 0, fullWords = length & ~7;
+            if (wordPos == 0)
             {
-                buf[bufPos] = input[offset + i];
-                if (++bufPos == buf.Length)
+                for (; i < fullWords; i += 8)
                 {
+                    m = (long)Pack.LE_To_UInt64(input, offset + i);
                     ProcessMessageWord();
-                    bufPos = 0;
+                }
+                for (; i < length; ++i)
+                {
+                    m = (long)(((ulong)m >> 8) | ((ulong)input[offset + i] << 56));
+                }
+                wordPos = length - fullWords;
+            }
+            else
+            {
+                int bits = wordPos << 3;
+                for (; i < fullWords; i += 8)
+                {
+                    ulong n = Pack.LE_To_UInt64(input, offset + i);
+                    m = (long)(((ulong)m >> (64 - bits)) | (n << bits));
+                    ProcessMessageWord();
+                    m = (long)n;
+                }
+                for (; i < length; ++i)
+                {
+                    m = (long)(((ulong)m >> 8) | ((ulong)input[offset + i] << 56));
+
+                    if (++wordPos == 8)
+                    {
+                        ProcessMessageWord();
+                        wordPos = 0;
+                    }
                 }
             }
         }
 
         public virtual long DoFinal()
         {
-            buf[7] = (byte)((wordCount << 3) + bufPos);
-            while (bufPos < 7)
-            {
-                buf[bufPos++] = 0;
-            }
+            m = (long)(((ulong)m >> ((8 - wordPos) << 3)) | ((ulong)((wordCount << 3) + wordPos) << 56));
 
             ProcessMessageWord();
 
@@ -125,15 +148,14 @@ namespace Org.BouncyCastle.Crypto.Macs
             v2 = k0 ^ 0x6c7967656e657261L;
             v3 = k1 ^ 0x7465646279746573L;
 
-            Array.Clear(buf, 0, buf.Length);
-            bufPos = 0;
+            m = 0;
+            wordPos = 0;
             wordCount = 0;
         }
 
         protected virtual void ProcessMessageWord()
         {
             ++wordCount;
-            long m = (long)Pack.LE_To_UInt64(buf, 0);
             v3 ^= m;
             ApplySipRounds(c);
             v0 ^= m;