From 44ccb96f7e859ee1f07d3ca032c59c88b92b09b4 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 10 Oct 2022 23:08:07 +0700 Subject: Refactor Haraka digests --- crypto/src/crypto/digests/Haraka256Digest.cs | 319 +++++++++---------- crypto/src/crypto/digests/Haraka512Digest.cs | 441 ++++++++++++--------------- crypto/src/crypto/digests/HarakaBase.cs | 183 ++++++----- 3 files changed, 439 insertions(+), 504 deletions(-) diff --git a/crypto/src/crypto/digests/Haraka256Digest.cs b/crypto/src/crypto/digests/Haraka256Digest.cs index 27aea9b29..2507125b2 100644 --- a/crypto/src/crypto/digests/Haraka256Digest.cs +++ b/crypto/src/crypto/digests/Haraka256Digest.cs @@ -1,231 +1,80 @@ using System; - namespace Org.BouncyCastle.Crypto.Digests { - public class Haraka256Digest : HarakaBase + public sealed class Haraka256Digest + : HarakaBase { - private static readonly byte[][] RC = new byte[][]{ - new byte[]{(byte)0x06, (byte)0x84, (byte)0x70, (byte)0x4c, (byte)0xe6, (byte)0x20, (byte)0xc0, (byte)0x0a, (byte)0xb2, (byte)0xc5, (byte)0xfe, (byte)0xf0, (byte)0x75, (byte)0x81, (byte)0x7b, (byte)0x9d}, - new byte[]{(byte)0x8b, (byte)0x66, (byte)0xb4, (byte)0xe1, (byte)0x88, (byte)0xf3, (byte)0xa0, (byte)0x6b, (byte)0x64, (byte)0x0f, (byte)0x6b, (byte)0xa4, (byte)0x2f, (byte)0x08, (byte)0xf7, (byte)0x17}, - new byte[]{(byte)0x34, (byte)0x02, (byte)0xde, (byte)0x2d, (byte)0x53, (byte)0xf2, (byte)0x84, (byte)0x98, (byte)0xcf, (byte)0x02, (byte)0x9d, (byte)0x60, (byte)0x9f, (byte)0x02, (byte)0x91, (byte)0x14}, - new byte[]{(byte)0x0e, (byte)0xd6, (byte)0xea, (byte)0xe6, (byte)0x2e, (byte)0x7b, (byte)0x4f, (byte)0x08, (byte)0xbb, (byte)0xf3, (byte)0xbc, (byte)0xaf, (byte)0xfd, (byte)0x5b, (byte)0x4f, (byte)0x79}, - new byte[]{(byte)0xcb, (byte)0xcf, (byte)0xb0, (byte)0xcb, (byte)0x48, (byte)0x72, (byte)0x44, (byte)0x8b, (byte)0x79, (byte)0xee, (byte)0xcd, (byte)0x1c, (byte)0xbe, (byte)0x39, (byte)0x70, (byte)0x44}, - new byte[]{(byte)0x7e, (byte)0xea, (byte)0xcd, (byte)0xee, (byte)0x6e, (byte)0x90, (byte)0x32, (byte)0xb7, (byte)0x8d, (byte)0x53, (byte)0x35, (byte)0xed, (byte)0x2b, (byte)0x8a, (byte)0x05, (byte)0x7b}, - new byte[]{(byte)0x67, (byte)0xc2, (byte)0x8f, (byte)0x43, (byte)0x5e, (byte)0x2e, (byte)0x7c, (byte)0xd0, (byte)0xe2, (byte)0x41, (byte)0x27, (byte)0x61, (byte)0xda, (byte)0x4f, (byte)0xef, (byte)0x1b}, - new byte[]{(byte)0x29, (byte)0x24, (byte)0xd9, (byte)0xb0, (byte)0xaf, (byte)0xca, (byte)0xcc, (byte)0x07, (byte)0x67, (byte)0x5f, (byte)0xfd, (byte)0xe2, (byte)0x1f, (byte)0xc7, (byte)0x0b, (byte)0x3b}, - new byte[]{(byte)0xab, (byte)0x4d, (byte)0x63, (byte)0xf1, (byte)0xe6, (byte)0x86, (byte)0x7f, (byte)0xe9, (byte)0xec, (byte)0xdb, (byte)0x8f, (byte)0xca, (byte)0xb9, (byte)0xd4, (byte)0x65, (byte)0xee}, - new byte[]{(byte)0x1c, (byte)0x30, (byte)0xbf, (byte)0x84, (byte)0xd4, (byte)0xb7, (byte)0xcd, (byte)0x64, (byte)0x5b, (byte)0x2a, (byte)0x40, (byte)0x4f, (byte)0xad, (byte)0x03, (byte)0x7e, (byte)0x33}, - new byte[]{(byte)0xb2, (byte)0xcc, (byte)0x0b, (byte)0xb9, (byte)0x94, (byte)0x17, (byte)0x23, (byte)0xbf, (byte)0x69, (byte)0x02, (byte)0x8b, (byte)0x2e, (byte)0x8d, (byte)0xf6, (byte)0x98, (byte)0x00}, - new byte[]{(byte)0xfa, (byte)0x04, (byte)0x78, (byte)0xa6, (byte)0xde, (byte)0x6f, (byte)0x55, (byte)0x72, (byte)0x4a, (byte)0xaa, (byte)0x9e, (byte)0xc8, (byte)0x5c, (byte)0x9d, (byte)0x2d, (byte)0x8a}, - new byte[]{(byte)0xdf, (byte)0xb4, (byte)0x9f, (byte)0x2b, (byte)0x6b, (byte)0x77, (byte)0x2a, (byte)0x12, (byte)0x0e, (byte)0xfa, (byte)0x4f, (byte)0x2e, (byte)0x29, (byte)0x12, (byte)0x9f, (byte)0xd4}, - new byte[]{(byte)0x1e, (byte)0xa1, (byte)0x03, (byte)0x44, (byte)0xf4, (byte)0x49, (byte)0xa2, (byte)0x36, (byte)0x32, (byte)0xd6, (byte)0x11, (byte)0xae, (byte)0xbb, (byte)0x6a, (byte)0x12, (byte)0xee}, - new byte[]{(byte)0xaf, (byte)0x04, (byte)0x49, (byte)0x88, (byte)0x4b, (byte)0x05, (byte)0x00, (byte)0x84, (byte)0x5f, (byte)0x96, (byte)0x00, (byte)0xc9, (byte)0x9c, (byte)0xa8, (byte)0xec, (byte)0xa6}, - new byte[]{(byte)0x21, (byte)0x02, (byte)0x5e, (byte)0xd8, (byte)0x9d, (byte)0x19, (byte)0x9c, (byte)0x4f, (byte)0x78, (byte)0xa2, (byte)0xc7, (byte)0xe3, (byte)0x27, (byte)0xe5, (byte)0x93, (byte)0xec}, - new byte[]{(byte)0xbf, (byte)0x3a, (byte)0xaa, (byte)0xf8, (byte)0xa7, (byte)0x59, (byte)0xc9, (byte)0xb7, (byte)0xb9, (byte)0x28, (byte)0x2e, (byte)0xcd, (byte)0x82, (byte)0xd4, (byte)0x01, (byte)0x73}, - new byte[]{(byte)0x62, (byte)0x60, (byte)0x70, (byte)0x0d, (byte)0x61, (byte)0x86, (byte)0xb0, (byte)0x17, (byte)0x37, (byte)0xf2, (byte)0xef, (byte)0xd9, (byte)0x10, (byte)0x30, (byte)0x7d, (byte)0x6b}, - new byte[]{(byte)0x5a, (byte)0xca, (byte)0x45, (byte)0xc2, (byte)0x21, (byte)0x30, (byte)0x04, (byte)0x43, (byte)0x81, (byte)0xc2, (byte)0x91, (byte)0x53, (byte)0xf6, (byte)0xfc, (byte)0x9a, (byte)0xc6}, - new byte[]{(byte)0x92, (byte)0x23, (byte)0x97, (byte)0x3c, (byte)0x22, (byte)0x6b, (byte)0x68, (byte)0xbb, (byte)0x2c, (byte)0xaf, (byte)0x92, (byte)0xe8, (byte)0x36, (byte)0xd1, (byte)0x94, (byte)0x3a} - }; - private readonly byte[] buffer; - private int off; - private void mix256(byte[][] s1, byte[][] s2) - { - Array.Copy(s1[0], 0, s2[0], 0, 4); - Array.Copy(s1[1], 0, s2[0], 4, 4); - Array.Copy(s1[0], 4, s2[0], 8, 4); - Array.Copy(s1[1], 4, s2[0], 12, 4); - - Array.Copy(s1[0], 8, s2[1], 0, 4); - Array.Copy(s1[1], 8, s2[1], 4, 4); - Array.Copy(s1[0], 12, s2[1], 8, 4); - Array.Copy(s1[1], 12, s2[1], 12, 4); - } - - private int haraka256256(byte[] msg, byte[] output, int outOff) - { - byte[][] s1 = new byte[2][]; - s1[0] = new byte[16]; - s1[1] = new byte[16]; - byte[][] s2 = new byte[2][]; - s2[0] = new byte[16]; - s2[1] = new byte[16]; - - Array.Copy(msg, 0, s1[0], 0, 16); - Array.Copy(msg, 16, s1[1], 0, 16); - - s1[0] = aesEnc(s1[0], RC[0]); - s1[1] = aesEnc(s1[1], RC[1]); - s1[0] = aesEnc(s1[0], RC[2]); - s1[1] = aesEnc(s1[1], RC[3]); - mix256(s1, s2); - - s1[0] = aesEnc(s2[0], RC[4]); - s1[1] = aesEnc(s2[1], RC[5]); - s1[0] = aesEnc(s1[0], RC[6]); - s1[1] = aesEnc(s1[1], RC[7]); - mix256(s1, s2); - - s1[0] = aesEnc(s2[0], RC[8]); - s1[1] = aesEnc(s2[1], RC[9]); - s1[0] = aesEnc(s1[0], RC[10]); - s1[1] = aesEnc(s1[1], RC[11]); - mix256(s1, s2); - - s1[0] = aesEnc(s2[0], RC[12]); - s1[1] = aesEnc(s2[1], RC[13]); - s1[0] = aesEnc(s1[0], RC[14]); - s1[1] = aesEnc(s1[1], RC[15]); - mix256(s1, s2); - - s1[0] = aesEnc(s2[0], RC[16]); - s1[1] = aesEnc(s2[1], RC[17]); - s1[0] = aesEnc(s1[0], RC[18]); - s1[1] = aesEnc(s1[1], RC[19]); - mix256(s1, s2); - - s1[0] = Xor(s2[0], msg, 0); - s1[1] = Xor(s2[1], msg, 16); - - Array.Copy(s1[0], 0, output, outOff, 16); - Array.Copy(s1[1], 0, output, outOff + 16, 16); - - return DIGEST_SIZE; - } - -#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - private int haraka256256(byte[] msg, Span output) - { - byte[][] s1 = new byte[2][]; - s1[0] = new byte[16]; - s1[1] = new byte[16]; - byte[][] s2 = new byte[2][]; - s2[0] = new byte[16]; - s2[1] = new byte[16]; - - Array.Copy(msg, 0, s1[0], 0, 16); - Array.Copy(msg, 16, s1[1], 0, 16); - - s1[0] = aesEnc(s1[0], RC[0]); - s1[1] = aesEnc(s1[1], RC[1]); - s1[0] = aesEnc(s1[0], RC[2]); - s1[1] = aesEnc(s1[1], RC[3]); - mix256(s1, s2); - - s1[0] = aesEnc(s2[0], RC[4]); - s1[1] = aesEnc(s2[1], RC[5]); - s1[0] = aesEnc(s1[0], RC[6]); - s1[1] = aesEnc(s1[1], RC[7]); - mix256(s1, s2); - - s1[0] = aesEnc(s2[0], RC[8]); - s1[1] = aesEnc(s2[1], RC[9]); - s1[0] = aesEnc(s1[0], RC[10]); - s1[1] = aesEnc(s1[1], RC[11]); - mix256(s1, s2); - - s1[0] = aesEnc(s2[0], RC[12]); - s1[1] = aesEnc(s2[1], RC[13]); - s1[0] = aesEnc(s1[0], RC[14]); - s1[1] = aesEnc(s1[1], RC[15]); - mix256(s1, s2); - - s1[0] = aesEnc(s2[0], RC[16]); - s1[1] = aesEnc(s2[1], RC[17]); - s1[0] = aesEnc(s1[0], RC[18]); - s1[1] = aesEnc(s1[1], RC[19]); - mix256(s1, s2); - - s1[0] = Xor(s2[0], msg, 0); - s1[1] = Xor(s2[1], msg, 16); - - s1[0].AsSpan(0, 16).CopyTo(output); - s1[1].AsSpan(0, 16).CopyTo(output[16..]); - - return DIGEST_SIZE; - } -#endif + private readonly byte[] m_buf; + private int m_bufPos; public Haraka256Digest() { - this.buffer = new byte[32]; - } - - public Haraka256Digest(Haraka256Digest digest) - { - this.buffer = (byte[]) digest.buffer.Clone(); - this.off = digest.off; + m_buf = new byte[32]; + m_bufPos = 0; } public override string AlgorithmName => "Haraka-256"; + public override int GetByteLength() => 32; + public override void Update(byte input) { - if (off + 1 > 32) - { + if (m_bufPos > 32 - 1) throw new ArgumentException("total input cannot be more than 32 bytes"); - } - buffer[off++] = input; + m_buf[m_bufPos++] = input; } public override void BlockUpdate(byte[] input, int inOff, int len) { - if (off + len > 32) - { + if (m_bufPos > 32 - len) throw new ArgumentException("total input cannot be more than 32 bytes"); - } - Array.Copy(input, inOff, buffer, off, len); - off += len; + Array.Copy(input, inOff, m_buf, m_bufPos, len); + m_bufPos += len; } #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER public override void BlockUpdate(ReadOnlySpan input) { - if (off + input.Length > 32) - { + if (m_bufPos > 32 - input.Length) throw new ArgumentException("total input cannot be more than 32 bytes"); - } - input.CopyTo(buffer.AsSpan(off)); - off += input.Length; + input.CopyTo(m_buf.AsSpan(m_bufPos)); + m_bufPos += input.Length; } #endif public override int DoFinal(byte[] output, int outOff) { - if (off != 32) - { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return DoFinal(output.AsSpan(outOff)); +#else + if (m_bufPos != 32) throw new ArgumentException("input must be exactly 32 bytes"); - } if (output.Length - outOff < 32) - { throw new ArgumentException("output too short to receive digest"); - } - int rv = haraka256256(buffer, output, outOff); + int rv = Haraka256256(m_buf, output, outOff); Reset(); return rv; +#endif } #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER public override int DoFinal(Span output) { - if (off != 32) - { + if (m_bufPos != 32) throw new ArgumentException("input must be exactly 32 bytes"); - } if (output.Length < 32) - { throw new ArgumentException("output too short to receive digest"); - } - int rv = haraka256256(buffer, output); + int rv = Haraka256256(m_buf, output); Reset(); @@ -235,8 +84,122 @@ namespace Org.BouncyCastle.Crypto.Digests public override void Reset() { - off = 0; - Array.Clear(buffer, 0, 32); + m_bufPos = 0; + Array.Clear(m_buf, 0, 32); + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + private static int Haraka256256(ReadOnlySpan msg, Span output) + { + byte[][] s1 = new byte[2][]; + s1[0] = new byte[16]; + s1[1] = new byte[16]; + byte[][] s2 = new byte[2][]; + s2[0] = new byte[16]; + s2[1] = new byte[16]; + + msg[ ..16].CopyTo(s1[0]); + msg[16..32].CopyTo(s1[1]); + + s1[0] = AesEnc(s1[0], RC[0]); + s1[1] = AesEnc(s1[1], RC[1]); + s1[0] = AesEnc(s1[0], RC[2]); + s1[1] = AesEnc(s1[1], RC[3]); + Mix256(s1, s2); + + s1[0] = AesEnc(s2[0], RC[4]); + s1[1] = AesEnc(s2[1], RC[5]); + s1[0] = AesEnc(s1[0], RC[6]); + s1[1] = AesEnc(s1[1], RC[7]); + Mix256(s1, s2); + + s1[0] = AesEnc(s2[0], RC[8]); + s1[1] = AesEnc(s2[1], RC[9]); + s1[0] = AesEnc(s1[0], RC[10]); + s1[1] = AesEnc(s1[1], RC[11]); + Mix256(s1, s2); + + s1[0] = AesEnc(s2[0], RC[12]); + s1[1] = AesEnc(s2[1], RC[13]); + s1[0] = AesEnc(s1[0], RC[14]); + s1[1] = AesEnc(s1[1], RC[15]); + Mix256(s1, s2); + + s1[0] = AesEnc(s2[0], RC[16]); + s1[1] = AesEnc(s2[1], RC[17]); + s1[0] = AesEnc(s1[0], RC[18]); + s1[1] = AesEnc(s1[1], RC[19]); + Mix256(s1, s2); + + Xor(s2[0], msg , output[ ..16]); + Xor(s2[1], msg[16..], output[16..32]); + + return DIGEST_SIZE; + } +#else + private static int Haraka256256(byte[] msg, byte[] output, int outOff) + { + byte[][] s1 = new byte[2][]; + s1[0] = new byte[16]; + s1[1] = new byte[16]; + byte[][] s2 = new byte[2][]; + s2[0] = new byte[16]; + s2[1] = new byte[16]; + + Array.Copy(msg, 0, s1[0], 0, 16); + Array.Copy(msg, 16, s1[1], 0, 16); + + s1[0] = AesEnc(s1[0], RC[0]); + s1[1] = AesEnc(s1[1], RC[1]); + s1[0] = AesEnc(s1[0], RC[2]); + s1[1] = AesEnc(s1[1], RC[3]); + Mix256(s1, s2); + + s1[0] = AesEnc(s2[0], RC[4]); + s1[1] = AesEnc(s2[1], RC[5]); + s1[0] = AesEnc(s1[0], RC[6]); + s1[1] = AesEnc(s1[1], RC[7]); + Mix256(s1, s2); + + s1[0] = AesEnc(s2[0], RC[8]); + s1[1] = AesEnc(s2[1], RC[9]); + s1[0] = AesEnc(s1[0], RC[10]); + s1[1] = AesEnc(s1[1], RC[11]); + Mix256(s1, s2); + + s1[0] = AesEnc(s2[0], RC[12]); + s1[1] = AesEnc(s2[1], RC[13]); + s1[0] = AesEnc(s1[0], RC[14]); + s1[1] = AesEnc(s1[1], RC[15]); + Mix256(s1, s2); + + s1[0] = AesEnc(s2[0], RC[16]); + s1[1] = AesEnc(s2[1], RC[17]); + s1[0] = AesEnc(s1[0], RC[18]); + s1[1] = AesEnc(s1[1], RC[19]); + Mix256(s1, s2); + + s1[0] = Xor(s2[0], msg, 0); + s1[1] = Xor(s2[1], msg, 16); + + Array.Copy(s1[0], 0, output, outOff , 16); + Array.Copy(s1[1], 0, output, outOff + 16, 16); + + return DIGEST_SIZE; + } +#endif + + private static void Mix256(byte[][] s1, byte[][] s2) + { + Array.Copy(s1[0], 0, s2[0], 0, 4); + Array.Copy(s1[1], 0, s2[0], 4, 4); + Array.Copy(s1[0], 4, s2[0], 8, 4); + Array.Copy(s1[1], 4, s2[0], 12, 4); + + Array.Copy(s1[0], 8, s2[1], 0, 4); + Array.Copy(s1[1], 8, s2[1], 4, 4); + Array.Copy(s1[0], 12, s2[1], 8, 4); + Array.Copy(s1[1], 12, s2[1], 12, 4); } } -} \ No newline at end of file +} diff --git a/crypto/src/crypto/digests/Haraka512Digest.cs b/crypto/src/crypto/digests/Haraka512Digest.cs index 0faeae710..540ab6446 100644 --- a/crypto/src/crypto/digests/Haraka512Digest.cs +++ b/crypto/src/crypto/digests/Haraka512Digest.cs @@ -1,92 +1,95 @@ using System; -using Org.BouncyCastle.Utilities; - namespace Org.BouncyCastle.Crypto.Digests { - public class Haraka512Digest : HarakaBase + public sealed class Haraka512Digest + : HarakaBase { - private static readonly byte[][] RC = new byte[][]{ - new byte[]{(byte)0x06, (byte)0x84, (byte)0x70, (byte)0x4c, (byte)0xe6, (byte)0x20, (byte)0xc0, (byte)0x0a, (byte)0xb2, (byte)0xc5, (byte)0xfe, (byte)0xf0, (byte)0x75, (byte)0x81, (byte)0x7b, (byte)0x9d}, - new byte[]{(byte)0x8b, (byte)0x66, (byte)0xb4, (byte)0xe1, (byte)0x88, (byte)0xf3, (byte)0xa0, (byte)0x6b, (byte)0x64, (byte)0x0f, (byte)0x6b, (byte)0xa4, (byte)0x2f, (byte)0x08, (byte)0xf7, (byte)0x17}, - new byte[]{(byte)0x34, (byte)0x02, (byte)0xde, (byte)0x2d, (byte)0x53, (byte)0xf2, (byte)0x84, (byte)0x98, (byte)0xcf, (byte)0x02, (byte)0x9d, (byte)0x60, (byte)0x9f, (byte)0x02, (byte)0x91, (byte)0x14}, - new byte[]{(byte)0x0e, (byte)0xd6, (byte)0xea, (byte)0xe6, (byte)0x2e, (byte)0x7b, (byte)0x4f, (byte)0x08, (byte)0xbb, (byte)0xf3, (byte)0xbc, (byte)0xaf, (byte)0xfd, (byte)0x5b, (byte)0x4f, (byte)0x79}, - new byte[]{(byte)0xcb, (byte)0xcf, (byte)0xb0, (byte)0xcb, (byte)0x48, (byte)0x72, (byte)0x44, (byte)0x8b, (byte)0x79, (byte)0xee, (byte)0xcd, (byte)0x1c, (byte)0xbe, (byte)0x39, (byte)0x70, (byte)0x44}, - new byte[]{(byte)0x7e, (byte)0xea, (byte)0xcd, (byte)0xee, (byte)0x6e, (byte)0x90, (byte)0x32, (byte)0xb7, (byte)0x8d, (byte)0x53, (byte)0x35, (byte)0xed, (byte)0x2b, (byte)0x8a, (byte)0x05, (byte)0x7b}, - new byte[]{(byte)0x67, (byte)0xc2, (byte)0x8f, (byte)0x43, (byte)0x5e, (byte)0x2e, (byte)0x7c, (byte)0xd0, (byte)0xe2, (byte)0x41, (byte)0x27, (byte)0x61, (byte)0xda, (byte)0x4f, (byte)0xef, (byte)0x1b}, - new byte[]{(byte)0x29, (byte)0x24, (byte)0xd9, (byte)0xb0, (byte)0xaf, (byte)0xca, (byte)0xcc, (byte)0x07, (byte)0x67, (byte)0x5f, (byte)0xfd, (byte)0xe2, (byte)0x1f, (byte)0xc7, (byte)0x0b, (byte)0x3b}, - new byte[]{(byte)0xab, (byte)0x4d, (byte)0x63, (byte)0xf1, (byte)0xe6, (byte)0x86, (byte)0x7f, (byte)0xe9, (byte)0xec, (byte)0xdb, (byte)0x8f, (byte)0xca, (byte)0xb9, (byte)0xd4, (byte)0x65, (byte)0xee}, - new byte[]{(byte)0x1c, (byte)0x30, (byte)0xbf, (byte)0x84, (byte)0xd4, (byte)0xb7, (byte)0xcd, (byte)0x64, (byte)0x5b, (byte)0x2a, (byte)0x40, (byte)0x4f, (byte)0xad, (byte)0x03, (byte)0x7e, (byte)0x33}, - new byte[]{(byte)0xb2, (byte)0xcc, (byte)0x0b, (byte)0xb9, (byte)0x94, (byte)0x17, (byte)0x23, (byte)0xbf, (byte)0x69, (byte)0x02, (byte)0x8b, (byte)0x2e, (byte)0x8d, (byte)0xf6, (byte)0x98, (byte)0x00}, - new byte[]{(byte)0xfa, (byte)0x04, (byte)0x78, (byte)0xa6, (byte)0xde, (byte)0x6f, (byte)0x55, (byte)0x72, (byte)0x4a, (byte)0xaa, (byte)0x9e, (byte)0xc8, (byte)0x5c, (byte)0x9d, (byte)0x2d, (byte)0x8a}, - new byte[]{(byte)0xdf, (byte)0xb4, (byte)0x9f, (byte)0x2b, (byte)0x6b, (byte)0x77, (byte)0x2a, (byte)0x12, (byte)0x0e, (byte)0xfa, (byte)0x4f, (byte)0x2e, (byte)0x29, (byte)0x12, (byte)0x9f, (byte)0xd4}, - new byte[]{(byte)0x1e, (byte)0xa1, (byte)0x03, (byte)0x44, (byte)0xf4, (byte)0x49, (byte)0xa2, (byte)0x36, (byte)0x32, (byte)0xd6, (byte)0x11, (byte)0xae, (byte)0xbb, (byte)0x6a, (byte)0x12, (byte)0xee}, - new byte[]{(byte)0xaf, (byte)0x04, (byte)0x49, (byte)0x88, (byte)0x4b, (byte)0x05, (byte)0x00, (byte)0x84, (byte)0x5f, (byte)0x96, (byte)0x00, (byte)0xc9, (byte)0x9c, (byte)0xa8, (byte)0xec, (byte)0xa6}, - new byte[]{(byte)0x21, (byte)0x02, (byte)0x5e, (byte)0xd8, (byte)0x9d, (byte)0x19, (byte)0x9c, (byte)0x4f, (byte)0x78, (byte)0xa2, (byte)0xc7, (byte)0xe3, (byte)0x27, (byte)0xe5, (byte)0x93, (byte)0xec}, - new byte[]{(byte)0xbf, (byte)0x3a, (byte)0xaa, (byte)0xf8, (byte)0xa7, (byte)0x59, (byte)0xc9, (byte)0xb7, (byte)0xb9, (byte)0x28, (byte)0x2e, (byte)0xcd, (byte)0x82, (byte)0xd4, (byte)0x01, (byte)0x73}, - new byte[]{(byte)0x62, (byte)0x60, (byte)0x70, (byte)0x0d, (byte)0x61, (byte)0x86, (byte)0xb0, (byte)0x17, (byte)0x37, (byte)0xf2, (byte)0xef, (byte)0xd9, (byte)0x10, (byte)0x30, (byte)0x7d, (byte)0x6b}, - new byte[]{(byte)0x5a, (byte)0xca, (byte)0x45, (byte)0xc2, (byte)0x21, (byte)0x30, (byte)0x04, (byte)0x43, (byte)0x81, (byte)0xc2, (byte)0x91, (byte)0x53, (byte)0xf6, (byte)0xfc, (byte)0x9a, (byte)0xc6}, - new byte[]{(byte)0x92, (byte)0x23, (byte)0x97, (byte)0x3c, (byte)0x22, (byte)0x6b, (byte)0x68, (byte)0xbb, (byte)0x2c, (byte)0xaf, (byte)0x92, (byte)0xe8, (byte)0x36, (byte)0xd1, (byte)0x94, (byte)0x3a}, - new byte[]{(byte)0xd3, (byte)0xbf, (byte)0x92, (byte)0x38, (byte)0x22, (byte)0x58, (byte)0x86, (byte)0xeb, (byte)0x6c, (byte)0xba, (byte)0xb9, (byte)0x58, (byte)0xe5, (byte)0x10, (byte)0x71, (byte)0xb4}, - new byte[]{(byte)0xdb, (byte)0x86, (byte)0x3c, (byte)0xe5, (byte)0xae, (byte)0xf0, (byte)0xc6, (byte)0x77, (byte)0x93, (byte)0x3d, (byte)0xfd, (byte)0xdd, (byte)0x24, (byte)0xe1, (byte)0x12, (byte)0x8d}, - new byte[]{(byte)0xbb, (byte)0x60, (byte)0x62, (byte)0x68, (byte)0xff, (byte)0xeb, (byte)0xa0, (byte)0x9c, (byte)0x83, (byte)0xe4, (byte)0x8d, (byte)0xe3, (byte)0xcb, (byte)0x22, (byte)0x12, (byte)0xb1}, - new byte[]{(byte)0x73, (byte)0x4b, (byte)0xd3, (byte)0xdc, (byte)0xe2, (byte)0xe4, (byte)0xd1, (byte)0x9c, (byte)0x2d, (byte)0xb9, (byte)0x1a, (byte)0x4e, (byte)0xc7, (byte)0x2b, (byte)0xf7, (byte)0x7d}, - new byte[]{(byte)0x43, (byte)0xbb, (byte)0x47, (byte)0xc3, (byte)0x61, (byte)0x30, (byte)0x1b, (byte)0x43, (byte)0x4b, (byte)0x14, (byte)0x15, (byte)0xc4, (byte)0x2c, (byte)0xb3, (byte)0x92, (byte)0x4e}, - new byte[]{(byte)0xdb, (byte)0xa7, (byte)0x75, (byte)0xa8, (byte)0xe7, (byte)0x07, (byte)0xef, (byte)0xf6, (byte)0x03, (byte)0xb2, (byte)0x31, (byte)0xdd, (byte)0x16, (byte)0xeb, (byte)0x68, (byte)0x99}, - new byte[]{(byte)0x6d, (byte)0xf3, (byte)0x61, (byte)0x4b, (byte)0x3c, (byte)0x75, (byte)0x59, (byte)0x77, (byte)0x8e, (byte)0x5e, (byte)0x23, (byte)0x02, (byte)0x7e, (byte)0xca, (byte)0x47, (byte)0x2c}, - new byte[]{(byte)0xcd, (byte)0xa7, (byte)0x5a, (byte)0x17, (byte)0xd6, (byte)0xde, (byte)0x7d, (byte)0x77, (byte)0x6d, (byte)0x1b, (byte)0xe5, (byte)0xb9, (byte)0xb8, (byte)0x86, (byte)0x17, (byte)0xf9}, - new byte[]{(byte)0xec, (byte)0x6b, (byte)0x43, (byte)0xf0, (byte)0x6b, (byte)0xa8, (byte)0xe9, (byte)0xaa, (byte)0x9d, (byte)0x6c, (byte)0x06, (byte)0x9d, (byte)0xa9, (byte)0x46, (byte)0xee, (byte)0x5d}, - new byte[]{(byte)0xcb, (byte)0x1e, (byte)0x69, (byte)0x50, (byte)0xf9, (byte)0x57, (byte)0x33, (byte)0x2b, (byte)0xa2, (byte)0x53, (byte)0x11, (byte)0x59, (byte)0x3b, (byte)0xf3, (byte)0x27, (byte)0xc1}, - new byte[]{(byte)0x2c, (byte)0xee, (byte)0x0c, (byte)0x75, (byte)0x00, (byte)0xda, (byte)0x61, (byte)0x9c, (byte)0xe4, (byte)0xed, (byte)0x03, (byte)0x53, (byte)0x60, (byte)0x0e, (byte)0xd0, (byte)0xd9}, - new byte[]{(byte)0xf0, (byte)0xb1, (byte)0xa5, (byte)0xa1, (byte)0x96, (byte)0xe9, (byte)0x0c, (byte)0xab, (byte)0x80, (byte)0xbb, (byte)0xba, (byte)0xbc, (byte)0x63, (byte)0xa4, (byte)0xa3, (byte)0x50}, - new byte[]{(byte)0xae, (byte)0x3d, (byte)0xb1, (byte)0x02, (byte)0x5e, (byte)0x96, (byte)0x29, (byte)0x88, (byte)0xab, (byte)0x0d, (byte)0xde, (byte)0x30, (byte)0x93, (byte)0x8d, (byte)0xca, (byte)0x39}, - new byte[]{(byte)0x17, (byte)0xbb, (byte)0x8f, (byte)0x38, (byte)0xd5, (byte)0x54, (byte)0xa4, (byte)0x0b, (byte)0x88, (byte)0x14, (byte)0xf3, (byte)0xa8, (byte)0x2e, (byte)0x75, (byte)0xb4, (byte)0x42}, - new byte[]{(byte)0x34, (byte)0xbb, (byte)0x8a, (byte)0x5b, (byte)0x5f, (byte)0x42, (byte)0x7f, (byte)0xd7, (byte)0xae, (byte)0xb6, (byte)0xb7, (byte)0x79, (byte)0x36, (byte)0x0a, (byte)0x16, (byte)0xf6}, - new byte[]{(byte)0x26, (byte)0xf6, (byte)0x52, (byte)0x41, (byte)0xcb, (byte)0xe5, (byte)0x54, (byte)0x38, (byte)0x43, (byte)0xce, (byte)0x59, (byte)0x18, (byte)0xff, (byte)0xba, (byte)0xaf, (byte)0xde}, - new byte[]{(byte)0x4c, (byte)0xe9, (byte)0x9a, (byte)0x54, (byte)0xb9, (byte)0xf3, (byte)0x02, (byte)0x6a, (byte)0xa2, (byte)0xca, (byte)0x9c, (byte)0xf7, (byte)0x83, (byte)0x9e, (byte)0xc9, (byte)0x78}, - new byte[]{(byte)0xae, (byte)0x51, (byte)0xa5, (byte)0x1a, (byte)0x1b, (byte)0xdf, (byte)0xf7, (byte)0xbe, (byte)0x40, (byte)0xc0, (byte)0x6e, (byte)0x28, (byte)0x22, (byte)0x90, (byte)0x12, (byte)0x35}, - new byte[]{(byte)0xa0, (byte)0xc1, (byte)0x61, (byte)0x3c, (byte)0xba, (byte)0x7e, (byte)0xd2, (byte)0x2b, (byte)0xc1, (byte)0x73, (byte)0xbc, (byte)0x0f, (byte)0x48, (byte)0xa6, (byte)0x59, (byte)0xcf}, - new byte[]{(byte)0x75, (byte)0x6a, (byte)0xcc, (byte)0x03, (byte)0x02, (byte)0x28, (byte)0x82, (byte)0x88, (byte)0x4a, (byte)0xd6, (byte)0xbd, (byte)0xfd, (byte)0xe9, (byte)0xc5, (byte)0x9d, (byte)0xa1} - }; - - private readonly byte[] buffer; - private int off; + private readonly byte[] m_buf; + private int m_bufPos; public Haraka512Digest() { - this.buffer = new byte[64]; + m_buf = new byte[64]; + m_bufPos = 0; } - public Haraka512Digest(Haraka512Digest digest) + public override string AlgorithmName => "Haraka-512"; + + public override int GetByteLength() => 64; + + public override void Update(byte input) { - this.buffer = (byte[])digest.buffer.Clone(); - this.off = digest.off; + if (m_bufPos > 64 - 1) + throw new ArgumentException("total input cannot be more than 64 bytes"); + + m_buf[m_bufPos++] = input; } - private void Mix512(byte[][] s1, byte[][] s2) + public override void BlockUpdate(byte[] input, int inOff, int len) { - Array.Copy(s1[0], 12, s2[0], 0, 4); - Array.Copy(s1[2], 12, s2[0], 4, 4); - Array.Copy(s1[1], 12, s2[0], 8, 4); - Array.Copy(s1[3], 12, s2[0], 12, 4); + if (m_bufPos > 64 - len) + throw new ArgumentException("total input cannot be more than 64 bytes"); - Array.Copy(s1[2], 0, s2[1], 0, 4); - Array.Copy(s1[0], 0, s2[1], 4, 4); - Array.Copy(s1[3], 0, s2[1], 8, 4); - Array.Copy(s1[1], 0, s2[1], 12, 4); + Array.Copy(input, inOff, m_buf, m_bufPos, len); + m_bufPos += len; + } - Array.Copy(s1[2], 4, s2[2], 0, 4); - Array.Copy(s1[0], 4, s2[2], 4, 4); - Array.Copy(s1[3], 4, s2[2], 8, 4); - Array.Copy(s1[1], 4, s2[2], 12, 4); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void BlockUpdate(ReadOnlySpan input) + { + if (m_bufPos > 64 - input.Length) + throw new ArgumentException("total input cannot be more than 64 bytes"); - Array.Copy(s1[0], 8, s2[3], 0, 4); - Array.Copy(s1[2], 8, s2[3], 4, 4); - Array.Copy(s1[1], 8, s2[3], 8, 4); - Array.Copy(s1[3], 8, s2[3], 12, 4); + input.CopyTo(m_buf.AsSpan(m_bufPos)); + m_bufPos += input.Length; + } +#endif + + public override int DoFinal(byte[] output, int outOff) + { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return DoFinal(output.AsSpan(outOff)); +#else + if (m_bufPos != 64) + throw new ArgumentException("input must be exactly 64 bytes"); + + if (output.Length - outOff < 32) + throw new ArgumentException("output too short to receive digest"); + + int rv = Haraka512256(m_buf, output, outOff); + + Reset(); + + return rv; +#endif + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override int DoFinal(Span output) + { + if (m_bufPos != 64) + throw new ArgumentException("input must be exactly 64 bytes"); + + if (output.Length < 32) + throw new ArgumentException("output too short to receive digest"); + + int rv = Haraka512256(m_buf, output); + + Reset(); + + return rv; + } +#endif + + public override void Reset() + { + m_bufPos = 0; + Array.Clear(m_buf, 0, 64); } - private int Haraka512256(byte[] msg, byte[] output, int outOff) +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + private static int Haraka512256(ReadOnlySpan msg, Span output) { byte[][] s1 = new byte[4][]; s1[0] = new byte[16]; @@ -99,78 +102,75 @@ namespace Org.BouncyCastle.Crypto.Digests s2[2] = new byte[16]; s2[3] = new byte[16]; - //-- Unrolled version of above. - - Array.Copy(msg, 0, s1[0], 0, 16); - Array.Copy(msg, 16, s1[1], 0, 16); - Array.Copy(msg, 32, s1[2], 0, 16); - Array.Copy(msg, 48, s1[3], 0, 16); - - s1[0] = aesEnc(s1[0], RC[0]); - s1[1] = aesEnc(s1[1], RC[1]); - s1[2] = aesEnc(s1[2], RC[2]); - s1[3] = aesEnc(s1[3], RC[3]); - s1[0] = aesEnc(s1[0], RC[4]); - s1[1] = aesEnc(s1[1], RC[5]); - s1[2] = aesEnc(s1[2], RC[6]); - s1[3] = aesEnc(s1[3], RC[7]); + msg[ ..16].CopyTo(s1[0]); + msg[16..32].CopyTo(s1[1]); + msg[32..48].CopyTo(s1[2]); + msg[48..64].CopyTo(s1[3]); + + s1[0] = AesEnc(s1[0], RC[0]); + s1[1] = AesEnc(s1[1], RC[1]); + s1[2] = AesEnc(s1[2], RC[2]); + s1[3] = AesEnc(s1[3], RC[3]); + s1[0] = AesEnc(s1[0], RC[4]); + s1[1] = AesEnc(s1[1], RC[5]); + s1[2] = AesEnc(s1[2], RC[6]); + s1[3] = AesEnc(s1[3], RC[7]); Mix512(s1, s2); - s1[0] = aesEnc(s2[0], RC[8]); - s1[1] = aesEnc(s2[1], RC[9]); - s1[2] = aesEnc(s2[2], RC[10]); - s1[3] = aesEnc(s2[3], RC[11]); - s1[0] = aesEnc(s1[0], RC[12]); - s1[1] = aesEnc(s1[1], RC[13]); - s1[2] = aesEnc(s1[2], RC[14]); - s1[3] = aesEnc(s1[3], RC[15]); + s1[0] = AesEnc(s2[0], RC[8]); + s1[1] = AesEnc(s2[1], RC[9]); + s1[2] = AesEnc(s2[2], RC[10]); + s1[3] = AesEnc(s2[3], RC[11]); + s1[0] = AesEnc(s1[0], RC[12]); + s1[1] = AesEnc(s1[1], RC[13]); + s1[2] = AesEnc(s1[2], RC[14]); + s1[3] = AesEnc(s1[3], RC[15]); Mix512(s1, s2); - s1[0] = aesEnc(s2[0], RC[16]); - s1[1] = aesEnc(s2[1], RC[17]); - s1[2] = aesEnc(s2[2], RC[18]); - s1[3] = aesEnc(s2[3], RC[19]); - s1[0] = aesEnc(s1[0], RC[20]); - s1[1] = aesEnc(s1[1], RC[21]); - s1[2] = aesEnc(s1[2], RC[22]); - s1[3] = aesEnc(s1[3], RC[23]); + s1[0] = AesEnc(s2[0], RC[16]); + s1[1] = AesEnc(s2[1], RC[17]); + s1[2] = AesEnc(s2[2], RC[18]); + s1[3] = AesEnc(s2[3], RC[19]); + s1[0] = AesEnc(s1[0], RC[20]); + s1[1] = AesEnc(s1[1], RC[21]); + s1[2] = AesEnc(s1[2], RC[22]); + s1[3] = AesEnc(s1[3], RC[23]); Mix512(s1, s2); - s1[0] = aesEnc(s2[0], RC[24]); - s1[1] = aesEnc(s2[1], RC[25]); - s1[2] = aesEnc(s2[2], RC[26]); - s1[3] = aesEnc(s2[3], RC[27]); - s1[0] = aesEnc(s1[0], RC[28]); - s1[1] = aesEnc(s1[1], RC[29]); - s1[2] = aesEnc(s1[2], RC[30]); - s1[3] = aesEnc(s1[3], RC[31]); + s1[0] = AesEnc(s2[0], RC[24]); + s1[1] = AesEnc(s2[1], RC[25]); + s1[2] = AesEnc(s2[2], RC[26]); + s1[3] = AesEnc(s2[3], RC[27]); + s1[0] = AesEnc(s1[0], RC[28]); + s1[1] = AesEnc(s1[1], RC[29]); + s1[2] = AesEnc(s1[2], RC[30]); + s1[3] = AesEnc(s1[3], RC[31]); Mix512(s1, s2); - s1[0] = aesEnc(s2[0], RC[32]); - s1[1] = aesEnc(s2[1], RC[33]); - s1[2] = aesEnc(s2[2], RC[34]); - s1[3] = aesEnc(s2[3], RC[35]); - s1[0] = aesEnc(s1[0], RC[36]); - s1[1] = aesEnc(s1[1], RC[37]); - s1[2] = aesEnc(s1[2], RC[38]); - s1[3] = aesEnc(s1[3], RC[39]); + s1[0] = AesEnc(s2[0], RC[32]); + s1[1] = AesEnc(s2[1], RC[33]); + s1[2] = AesEnc(s2[2], RC[34]); + s1[3] = AesEnc(s2[3], RC[35]); + s1[0] = AesEnc(s1[0], RC[36]); + s1[1] = AesEnc(s1[1], RC[37]); + s1[2] = AesEnc(s1[2], RC[38]); + s1[3] = AesEnc(s1[3], RC[39]); Mix512(s1, s2); - s1[0] = Xor(s2[0], msg, 0); - s1[1] = Xor(s2[1], msg, 16); - s1[2] = Xor(s2[2], msg, 32); - s1[3] = Xor(s2[3], msg, 48); + Xor(s2[0], msg, s1[0]); + Xor(s2[1], msg[16..], s1[1]); + Xor(s2[2], msg[32..], s1[2]); + Xor(s2[3], msg[48..], s1[3]); - Array.Copy(s1[0], 8, output, outOff, 8); - Array.Copy(s1[1], 8, output, outOff + 8, 8); - Array.Copy(s1[2], 0, output, outOff + 16, 8); - Array.Copy(s1[3], 0, output, outOff + 24, 8); + s1[0].AsSpan(8, 8).CopyTo(output); + s1[1].AsSpan(8, 8).CopyTo(output[8..]); + s1[2].AsSpan(0, 8).CopyTo(output[16..]); + s1[3].AsSpan(0, 8).CopyTo(output[24..]); return DIGEST_SIZE; } - -#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - private int Haraka512256(byte[] msg, Span output) +#else + private static int Haraka512256(byte[] msg, byte[] output, int outOff) { byte[][] s1 = new byte[4][]; s1[0] = new byte[16]; @@ -183,61 +183,59 @@ namespace Org.BouncyCastle.Crypto.Digests s2[2] = new byte[16]; s2[3] = new byte[16]; - //-- Unrolled version of above. - Array.Copy(msg, 0, s1[0], 0, 16); Array.Copy(msg, 16, s1[1], 0, 16); Array.Copy(msg, 32, s1[2], 0, 16); Array.Copy(msg, 48, s1[3], 0, 16); - s1[0] = aesEnc(s1[0], RC[0]); - s1[1] = aesEnc(s1[1], RC[1]); - s1[2] = aesEnc(s1[2], RC[2]); - s1[3] = aesEnc(s1[3], RC[3]); - s1[0] = aesEnc(s1[0], RC[4]); - s1[1] = aesEnc(s1[1], RC[5]); - s1[2] = aesEnc(s1[2], RC[6]); - s1[3] = aesEnc(s1[3], RC[7]); + s1[0] = AesEnc(s1[0], RC[0]); + s1[1] = AesEnc(s1[1], RC[1]); + s1[2] = AesEnc(s1[2], RC[2]); + s1[3] = AesEnc(s1[3], RC[3]); + s1[0] = AesEnc(s1[0], RC[4]); + s1[1] = AesEnc(s1[1], RC[5]); + s1[2] = AesEnc(s1[2], RC[6]); + s1[3] = AesEnc(s1[3], RC[7]); Mix512(s1, s2); - s1[0] = aesEnc(s2[0], RC[8]); - s1[1] = aesEnc(s2[1], RC[9]); - s1[2] = aesEnc(s2[2], RC[10]); - s1[3] = aesEnc(s2[3], RC[11]); - s1[0] = aesEnc(s1[0], RC[12]); - s1[1] = aesEnc(s1[1], RC[13]); - s1[2] = aesEnc(s1[2], RC[14]); - s1[3] = aesEnc(s1[3], RC[15]); + s1[0] = AesEnc(s2[0], RC[8]); + s1[1] = AesEnc(s2[1], RC[9]); + s1[2] = AesEnc(s2[2], RC[10]); + s1[3] = AesEnc(s2[3], RC[11]); + s1[0] = AesEnc(s1[0], RC[12]); + s1[1] = AesEnc(s1[1], RC[13]); + s1[2] = AesEnc(s1[2], RC[14]); + s1[3] = AesEnc(s1[3], RC[15]); Mix512(s1, s2); - s1[0] = aesEnc(s2[0], RC[16]); - s1[1] = aesEnc(s2[1], RC[17]); - s1[2] = aesEnc(s2[2], RC[18]); - s1[3] = aesEnc(s2[3], RC[19]); - s1[0] = aesEnc(s1[0], RC[20]); - s1[1] = aesEnc(s1[1], RC[21]); - s1[2] = aesEnc(s1[2], RC[22]); - s1[3] = aesEnc(s1[3], RC[23]); + s1[0] = AesEnc(s2[0], RC[16]); + s1[1] = AesEnc(s2[1], RC[17]); + s1[2] = AesEnc(s2[2], RC[18]); + s1[3] = AesEnc(s2[3], RC[19]); + s1[0] = AesEnc(s1[0], RC[20]); + s1[1] = AesEnc(s1[1], RC[21]); + s1[2] = AesEnc(s1[2], RC[22]); + s1[3] = AesEnc(s1[3], RC[23]); Mix512(s1, s2); - s1[0] = aesEnc(s2[0], RC[24]); - s1[1] = aesEnc(s2[1], RC[25]); - s1[2] = aesEnc(s2[2], RC[26]); - s1[3] = aesEnc(s2[3], RC[27]); - s1[0] = aesEnc(s1[0], RC[28]); - s1[1] = aesEnc(s1[1], RC[29]); - s1[2] = aesEnc(s1[2], RC[30]); - s1[3] = aesEnc(s1[3], RC[31]); + s1[0] = AesEnc(s2[0], RC[24]); + s1[1] = AesEnc(s2[1], RC[25]); + s1[2] = AesEnc(s2[2], RC[26]); + s1[3] = AesEnc(s2[3], RC[27]); + s1[0] = AesEnc(s1[0], RC[28]); + s1[1] = AesEnc(s1[1], RC[29]); + s1[2] = AesEnc(s1[2], RC[30]); + s1[3] = AesEnc(s1[3], RC[31]); Mix512(s1, s2); - s1[0] = aesEnc(s2[0], RC[32]); - s1[1] = aesEnc(s2[1], RC[33]); - s1[2] = aesEnc(s2[2], RC[34]); - s1[3] = aesEnc(s2[3], RC[35]); - s1[0] = aesEnc(s1[0], RC[36]); - s1[1] = aesEnc(s1[1], RC[37]); - s1[2] = aesEnc(s1[2], RC[38]); - s1[3] = aesEnc(s1[3], RC[39]); + s1[0] = AesEnc(s2[0], RC[32]); + s1[1] = AesEnc(s2[1], RC[33]); + s1[2] = AesEnc(s2[2], RC[34]); + s1[3] = AesEnc(s2[3], RC[35]); + s1[0] = AesEnc(s1[0], RC[36]); + s1[1] = AesEnc(s1[1], RC[37]); + s1[2] = AesEnc(s1[2], RC[38]); + s1[3] = AesEnc(s1[3], RC[39]); Mix512(s1, s2); s1[0] = Xor(s2[0], msg, 0); @@ -245,95 +243,36 @@ namespace Org.BouncyCastle.Crypto.Digests s1[2] = Xor(s2[2], msg, 32); s1[3] = Xor(s2[3], msg, 48); - s1[0].AsSpan(8, 8).CopyTo(output); - s1[1].AsSpan(8, 8).CopyTo(output[8..]); - s1[2].AsSpan(0, 8).CopyTo(output[16..]); - s1[3].AsSpan(0, 8).CopyTo(output[24..]); + Array.Copy(s1[0], 8, output, outOff, 8); + Array.Copy(s1[1], 8, output, outOff + 8, 8); + Array.Copy(s1[2], 0, output, outOff + 16, 8); + Array.Copy(s1[3], 0, output, outOff + 24, 8); return DIGEST_SIZE; } #endif - public override string AlgorithmName => "Haraka-512"; - - public override void Update(byte input) - { - if (off + 1 > 64) - { - throw new ArgumentException("total input cannot be more than 64 bytes"); - } - - buffer[off++] = input; - } - - public override void BlockUpdate(byte[] input, int inOff, int len) - { - if (off + len > 64) - { - throw new ArgumentException("total input cannot be more than 64 bytes"); - } - - Array.Copy(input, inOff, buffer, off, len); - off += len; - } - -#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - public override void BlockUpdate(ReadOnlySpan input) - { - if (off + input.Length > 64) - { - throw new ArgumentException("total input cannot be more than 64 bytes"); - } - - input.CopyTo(buffer.AsSpan(off)); - off += input.Length; - } -#endif - - public override int DoFinal(byte[] output, int outOff) + private static void Mix512(byte[][] s1, byte[][] s2) { - if (off != 64) - { - throw new ArgumentException("input must be exactly 64 bytes"); - } - - if (output.Length - outOff < 32) - { - throw new ArgumentException("output too short to receive digest"); - } - - int rv = Haraka512256(buffer, output, outOff); - - Reset(); - - return rv; - } - -#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - public override int DoFinal(Span output) - { - if (off != 64) - { - throw new ArgumentException("input must be exactly 64 bytes"); - } - - if (output.Length < 32) - { - throw new ArgumentException("output too short to receive digest"); - } - - int rv = Haraka512256(buffer, output); + Array.Copy(s1[0], 12, s2[0], 0, 4); + Array.Copy(s1[2], 12, s2[0], 4, 4); + Array.Copy(s1[1], 12, s2[0], 8, 4); + Array.Copy(s1[3], 12, s2[0], 12, 4); - Reset(); + Array.Copy(s1[2], 0, s2[1], 0, 4); + Array.Copy(s1[0], 0, s2[1], 4, 4); + Array.Copy(s1[3], 0, s2[1], 8, 4); + Array.Copy(s1[1], 0, s2[1], 12, 4); - return rv; - } -#endif + Array.Copy(s1[2], 4, s2[2], 0, 4); + Array.Copy(s1[0], 4, s2[2], 4, 4); + Array.Copy(s1[3], 4, s2[2], 8, 4); + Array.Copy(s1[1], 4, s2[2], 12, 4); - public override void Reset() - { - off = 0; - Array.Clear(buffer, 0, 64); + Array.Copy(s1[0], 8, s2[3], 0, 4); + Array.Copy(s1[2], 8, s2[3], 4, 4); + Array.Copy(s1[1], 8, s2[3], 8, 4); + Array.Copy(s1[3], 8, s2[3], 12, 4); } } -} \ No newline at end of file +} diff --git a/crypto/src/crypto/digests/HarakaBase.cs b/crypto/src/crypto/digests/HarakaBase.cs index 1270de35c..37dda2163 100644 --- a/crypto/src/crypto/digests/HarakaBase.cs +++ b/crypto/src/crypto/digests/HarakaBase.cs @@ -2,99 +2,125 @@ namespace Org.BouncyCastle.Crypto.Digests { - public abstract class HarakaBase : IDigest + public abstract class HarakaBase + : IDigest { - protected static readonly int DIGEST_SIZE = 32; - - protected static readonly byte[,] S = { - {(byte)0x63, (byte)0x7c, (byte)0x77, (byte)0x7b, (byte)0xf2, (byte)0x6b, (byte)0x6f, (byte)0xc5, (byte)0x30, (byte)0x01, (byte)0x67, (byte)0x2b, (byte)0xfe, (byte)0xd7, (byte)0xab, (byte)0x76}, - {(byte)0xca, (byte)0x82, (byte)0xc9, (byte)0x7d, (byte)0xfa, (byte)0x59, (byte)0x47, (byte)0xf0, (byte)0xad, (byte)0xd4, (byte)0xa2, (byte)0xaf, (byte)0x9c, (byte)0xa4, (byte)0x72, (byte)0xc0}, - {(byte)0xb7, (byte)0xfd, (byte)0x93, (byte)0x26, (byte)0x36, (byte)0x3f, (byte)0xf7, (byte)0xcc, (byte)0x34, (byte)0xa5, (byte)0xe5, (byte)0xf1, (byte)0x71, (byte)0xd8, (byte)0x31, (byte)0x15}, - {(byte)0x04, (byte)0xc7, (byte)0x23, (byte)0xc3, (byte)0x18, (byte)0x96, (byte)0x05, (byte)0x9a, (byte)0x07, (byte)0x12, (byte)0x80, (byte)0xe2, (byte)0xeb, (byte)0x27, (byte)0xb2, (byte)0x75}, - {(byte)0x09, (byte)0x83, (byte)0x2c, (byte)0x1a, (byte)0x1b, (byte)0x6e, (byte)0x5a, (byte)0xa0, (byte)0x52, (byte)0x3b, (byte)0xd6, (byte)0xb3, (byte)0x29, (byte)0xe3, (byte)0x2f, (byte)0x84}, - {(byte)0x53, (byte)0xd1, (byte)0x00, (byte)0xed, (byte)0x20, (byte)0xfc, (byte)0xb1, (byte)0x5b, (byte)0x6a, (byte)0xcb, (byte)0xbe, (byte)0x39, (byte)0x4a, (byte)0x4c, (byte)0x58, (byte)0xcf}, - {(byte)0xd0, (byte)0xef, (byte)0xaa, (byte)0xfb, (byte)0x43, (byte)0x4d, (byte)0x33, (byte)0x85, (byte)0x45, (byte)0xf9, (byte)0x02, (byte)0x7f, (byte)0x50, (byte)0x3c, (byte)0x9f, (byte)0xa8}, - {(byte)0x51, (byte)0xa3, (byte)0x40, (byte)0x8f, (byte)0x92, (byte)0x9d, (byte)0x38, (byte)0xf5, (byte)0xbc, (byte)0xb6, (byte)0xda, (byte)0x21, (byte)0x10, (byte)0xff, (byte)0xf3, (byte)0xd2}, - {(byte)0xcd, (byte)0x0c, (byte)0x13, (byte)0xec, (byte)0x5f, (byte)0x97, (byte)0x44, (byte)0x17, (byte)0xc4, (byte)0xa7, (byte)0x7e, (byte)0x3d, (byte)0x64, (byte)0x5d, (byte)0x19, (byte)0x73}, - {(byte)0x60, (byte)0x81, (byte)0x4f, (byte)0xdc, (byte)0x22, (byte)0x2a, (byte)0x90, (byte)0x88, (byte)0x46, (byte)0xee, (byte)0xb8, (byte)0x14, (byte)0xde, (byte)0x5e, (byte)0x0b, (byte)0xdb}, - {(byte)0xe0, (byte)0x32, (byte)0x3a, (byte)0x0a, (byte)0x49, (byte)0x06, (byte)0x24, (byte)0x5c, (byte)0xc2, (byte)0xd3, (byte)0xac, (byte)0x62, (byte)0x91, (byte)0x95, (byte)0xe4, (byte)0x79}, - {(byte)0xe7, (byte)0xc8, (byte)0x37, (byte)0x6d, (byte)0x8d, (byte)0xd5, (byte)0x4e, (byte)0xa9, (byte)0x6c, (byte)0x56, (byte)0xf4, (byte)0xea, (byte)0x65, (byte)0x7a, (byte)0xae, (byte)0x08}, - {(byte)0xba, (byte)0x78, (byte)0x25, (byte)0x2e, (byte)0x1c, (byte)0xa6, (byte)0xb4, (byte)0xc6, (byte)0xe8, (byte)0xdd, (byte)0x74, (byte)0x1f, (byte)0x4b, (byte)0xbd, (byte)0x8b, (byte)0x8a}, - {(byte)0x70, (byte)0x3e, (byte)0xb5, (byte)0x66, (byte)0x48, (byte)0x03, (byte)0xf6, (byte)0x0e, (byte)0x61, (byte)0x35, (byte)0x57, (byte)0xb9, (byte)0x86, (byte)0xc1, (byte)0x1d, (byte)0x9e}, - {(byte)0xe1, (byte)0xf8, (byte)0x98, (byte)0x11, (byte)0x69, (byte)0xd9, (byte)0x8e, (byte)0x94, (byte)0x9b, (byte)0x1e, (byte)0x87, (byte)0xe9, (byte)0xce, (byte)0x55, (byte)0x28, (byte)0xdf}, - {(byte)0x8c, (byte)0xa1, (byte)0x89, (byte)0x0d, (byte)0xbf, (byte)0xe6, (byte)0x42, (byte)0x68, (byte)0x41, (byte)0x99, (byte)0x2d, (byte)0x0f, (byte)0xb0, (byte)0x54, (byte)0xbb, (byte)0x16}}; + internal static readonly int DIGEST_SIZE = 32; - public abstract string AlgorithmName { get; } + // Haraka round constants + internal static readonly byte[][] RC = new byte[][] + { + new byte[]{ 0x9D, 0x7B, 0x81, 0x75, 0xF0, 0xFE, 0xC5, 0xB2, 0x0A, 0xC0, 0x20, 0xE6, 0x4C, 0x70, 0x84, 0x06 }, + new byte[]{ 0x17, 0xF7, 0x08, 0x2F, 0xA4, 0x6B, 0x0F, 0x64, 0x6B, 0xA0, 0xF3, 0x88, 0xE1, 0xB4, 0x66, 0x8B }, + new byte[]{ 0x14, 0x91, 0x02, 0x9F, 0x60, 0x9D, 0x02, 0xCF, 0x98, 0x84, 0xF2, 0x53, 0x2D, 0xDE, 0x02, 0x34 }, + new byte[]{ 0x79, 0x4F, 0x5B, 0xFD, 0xAF, 0xBC, 0xF3, 0xBB, 0x08, 0x4F, 0x7B, 0x2E, 0xE6, 0xEA, 0xD6, 0x0E }, + new byte[]{ 0x44, 0x70, 0x39, 0xBE, 0x1C, 0xCD, 0xEE, 0x79, 0x8B, 0x44, 0x72, 0x48, 0xCB, 0xB0, 0xCF, 0xCB }, + new byte[]{ 0x7B, 0x05, 0x8A, 0x2B, 0xED, 0x35, 0x53, 0x8D, 0xB7, 0x32, 0x90, 0x6E, 0xEE, 0xCD, 0xEA, 0x7E }, + new byte[]{ 0x1B, 0xEF, 0x4F, 0xDA, 0x61, 0x27, 0x41, 0xE2, 0xD0, 0x7C, 0x2E, 0x5E, 0x43, 0x8F, 0xC2, 0x67 }, + new byte[]{ 0x3B, 0x0B, 0xC7, 0x1F, 0xE2, 0xFD, 0x5F, 0x67, 0x07, 0xCC, 0xCA, 0xAF, 0xB0, 0xD9, 0x24, 0x29 }, + new byte[]{ 0xEE, 0x65, 0xD4, 0xB9, 0xCA, 0x8F, 0xDB, 0xEC, 0xE9, 0x7F, 0x86, 0xE6, 0xF1, 0x63, 0x4D, 0xAB }, + new byte[]{ 0x33, 0x7E, 0x03, 0xAD, 0x4F, 0x40, 0x2A, 0x5B, 0x64, 0xCD, 0xB7, 0xD4, 0x84, 0xBF, 0x30, 0x1C }, + new byte[]{ 0x00, 0x98, 0xF6, 0x8D, 0x2E, 0x8B, 0x02, 0x69, 0xBF, 0x23, 0x17, 0x94, 0xB9, 0x0B, 0xCC, 0xB2 }, + new byte[]{ 0x8A, 0x2D, 0x9D, 0x5C, 0xC8, 0x9E, 0xAA, 0x4A, 0x72, 0x55, 0x6F, 0xDE, 0xA6, 0x78, 0x04, 0xFA }, + new byte[]{ 0xD4, 0x9F, 0x12, 0x29, 0x2E, 0x4F, 0xFA, 0x0E, 0x12, 0x2A, 0x77, 0x6B, 0x2B, 0x9F, 0xB4, 0xDF }, + new byte[]{ 0xEE, 0x12, 0x6A, 0xBB, 0xAE, 0x11, 0xD6, 0x32, 0x36, 0xA2, 0x49, 0xF4, 0x44, 0x03, 0xA1, 0x1E }, + new byte[]{ 0xA6, 0xEC, 0xA8, 0x9C, 0xC9, 0x00, 0x96, 0x5F, 0x84, 0x00, 0x05, 0x4B, 0x88, 0x49, 0x04, 0xAF }, + new byte[]{ 0xEC, 0x93, 0xE5, 0x27, 0xE3, 0xC7, 0xA2, 0x78, 0x4F, 0x9C, 0x19, 0x9D, 0xD8, 0x5E, 0x02, 0x21 }, + new byte[]{ 0x73, 0x01, 0xD4, 0x82, 0xCD, 0x2E, 0x28, 0xB9, 0xB7, 0xC9, 0x59, 0xA7, 0xF8, 0xAA, 0x3A, 0xBF }, + new byte[]{ 0x6B, 0x7D, 0x30, 0x10, 0xD9, 0xEF, 0xF2, 0x37, 0x17, 0xB0, 0x86, 0x61, 0x0D, 0x70, 0x60, 0x62 }, + new byte[]{ 0xC6, 0x9A, 0xFC, 0xF6, 0x53, 0x91, 0xC2, 0x81, 0x43, 0x04, 0x30, 0x21, 0xC2, 0x45, 0xCA, 0x5A }, + new byte[]{ 0x3A, 0x94, 0xD1, 0x36, 0xE8, 0x92, 0xAF, 0x2C, 0xBB, 0x68, 0x6B, 0x22, 0x3C, 0x97, 0x23, 0x92 }, + new byte[]{ 0xB4, 0x71, 0x10, 0xE5, 0x58, 0xB9, 0xBA, 0x6C, 0xEB, 0x86, 0x58, 0x22, 0x38, 0x92, 0xBF, 0xD3 }, + new byte[]{ 0x8D, 0x12, 0xE1, 0x24, 0xDD, 0xFD, 0x3D, 0x93, 0x77, 0xC6, 0xF0, 0xAE, 0xE5, 0x3C, 0x86, 0xDB }, + new byte[]{ 0xB1, 0x12, 0x22, 0xCB, 0xE3, 0x8D, 0xE4, 0x83, 0x9C, 0xA0, 0xEB, 0xFF, 0x68, 0x62, 0x60, 0xBB }, + new byte[]{ 0x7D, 0xF7, 0x2B, 0xC7, 0x4E, 0x1A, 0xB9, 0x2D, 0x9C, 0xD1, 0xE4, 0xE2, 0xDC, 0xD3, 0x4B, 0x73 }, + new byte[]{ 0x4E, 0x92, 0xB3, 0x2C, 0xC4, 0x15, 0x14, 0x4B, 0x43, 0x1B, 0x30, 0x61, 0xC3, 0x47, 0xBB, 0x43 }, + new byte[]{ 0x99, 0x68, 0xEB, 0x16, 0xDD, 0x31, 0xB2, 0x03, 0xF6, 0xEF, 0x07, 0xE7, 0xA8, 0x75, 0xA7, 0xDB }, + new byte[]{ 0x2C, 0x47, 0xCA, 0x7E, 0x02, 0x23, 0x5E, 0x8E, 0x77, 0x59, 0x75, 0x3C, 0x4B, 0x61, 0xF3, 0x6D }, + new byte[]{ 0xF9, 0x17, 0x86, 0xB8, 0xB9, 0xE5, 0x1B, 0x6D, 0x77, 0x7D, 0xDE, 0xD6, 0x17, 0x5A, 0xA7, 0xCD }, + new byte[]{ 0x5D, 0xEE, 0x46, 0xA9, 0x9D, 0x06, 0x6C, 0x9D, 0xAA, 0xE9, 0xA8, 0x6B, 0xF0, 0x43, 0x6B, 0xEC }, + new byte[]{ 0xC1, 0x27, 0xF3, 0x3B, 0x59, 0x11, 0x53, 0xA2, 0x2B, 0x33, 0x57, 0xF9, 0x50, 0x69, 0x1E, 0xCB }, + new byte[]{ 0xD9, 0xD0, 0x0E, 0x60, 0x53, 0x03, 0xED, 0xE4, 0x9C, 0x61, 0xDA, 0x00, 0x75, 0x0C, 0xEE, 0x2C }, + new byte[]{ 0x50, 0xA3, 0xA4, 0x63, 0xBC, 0xBA, 0xBB, 0x80, 0xAB, 0x0C, 0xE9, 0x96, 0xA1, 0xA5, 0xB1, 0xF0 }, + new byte[]{ 0x39, 0xCA, 0x8D, 0x93, 0x30, 0xDE, 0x0D, 0xAB, 0x88, 0x29, 0x96, 0x5E, 0x02, 0xB1, 0x3D, 0xAE }, + new byte[]{ 0x42, 0xB4, 0x75, 0x2E, 0xA8, 0xF3, 0x14, 0x88, 0x0B, 0xA4, 0x54, 0xD5, 0x38, 0x8F, 0xBB, 0x17 }, + new byte[]{ 0xF6, 0x16, 0x0A, 0x36, 0x79, 0xB7, 0xB6, 0xAE, 0xD7, 0x7F, 0x42, 0x5F, 0x5B, 0x8A, 0xBB, 0x34 }, + new byte[]{ 0xDE, 0xAF, 0xBA, 0xFF, 0x18, 0x59, 0xCE, 0x43, 0x38, 0x54, 0xE5, 0xCB, 0x41, 0x52, 0xF6, 0x26 }, + new byte[]{ 0x78, 0xC9, 0x9E, 0x83, 0xF7, 0x9C, 0xCA, 0xA2, 0x6A, 0x02, 0xF3, 0xB9, 0x54, 0x9A, 0xE9, 0x4C }, + new byte[]{ 0x35, 0x12, 0x90, 0x22, 0x28, 0x6E, 0xC0, 0x40, 0xBE, 0xF7, 0xDF, 0x1B, 0x1A, 0xA5, 0x51, 0xAE }, + new byte[]{ 0xCF, 0x59, 0xA6, 0x48, 0x0F, 0xBC, 0x73, 0xC1, 0x2B, 0xD2, 0x7E, 0xBA, 0x3C, 0x61, 0xC1, 0xA0 }, + new byte[]{ 0xA1, 0x9D, 0xC5, 0xE9, 0xFD, 0xBD, 0xD6, 0x4A, 0x88, 0x82, 0x28, 0x02, 0x03, 0xCC, 0x6A, 0x75 }, + }; - static byte sBox(byte x) + private static readonly byte[,] S = { - return S[(uint)(((x & 0xFF) >> 4)),x & 0xF]; + { 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76 }, + { 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0 }, + { 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15 }, + { 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75 }, + { 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84 }, + { 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF }, + { 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8 }, + { 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2 }, + { 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73 }, + { 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB }, + { 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79 }, + { 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08 }, + { 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A }, + { 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E }, + { 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF }, + { 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 }, + }; + + private static byte SBox(byte x) + { + return S[(uint)x >> 4, x & 0xFU]; } - static byte[] subBytes(byte[] s) + private static byte[] SubBytes(byte[] s) { byte[] output = new byte[s.Length]; for(int i = 0; i < 16; ++i) { - output[i] = sBox(s[i]); + output[i] = SBox(s[i]); } return output; } - static byte[] shiftRows(byte[] s) + private static byte[] ShiftRows(byte[] s) { return new byte[]{ - s[0], s[5], s[10], s[15], - s[4], s[9], s[14], s[3], - s[8], s[13], s[2], s[7], - s[12], s[1], s[6], s[11] - }; + s[0], s[5], s[10], s[15], + s[4], s[9], s[14], s[3], + s[8], s[13], s[2], s[7], + s[12], s[1], s[6], s[11] + }; } - protected static byte[] aesEnc(byte[] s, byte[] rk) + internal static byte[] AesEnc(byte[] s, byte[] rk) { - s = subBytes(s); - s = shiftRows(s); - s = mixColumns(s); - xorReverse(s, rk); + s = SubBytes(s); + s = ShiftRows(s); + s = MixColumns(s); + XorWith(rk, s); return s; } - static byte xTime(byte x) + private static byte MulX(byte p) { - if ((x >> 7) > 0) - { - return (byte)(((x << 1) ^ 0x1b) & 0xff); - } - else - { - return (byte)((x << 1) & 0xff); - } + return (byte)(((p & 0x7F) << 1) ^ (((uint)p >> 7) * 0x1BU)); } - - static void xorReverse(byte[] x, byte[] y) +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + internal static void Xor(ReadOnlySpan x, ReadOnlySpan y, Span z) { - x[0] = (byte)(x[0] ^ y[15]); - x[1] = (byte)(x[1] ^ y[14]); - x[2] = (byte)(x[2] ^ y[13]); - x[3] = (byte)(x[3] ^ y[12]); - x[4] = (byte)(x[4] ^ y[11]); - x[5] = (byte)(x[5] ^ y[10]); - x[6] = (byte)(x[6] ^ y[9]); - x[7] = (byte)(x[7] ^ y[8]); - x[8] = (byte)(x[8] ^ y[7]); - x[9] = (byte)(x[9] ^ y[6]); - x[10] = (byte)(x[10] ^ y[5]); - x[11] = (byte)(x[11] ^ y[4]); - x[12] = (byte)(x[12] ^ y[3]); - x[13] = (byte)(x[13] ^ y[2]); - x[14] = (byte)(x[14] ^ y[1]); - x[15] = (byte)(x[15] ^ y[0]); + for (int i = 0; i < z.Length; i++) + { + z[i] = (byte)(x[i] ^ y[i]); + } } - - - protected static byte[] Xor(byte[] x, byte[] y, int yStart) +#else + internal static byte[] Xor(byte[] x, byte[] y, int yStart) { byte[] output = new byte[16]; for (int i = 0; i < output.Length; i++) @@ -103,33 +129,40 @@ namespace Org.BouncyCastle.Crypto.Digests } return output; } +#endif + private static void XorWith(byte[] x, byte[] z) + { + for (int i = 0; i < 16; ++i) + { + z[i] ^= x[i]; + } + } - static private byte[] mixColumns(byte[] s) + private static byte[] MixColumns(byte[] s) { byte[] output = new byte[s.Length]; int j = 0, i4; for (int i = 0; i < 4; i++) { i4 = i << 2; - output[j++] = (byte)(xTime(s[i4]) ^ xTime(s[i4 + 1]) ^ s[i4 + 1] ^ s[i4 + 2] ^ s[i4 + 3]); - output[j++] = (byte)(s[i4] ^ xTime(s[i4 + 1]) ^ xTime(s[i4 + 2]) ^ s[i4 + 2] ^ s[i4 + 3]); - output[j++] = (byte)(s[i4] ^ s[i4 + 1] ^ xTime(s[i4 + 2]) ^ xTime(s[i4 + 3]) ^ s[i4 + 3]); - output[j++] = (byte)(xTime(s[i4]) ^ s[i4] ^ s[i4 + 1] ^ s[i4 + 2] ^ xTime(s[i4 + 3])); + output[j++] = (byte)(MulX(s[i4]) ^ MulX(s[i4 + 1]) ^ s[i4 + 1] ^ s[i4 + 2] ^ s[i4 + 3]); + output[j++] = (byte)(s[i4] ^ MulX(s[i4 + 1]) ^ MulX(s[i4 + 2]) ^ s[i4 + 2] ^ s[i4 + 3]); + output[j++] = (byte)(s[i4] ^ s[i4 + 1] ^ MulX(s[i4 + 2]) ^ MulX(s[i4 + 3]) ^ s[i4 + 3]); + output[j++] = (byte)(MulX(s[i4]) ^ s[i4] ^ s[i4 + 1] ^ s[i4 + 2] ^ MulX(s[i4 + 3])); } return output; } + public abstract string AlgorithmName { get; } + public int GetDigestSize() { return DIGEST_SIZE; } - public int GetByteLength() - { - throw new NotImplementedException(); - } + public abstract int GetByteLength(); public abstract void Update(byte input); -- cgit 1.4.1