diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2020-04-05 19:27:29 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2020-04-05 19:27:29 +0700 |
commit | 3b56fd1d415c38933127056e3948934c2a86f650 (patch) | |
tree | 4f03fa9b533b0bfe34191efd13c558135c338357 | |
parent | Reset after wrong-length failure (diff) | |
download | BouncyCastle.NET-ed25519-3b56fd1d415c38933127056e3948934c2a86f650.tar.xz |
Keccak refactoring/performance
-rw-r--r-- | crypto/src/crypto/digests/KeccakDigest.cs | 79 | ||||
-rw-r--r-- | crypto/src/crypto/digests/SHA3Digest.cs | 2 | ||||
-rw-r--r-- | crypto/src/crypto/digests/ShakeDigest.cs | 2 |
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; } |