summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
authorDavid Hook <dgh@bouncycastle.org>2016-02-07 22:46:57 +1100
committerDavid Hook <dgh@bouncycastle.org>2016-02-07 22:46:57 +1100
commitea14fe42f35364f2785f9baf979366ed4aae6118 (patch)
treef75806b3413b68c0a4ba23ac0c40dcf42512b8bb /crypto
parentAdd bcrypt classes to mobile projects (diff)
downloadBouncyCastle.NET-ed25519-ea14fe42f35364f2785f9baf979366ed4aae6118.tar.xz
Added support for repeated requests for output to Xof.
Diffstat (limited to 'crypto')
-rw-r--r--crypto/src/crypto/IXof.cs25
-rw-r--r--crypto/src/crypto/digests/KeccakDigest.cs4
-rw-r--r--crypto/src/crypto/digests/ShakeDigest.cs16
-rw-r--r--crypto/test/src/crypto/test/ShakeDigestTest.cs44
4 files changed, 76 insertions, 13 deletions
diff --git a/crypto/src/crypto/IXof.cs b/crypto/src/crypto/IXof.cs
index e9e2253a0..f76304d48 100644
--- a/crypto/src/crypto/IXof.cs
+++ b/crypto/src/crypto/IXof.cs
@@ -9,14 +9,23 @@ namespace Org.BouncyCastle.Crypto
     public interface IXof
         : IDigest
     {
-        /**
-         * Output the results of the final calculation for this digest to outLen number of bytes.
-         *
-         * @param out output array to write the output bytes to.
-         * @param outOff offset to start writing the bytes at.
-         * @param outLen the number of output bytes requested.
-         * @return the number of bytes written
-         */
+        /// <summary>
+        /// Output the results of the final calculation for this digest to outLen number of bytes.
+        /// </summary>
+        /// <param name="output">output array to write the output bytes to.</param>
+        /// <param name="outOff">offset to start writing the bytes at.</param>
+        /// <param name="outLen">the number of output bytes requested.</param>
+        /// <returns>the number of bytes written</returns>
         int DoFinal(byte[] output, int outOff, int outLen);
+
+        /// <summary>
+        /// Start outputting the results of the final calculation for this digest. Unlike DoFinal, this method
+        /// will continue producing output until the Xof is explicitly reset, or signals otherwise.
+        /// </summary>
+        /// <param name="output">output array to write the output bytes to.</param>
+        /// <param name="outOff">offset to start writing the bytes at.</param>
+        /// <param name="outLen">the number of output bytes requested.</param>
+        /// <returns>the number of bytes written</returns>
+        int DoOutput(byte[] output, int outOff, int outLen);
     }
 }
diff --git a/crypto/src/crypto/digests/KeccakDigest.cs b/crypto/src/crypto/digests/KeccakDigest.cs
index 2d6cf393c..20aa225b8 100644
--- a/crypto/src/crypto/digests/KeccakDigest.cs
+++ b/crypto/src/crypto/digests/KeccakDigest.cs
@@ -248,11 +248,11 @@ namespace Org.BouncyCastle.Crypto.Digests
 
             if ((bitsInQueue % 8) != 0)
             {
-                throw new InvalidOperationException("attempt to absorb with odd length queue.");
+                throw new InvalidOperationException("attempt to absorb with odd length queue");
             }
             if (squeezing)
             {
-                throw new InvalidOperationException("attempt to absorb while squeezing.");
+                throw new InvalidOperationException("attempt to absorb while squeezing");
             }
 
             i = 0;
diff --git a/crypto/src/crypto/digests/ShakeDigest.cs b/crypto/src/crypto/digests/ShakeDigest.cs
index fd7d85681..a7bddccba 100644
--- a/crypto/src/crypto/digests/ShakeDigest.cs
+++ b/crypto/src/crypto/digests/ShakeDigest.cs
@@ -53,15 +53,25 @@ namespace Org.BouncyCastle.Crypto.Digests
 
         public virtual int DoFinal(byte[] output, int outOff, int outLen)
         {
-            Absorb(new byte[]{ 0x0F }, 0, 4);
-
-            Squeeze(output, outOff, ((long)outLen) * 8);
+            DoOutput(output, outOff, outLen);
 
             Reset();
 
             return outLen;
         }
 
+        public virtual int DoOutput(byte[] output, int outOff, int outLen)
+        {
+            if (!squeezing)
+            {
+                Absorb(new byte[] { 0x0F }, 0, 4);
+            }
+
+            Squeeze(output, outOff, ((long)outLen) * 8);
+
+            return outLen;
+        }
+
         /*
          * TODO Possible API change to support partial-byte suffixes.
          */
diff --git a/crypto/test/src/crypto/test/ShakeDigestTest.cs b/crypto/test/src/crypto/test/ShakeDigestTest.cs
index ef4696739..d8b2d55d6 100644
--- a/crypto/test/src/crypto/test/ShakeDigestTest.cs
+++ b/crypto/test/src/crypto/test/ShakeDigestTest.cs
@@ -199,6 +199,50 @@ namespace Org.BouncyCastle.Crypto.Tests
                 //Console.Error.WriteLine(v.Algorithm + " " + v.Bits + "-bit test vector hash mismatch");
                 //Console.Error.WriteLine(Hex.ToHexString(output).ToUpper());
             }
+
+            if (partialBits == 0)
+            {
+                d = CreateDigest(v.Algorithm);
+
+                m = v.Message;
+
+                d.BlockUpdate(m, 0, m.Length);
+                d.DoOutput(output, 0, outLen / 2);
+                d.DoOutput(output, outLen / 2, output.Length - outLen / 2);
+
+                if (!Arrays.AreEqual(expected, output))
+                {
+                    Fail(v.Algorithm + " " + v.Bits + "-bit test vector extended hash mismatch");
+                }
+
+                try
+                {
+                    d.Update((byte)0x01);
+                    Fail("no exception");
+                }
+                catch (InvalidOperationException e)
+                {
+                    if (!"attempt to absorb while squeezing".Equals(e.Message))
+                    {
+                        Fail("wrong exception");
+                    }
+                }
+
+                d = CreateDigest(v.Algorithm);
+
+                m = v.Message;
+
+                d.BlockUpdate(m, 0, m.Length);
+                d.DoOutput(output, 0, outLen / 2);
+                d.DoFinal(output, outLen / 2, output.Length - outLen / 2);
+
+                if (!Arrays.AreEqual(expected, output))
+                {
+                    Fail(v.Algorithm + " " + v.Bits + "-bit test vector extended doFinal hash mismatch");
+                }
+
+                d.Update((byte)0x01); // this should be okay as we've reset on DoFinal()
+            }
         }
 
         private void SkipUntil(StreamReader r, string header)