1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- using System.Collections.Generic;
- #if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER || UNITY_2021_2_OR_NEWER
- using System.Runtime.CompilerServices;
- #endif
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
- namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests
- {
- public sealed class Blake3Digest
- : IDigest, IMemoable, IXof
- {
- /**
- * Already outputting error.
- */
- private const string ERR_OUTPUTTING = "Already outputting";
- /**
- * Number of Words.
- */
- private const int NUMWORDS = 8;
- /**
- * Number of Rounds.
- */
- private const int ROUNDS = 7;
- /**
- * Buffer length.
- */
- private const int BLOCKLEN = NUMWORDS * Integers.NumBytes * 2;
- /**
- * Chunk length.
- */
- private const int CHUNKLEN = 1024;
- /**
- * ChunkStart Flag.
- */
- private const int CHUNKSTART = 1;
- /**
- * ChunkEnd Flag.
- */
- private const int CHUNKEND = 2;
- /**
- * Parent Flag.
- */
- private const int PARENT = 4;
- /**
- * Root Flag.
- */
- private const int ROOT = 8;
- /**
- * KeyedHash Flag.
- */
- private const int KEYEDHASH = 16;
- /**
- * DeriveContext Flag.
- */
- private const int DERIVECONTEXT = 32;
- /**
- * DeriveKey Flag.
- */
- private const int DERIVEKEY = 64;
- /**
- * Chaining0 State Locations.
- */
- private const int CHAINING0 = 0;
- /**
- * Chaining1 State Location.
- */
- private const int CHAINING1 = 1;
- /**
- * Chaining2 State Location.
- */
- private const int CHAINING2 = 2;
- /**
- * Chaining3 State Location.
- */
- private const int CHAINING3 = 3;
- /**
- * Chaining4 State Location.
- */
- private const int CHAINING4 = 4;
- /**
- * Chaining5 State Location.
- */
- private const int CHAINING5 = 5;
- /**
- * Chaining6 State Location.
- */
- private const int CHAINING6 = 6;
- /**
- * Chaining7 State Location.
- */
- private const int CHAINING7 = 7;
- /**
- * IV0 State Locations.
- */
- private const int IV0 = 8;
- /**
- * IV1 State Location.
- */
- private const int IV1 = 9;
- /**
- * IV2 State Location.
- */
- private const int IV2 = 10;
- /**
- * IV3 State Location.
- */
- private const int IV3 = 11;
- /**
- * Count0 State Location.
- */
- private const int COUNT0 = 12;
- /**
- * Count1 State Location.
- */
- private const int COUNT1 = 13;
- /**
- * DataLen State Location.
- */
- private const int DATALEN = 14;
- /**
- * Flags State Location.
- */
- private const int FLAGS = 15;
- /**
- * Message word permutations.
- */
- private static readonly byte[] SIGMA = { 2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8 };
- /**
- * Blake3 Initialization Vector.
- */
- private static readonly uint[] IV = {
- 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
- };
- /**
- * The byte input/output buffer.
- */
- private readonly byte[] m_theBuffer = new byte[BLOCKLEN];
- /**
- * The key.
- */
- private readonly uint[] m_theK = new uint[NUMWORDS];
- /**
- * The chaining value.
- */
- private readonly uint[] m_theChaining = new uint[NUMWORDS];
- /**
- * The state.
- */
- private readonly uint[] m_theV = new uint[NUMWORDS << 1];
- /**
- * The message Buffer.
- */
- private readonly uint[] m_theM = new uint[NUMWORDS << 1];
- /**
- * The indices.
- */
- private readonly byte[] m_theIndices = new byte[NUMWORDS << 1];
- /**
- * The chainingStack.
- */
- private readonly List<uint[]> m_theStack = new List<uint[]>();
- /**
- * The default digestLength.
- */
- private readonly int m_theDigestLen;
- /**
- * Are we outputting?
- */
- private bool m_outputting;
- /**
- * How many more bytes can we output?
- */
- private long m_outputAvailable;
- /**
- * The current mode.
- */
- private int m_theMode;
- /**
- * The output mode.
- */
- private int m_theOutputMode;
- /**
- * The output dataLen.
- */
- private int m_theOutputDataLen;
- /**
- * The block counter.
- */
- private long m_theCounter;
- /**
- * The # of bytes in the current block.
- */
- private int m_theCurrBytes;
- /**
- * The position of the next byte in the buffer.
- */
- private int m_thePos;
- public Blake3Digest()
- : this((BLOCKLEN >> 1) * 8)
- {
- }
- /// <param name="pDigestSize">the default digest size (in bits)</param>
- public Blake3Digest(int pDigestSize)
- {
- m_theDigestLen = pDigestSize / 8;
- Init(null);
- }
- /**
- * Constructor.
- *
- * @param pSource the source digest.
- */
- public Blake3Digest(Blake3Digest pSource)
- {
- /* Copy default digest length */
- m_theDigestLen = pSource.m_theDigestLen;
- /* Initialise from source */
- Reset(pSource);
- }
- public int GetByteLength() => BLOCKLEN;
- public string AlgorithmName => "BLAKE3";
- public int GetDigestSize() => m_theDigestLen;
- /**
- * Initialise.
- *
- * @param pParams the parameters.
- */
- public void Init(Blake3Parameters pParams)
- {
- /* Access key/context */
- byte[] myKey = pParams?.GetKey();
- byte[] myContext = pParams?.GetContext();
- /* Reset the digest */
- Reset();
- /* If we have a key */
- if (myKey != null)
- {
- /* Initialise with the key */
- InitKey(myKey);
- Arrays.Fill(myKey, 0);
- /* else if we have a context */
- }
- else if (myContext != null)
- {
- /* Initialise for deriving context */
- InitNullKey();
- m_theMode = DERIVECONTEXT;
- /* Derive key from context */
- BlockUpdate(myContext, 0, myContext.Length);
- DoFinal(m_theBuffer, 0);
- InitKeyFromContext();
- Reset();
- /* Else init null key and reset mode */
- }
- else
- {
- InitNullKey();
- m_theMode = 0;
- }
- }
- public void Update(byte b)
- {
- /* Check that we are not outputting */
- if (m_outputting)
- throw new InvalidOperationException(ERR_OUTPUTTING);
- /* If the buffer is full */
- int blockLen = m_theBuffer.Length;
- int remainingLength = blockLen - m_thePos;
- if (remainingLength == 0)
- {
- /* Process the buffer */
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- CompressBlock(m_theBuffer);
- #else
- CompressBlock(m_theBuffer, 0);
- #endif
- /* Reset the buffer */
- Arrays.Fill(m_theBuffer, 0);
- m_thePos = 0;
- }
- /* Store the byte */
- m_theBuffer[m_thePos] = b;
- m_thePos++;
- }
- public void BlockUpdate(byte[] pMessage, int pOffset, int pLen)
- {
- /* Ignore null operation */
- if (pMessage == null)
- return;
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- BlockUpdate(pMessage.AsSpan(pOffset, pLen));
- #else
- if (pLen == 0)
- return;
- /* Check that we are not outputting */
- if (m_outputting)
- throw new InvalidOperationException(ERR_OUTPUTTING);
- /* Process any bytes currently in the buffer */
- int remainingLen = 0; // left bytes of buffer
- if (m_thePos != 0)
- {
- /* Calculate space remaining in the buffer */
- remainingLen = BLOCKLEN - m_thePos;
- /* If there is sufficient space in the buffer */
- if (remainingLen >= pLen)
- {
- /* Copy data into buffer and return */
- Array.Copy(pMessage, pOffset, m_theBuffer, m_thePos, pLen);
- m_thePos += pLen;
- return;
- }
- /* Fill the buffer */
- Array.Copy(pMessage, pOffset, m_theBuffer, m_thePos, remainingLen);
- /* Process the buffer */
- CompressBlock(m_theBuffer, 0);
- /* Reset the buffer */
- m_thePos = 0;
- Arrays.Fill(m_theBuffer, 0);
- }
- /* process all blocks except the last one */
- int messagePos;
- int blockWiseLastPos = pOffset + pLen - BLOCKLEN;
- for (messagePos = pOffset + remainingLen; messagePos < blockWiseLastPos; messagePos += BLOCKLEN)
- {
- /* Process the buffer */
- CompressBlock(pMessage, messagePos);
- }
- /* Fill the buffer with the remaining bytes of the message */
- int len = pLen - messagePos;
- Array.Copy(pMessage, messagePos, m_theBuffer, 0, pOffset + len);
- m_thePos += pOffset + len;
- #endif
- }
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- public void BlockUpdate(ReadOnlySpan<byte> input)
- {
- if (input.IsEmpty)
- return;
- /* Check that we are not outputting */
- if (m_outputting)
- throw new InvalidOperationException(ERR_OUTPUTTING);
- int pLen = input.Length;
- /* Process any bytes currently in the buffer */
- int remainingLen = 0; // left bytes of buffer
- if (m_thePos != 0)
- {
- /* Calculate space remaining in the buffer */
- remainingLen = BLOCKLEN - m_thePos;
- /* If there is sufficient space in the buffer */
- if (remainingLen >= pLen)
- {
- /* Copy data into buffer and return */
- input.CopyTo(m_theBuffer.AsSpan(m_thePos));
- m_thePos += pLen;
- return;
- }
- /* Fill the buffer */
- input[..remainingLen].CopyTo(m_theBuffer.AsSpan(m_thePos));
- /* Process the buffer */
- CompressBlock(m_theBuffer);
- /* Reset the buffer */
- m_thePos = 0;
- Arrays.Fill(m_theBuffer, 0);
- }
- /* process all blocks except the last one */
- int messagePos;
- int blockWiseLastPos = pLen - BLOCKLEN;
- for (messagePos = remainingLen; messagePos < blockWiseLastPos; messagePos += BLOCKLEN)
- {
- /* Process the buffer */
- CompressBlock(input[messagePos..]);
- }
- /* Fill the buffer with the remaining bytes of the message */
- input[messagePos..].CopyTo(m_theBuffer);
- m_thePos += pLen - messagePos;
- }
- #endif
- public int DoFinal(byte[] pOutput, int pOutOffset)
- {
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- return OutputFinal(pOutput.AsSpan(pOutOffset, GetDigestSize()));
- #else
- return OutputFinal(pOutput, pOutOffset, GetDigestSize());
- #endif
- }
- public int OutputFinal(byte[] pOut, int pOutOffset, int pOutLen)
- {
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- return OutputFinal(pOut.AsSpan(pOutOffset, pOutLen));
- #else
- /* Reject if we are already outputting */
- if (m_outputting)
- throw new InvalidOperationException(ERR_OUTPUTTING);
- /* Build the required output */
- int length = Output(pOut, pOutOffset, pOutLen);
- /* reset the underlying digest and return the length */
- Reset();
- return length;
- #endif
- }
- public int Output(byte[] pOut, int pOutOffset, int pOutLen)
- {
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- return Output(pOut.AsSpan(pOutOffset, pOutLen));
- #else
- /* If we have not started outputting yet */
- if (!m_outputting)
- {
- /* Process the buffer */
- CompressFinalBlock(m_thePos);
- }
- /* Reject if there is insufficient Xof remaining */
- if (pOutLen < 0 || (m_outputAvailable >= 0 && pOutLen > m_outputAvailable))
- throw new ArgumentException("Insufficient bytes remaining");
- /* If we have some remaining data in the current buffer */
- int dataLeft = pOutLen;
- int outPos = pOutOffset;
- if (m_thePos < BLOCKLEN)
- {
- /* Copy data from current hash */
- int dataToCopy = System.Math.Min(dataLeft, BLOCKLEN - m_thePos);
- Array.Copy(m_theBuffer, m_thePos, pOut, outPos, dataToCopy);
- /* Adjust counters */
- m_thePos += dataToCopy;
- outPos += dataToCopy;
- dataLeft -= dataToCopy;
- }
- /* Loop until we have completed the request */
- while (dataLeft > 0)
- {
- /* Calculate the next block */
- NextOutputBlock();
- /* Copy data from current hash */
- int dataToCopy = System.Math.Min(dataLeft, BLOCKLEN);
- Array.Copy(m_theBuffer, 0, pOut, outPos, dataToCopy);
- /* Adjust counters */
- m_thePos += dataToCopy;
- outPos += dataToCopy;
- dataLeft -= dataToCopy;
- }
- /* Adjust outputAvailable */
- m_outputAvailable -= pOutLen;
- /* Return the number of bytes transferred */
- return pOutLen;
- #endif
- }
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- public int DoFinal(Span<byte> output)
- {
- return OutputFinal(output[..GetDigestSize()]);
- }
- public int OutputFinal(Span<byte> output)
- {
- /* Reject if we are already outputting */
- if (m_outputting)
- throw new InvalidOperationException(ERR_OUTPUTTING);
- /* Build the required output */
- int length = Output(output);
- /* reset the underlying digest and return the length */
- Reset();
- return length;
- }
- public int Output(Span<byte> output)
- {
- /* If we have not started outputting yet */
- if (!m_outputting)
- {
- /* Process the buffer */
- CompressFinalBlock(m_thePos);
- }
- int pOutOffset = 0, pOutLen = output.Length;
- /* Reject if there is insufficient Xof remaining */
- if (pOutLen < 0 || (m_outputAvailable >= 0 && pOutLen > m_outputAvailable))
- throw new ArgumentException("Insufficient bytes remaining");
- /* If we have some remaining data in the current buffer */
- int dataLeft = pOutLen;
- int outPos = pOutOffset;
- if (m_thePos < BLOCKLEN)
- {
- /* Copy data from current hash */
- int dataToCopy = System.Math.Min(dataLeft, BLOCKLEN - m_thePos);
- m_theBuffer.AsSpan(m_thePos, dataToCopy).CopyTo(output[outPos..]);
- /* Adjust counters */
- m_thePos += dataToCopy;
- outPos += dataToCopy;
- dataLeft -= dataToCopy;
- }
- /* Loop until we have completed the request */
- while (dataLeft > 0)
- {
- /* Calculate the next block */
- NextOutputBlock();
- /* Copy data from current hash */
- int dataToCopy = System.Math.Min(dataLeft, BLOCKLEN);
- m_theBuffer.AsSpan(0, dataToCopy).CopyTo(output[outPos..]);
- /* Adjust counters */
- m_thePos += dataToCopy;
- outPos += dataToCopy;
- dataLeft -= dataToCopy;
- }
- /* Adjust outputAvailable */
- m_outputAvailable -= pOutLen;
- /* Return the number of bytes transferred */
- return pOutLen;
- }
- #endif
- public void Reset()
- {
- ResetBlockCount();
- m_thePos = 0;
- m_outputting = false;
- Arrays.Fill(m_theBuffer, 0);
- }
- public void Reset(IMemoable pSource)
- {
- /* Access source */
- Blake3Digest mySource = (Blake3Digest)pSource;
- /* Reset counter */
- m_theCounter = mySource.m_theCounter;
- m_theCurrBytes = mySource.m_theCurrBytes;
- m_theMode = mySource.m_theMode;
- /* Reset output state */
- m_outputting = mySource.m_outputting;
- m_outputAvailable = mySource.m_outputAvailable;
- m_theOutputMode = mySource.m_theOutputMode;
- m_theOutputDataLen = mySource.m_theOutputDataLen;
- /* Copy state */
- Array.Copy(mySource.m_theChaining, 0, m_theChaining, 0, m_theChaining.Length);
- Array.Copy(mySource.m_theK, 0, m_theK, 0, m_theK.Length);
- Array.Copy(mySource.m_theM, 0, m_theM, 0, m_theM.Length);
- /* Copy stack */
- m_theStack.Clear();
- foreach (var element in mySource.m_theStack)
- {
- m_theStack.Add(Arrays.Clone(element));
- }
- /* Copy buffer */
- Array.Copy(mySource.m_theBuffer, 0, m_theBuffer, 0, m_theBuffer.Length);
- m_thePos = mySource.m_thePos;
- }
- public IMemoable Copy()
- {
- return new Blake3Digest(this);
- }
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- private void CompressBlock(ReadOnlySpan<byte> block)
- {
- /* Initialise state and compress message */
- InitChunkBlock(BLOCKLEN, false);
- InitM(block);
- Compress();
- /* Adjust stack if we have completed a block */
- if (m_theCurrBytes == 0)
- {
- AdjustStack();
- }
- }
- private void InitM(ReadOnlySpan<byte> block)
- {
- /* Copy message bytes into word array */
- Pack.LE_To_UInt32(block, m_theM);
- }
- #else
- /**
- * Compress next block of the message.
- *
- * @param pMessage the message buffer
- * @param pMsgPos the position within the message buffer
- */
- private void CompressBlock(byte[] pMessage, int pMsgPos)
- {
- /* Initialise state and compress message */
- InitChunkBlock(BLOCKLEN, false);
- InitM(pMessage, pMsgPos);
- Compress();
- /* Adjust stack if we have completed a block */
- if (m_theCurrBytes == 0)
- {
- AdjustStack();
- }
- }
- /**
- * Initialise M from message.
- *
- * @param pMessage the source message
- * @param pMsgPos the message position
- */
- private void InitM(byte[] pMessage, int pMsgPos)
- {
- /* Copy message bytes into word array */
- Pack.LE_To_UInt32(pMessage, pMsgPos, m_theM);
- }
- #endif
- /**
- * Adjust the stack.
- */
- private void AdjustStack()
- {
- /* Loop to combine blocks */
- long myCount = m_theCounter;
- while (myCount > 0)
- {
- /* Break loop if we are not combining */
- if ((myCount & 1) == 1)
- break;
- /* Build the message to be hashed */
- uint[] myLeft = m_theStack[m_theStack.Count - 1];
- m_theStack.RemoveAt(m_theStack.Count - 1);
- Array.Copy(myLeft, 0, m_theM, 0, NUMWORDS);
- Array.Copy(m_theChaining, 0, m_theM, NUMWORDS, NUMWORDS);
- /* Create parent block */
- InitParentBlock();
- Compress();
- /* Next block */
- myCount >>= 1;
- }
- /* Add back to the stack */
- m_theStack.Add(Arrays.CopyOf(m_theChaining, NUMWORDS));
- }
- /**
- * Compress final block.
- *
- * @param pDataLen the data length
- */
- private void CompressFinalBlock(int pDataLen)
- {
- /* Initialise state and compress message */
- InitChunkBlock(pDataLen, true);
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- InitM(m_theBuffer);
- #else
- InitM(m_theBuffer, 0);
- #endif
- Compress();
- /* Finalise stack */
- ProcessStack();
- }
- /**
- * Process the stack.
- */
- private void ProcessStack()
- {
- /* Finalise stack */
- while (m_theStack.Count > 0)
- {
- /* Build the message to be hashed */
- uint[] myLeft = m_theStack[m_theStack.Count - 1];
- m_theStack.RemoveAt(m_theStack.Count - 1);
- Array.Copy(myLeft, 0, m_theM, 0, NUMWORDS);
- Array.Copy(m_theChaining, 0, m_theM, NUMWORDS, NUMWORDS);
- /* Create parent block */
- InitParentBlock();
- if (m_theStack.Count < 1)
- {
- SetRoot();
- }
- Compress();
- }
- }
- /**
- * Perform compression.
- */
- private void Compress()
- {
- /* Initialise the buffers */
- InitIndices();
- /* Loop through the rounds */
- for (int round = 0; round < ROUNDS - 1; round++)
- {
- /* Perform the round and permuteM */
- PerformRound();
- PermuteIndices();
- }
- PerformRound();
- AdjustChaining();
- }
- /**
- * Perform a round.
- */
- #if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER || UNITY_2021_2_OR_NEWER
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- #endif
- private void PerformRound()
- {
- /* Apply to columns of V */
- MixG(0, CHAINING0, CHAINING4, IV0, COUNT0);
- MixG(1, CHAINING1, CHAINING5, IV1, COUNT1);
- MixG(2, CHAINING2, CHAINING6, IV2, DATALEN);
- MixG(3, CHAINING3, CHAINING7, IV3, FLAGS);
- /* Apply to diagonals of V */
- MixG(4, CHAINING0, CHAINING5, IV2, FLAGS);
- MixG(5, CHAINING1, CHAINING6, IV3, COUNT0);
- MixG(6, CHAINING2, CHAINING7, IV0, COUNT1);
- MixG(7, CHAINING3, CHAINING4, IV1, DATALEN);
- }
- /**
- * Adjust Chaining after compression.
- */
- private void AdjustChaining()
- {
- /* If we are outputting */
- if (m_outputting)
- {
- /* Adjust full state */
- for (int i = 0; i < NUMWORDS; i++)
- {
- m_theV[i] ^= m_theV[i + NUMWORDS];
- m_theV[i + NUMWORDS] ^= m_theChaining[i];
- }
- /* Output state to buffer */
- Pack.UInt32_To_LE(m_theV, m_theBuffer, 0);
- m_thePos = 0;
- /* Else just build chain value */
- }
- else
- {
- /* Combine V into Chaining */
- for (int i = 0; i < NUMWORDS; i++)
- {
- m_theChaining[i] = m_theV[i] ^ m_theV[i + NUMWORDS];
- }
- }
- }
- /**
- * Mix function G.
- *
- * @param msgIdx the message index
- * @param posA position A in V
- * @param posB position B in V
- * @param posC position C in V
- * @param posD poistion D in V
- */
- #if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER || UNITY_2021_2_OR_NEWER
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- #endif
- private void MixG(int msgIdx, int posA, int posB, int posC, int posD)
- {
- /* Determine indices */
- int msg = msgIdx << 1;
- /* Perform the Round */
- m_theV[posA] += m_theV[posB] + m_theM[m_theIndices[msg++]];
- m_theV[posD] = Integers.RotateRight(m_theV[posD] ^ m_theV[posA], 16);
- m_theV[posC] += m_theV[posD];
- m_theV[posB] = Integers.RotateRight(m_theV[posB] ^ m_theV[posC], 12);
- m_theV[posA] += m_theV[posB] + m_theM[m_theIndices[msg]];
- m_theV[posD] = Integers.RotateRight(m_theV[posD] ^ m_theV[posA], 8);
- m_theV[posC] += m_theV[posD];
- m_theV[posB] = Integers.RotateRight(m_theV[posB] ^ m_theV[posC], 7);
- }
- /**
- * initialise the indices.
- */
- private void InitIndices()
- {
- for (byte i = 0; i < m_theIndices.Length; i++)
- {
- m_theIndices[i] = i;
- }
- }
- /**
- * PermuteIndices.
- */
- private void PermuteIndices()
- {
- for (byte i = 0; i < m_theIndices.Length; i++)
- {
- m_theIndices[i] = SIGMA[m_theIndices[i]];
- }
- }
- /**
- * Initialise null key.
- */
- private void InitNullKey()
- {
- Array.Copy(IV, 0, m_theK, 0, NUMWORDS);
- }
- /**
- * Initialise key.
- *
- * @param pKey the keyBytes
- */
- private void InitKey(byte[] pKey)
- {
- /* Copy message bytes into word array */
- Pack.LE_To_UInt32(pKey, 0, m_theK);
- m_theMode = KEYEDHASH;
- }
- /**
- * Initialise key from context.
- */
- private void InitKeyFromContext()
- {
- Array.Copy(m_theV, 0, m_theK, 0, NUMWORDS);
- m_theMode = DERIVEKEY;
- }
- /**
- * Initialise chunk block.
- *
- * @param pDataLen the dataLength
- * @param pFinal is this the final chunk?
- */
- private void InitChunkBlock(int pDataLen, bool pFinal)
- {
- /* Initialise the block */
- Array.Copy(m_theCurrBytes == 0 ? m_theK : m_theChaining, 0, m_theV, 0, NUMWORDS);
- Array.Copy(IV, 0, m_theV, NUMWORDS, NUMWORDS >> 1);
- m_theV[COUNT0] = (uint)m_theCounter;
- m_theV[COUNT1] = (uint)(m_theCounter >> Integers.NumBits);
- m_theV[DATALEN] = (uint)pDataLen;
- m_theV[FLAGS] = (uint)(m_theMode
- + (m_theCurrBytes == 0 ? CHUNKSTART : 0)
- + (pFinal ? CHUNKEND : 0));
- /* * Adjust block count */
- m_theCurrBytes += pDataLen;
- if (m_theCurrBytes >= CHUNKLEN)
- {
- IncrementBlockCount();
- m_theV[FLAGS] |= CHUNKEND;
- }
- /* If we are single chunk */
- if (pFinal && m_theStack.Count < 1)
- {
- SetRoot();
- }
- }
- /**
- * Initialise parent block.
- */
- private void InitParentBlock()
- {
- /* Initialise the block */
- Array.Copy(m_theK, 0, m_theV, 0, NUMWORDS);
- Array.Copy(IV, 0, m_theV, NUMWORDS, NUMWORDS >> 1);
- m_theV[COUNT0] = 0;
- m_theV[COUNT1] = 0;
- m_theV[DATALEN] = BLOCKLEN;
- m_theV[FLAGS] = (uint)(m_theMode | PARENT);
- }
- /**
- * Initialise output block.
- */
- private void NextOutputBlock()
- {
- /* Increment the counter */
- m_theCounter++;
- /* Initialise the block */
- Array.Copy(m_theChaining, 0, m_theV, 0, NUMWORDS);
- Array.Copy(IV, 0, m_theV, NUMWORDS, NUMWORDS >> 1);
- m_theV[COUNT0] = (uint)m_theCounter;
- m_theV[COUNT1] = (uint)(m_theCounter >> Integers.NumBits);
- m_theV[DATALEN] = (uint)m_theOutputDataLen;
- m_theV[FLAGS] = (uint)m_theOutputMode;
- /* Generate output */
- Compress();
- }
- /**
- * IncrementBlockCount.
- */
- private void IncrementBlockCount()
- {
- m_theCounter++;
- m_theCurrBytes = 0;
- }
- /**
- * ResetBlockCount.
- */
- private void ResetBlockCount()
- {
- m_theCounter = 0;
- m_theCurrBytes = 0;
- }
- /**
- * Set root indication.
- */
- private void SetRoot()
- {
- m_theV[FLAGS] |= ROOT;
- m_theOutputMode = (int)m_theV[FLAGS];
- m_theOutputDataLen = (int)m_theV[DATALEN];
- m_theCounter = 0;
- m_outputting = true;
- m_outputAvailable = -1;
- Array.Copy(m_theV, 0, m_theChaining, 0, NUMWORDS);
- }
- }
- }
- #pragma warning restore
- #endif
|