From ea14fe42f35364f2785f9baf979366ed4aae6118 Mon Sep 17 00:00:00 2001 From: David Hook Date: Sun, 7 Feb 2016 22:46:57 +1100 Subject: Added support for repeated requests for output to Xof. --- crypto/src/crypto/IXof.cs | 25 ++++++++++----- crypto/src/crypto/digests/KeccakDigest.cs | 4 +-- crypto/src/crypto/digests/ShakeDigest.cs | 16 ++++++++-- crypto/test/src/crypto/test/ShakeDigestTest.cs | 44 ++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 13 deletions(-) (limited to 'crypto') 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 - */ + /// + /// Output the results of the final calculation for this digest to outLen number of bytes. + /// + /// output array to write the output bytes to. + /// offset to start writing the bytes at. + /// the number of output bytes requested. + /// the number of bytes written int DoFinal(byte[] output, int outOff, int outLen); + + /// + /// 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. + /// + /// output array to write the output bytes to. + /// offset to start writing the bytes at. + /// the number of output bytes requested. + /// the number of bytes written + 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) -- cgit 1.4.1