/// <remarks> /// Convert to big endian integers, increment and convert back /// </remarks> private void Rotate(byte[] Counter) { // rotate the counter at 32 or 64 bit intervals if (RotationalAlignment == CounterAlignmentSizes.RAP32) { for (int i = 0; i < Counter.Length; i += 4) { IntUtils.Be32ToBytes(IntUtils.BytesToBe32(Counter, i) + 1, Counter, i); } } else { for (int i = 0; i < Counter.Length; i += 8) { IntUtils.Be64ToBytes(IntUtils.BytesToBe64(Counter, i) + 1, Counter, i); } } }
/// <summary> /// Do final processing and get the hash value /// </summary> /// /// <param name="Output">The Hash value container</param> /// <param name="OutOffset">The starting offset within the Output array</param> /// /// <returns>Size of Hash value, Always 64 bytes</returns> /// /// <exception cref="CryptoHashException">Thrown if Output array is too small</exception> public int DoFinal(byte[] Output, int OutOffset) { if (Output.Length - OutOffset < DigestSize) { throw new CryptoHashException("SHA512:DoFinal", "The Output buffer is too short!", new ArgumentOutOfRangeException()); } Finish(); IntUtils.Be64ToBytes(m_H0, Output, OutOffset); IntUtils.Be64ToBytes(m_H1, Output, OutOffset + 8); IntUtils.Be64ToBytes(m_H2, Output, OutOffset + 16); IntUtils.Be64ToBytes(m_H3, Output, OutOffset + 24); IntUtils.Be64ToBytes(m_H4, Output, OutOffset + 32); IntUtils.Be64ToBytes(m_H5, Output, OutOffset + 40); IntUtils.Be64ToBytes(m_H6, Output, OutOffset + 48); IntUtils.Be64ToBytes(m_H7, Output, OutOffset + 56); Reset(); return(DIGEST_SIZE); }
/// <summary> /// Do final processing and get the hash value /// </summary> /// /// <param name="Output">The Hash value container</param> /// <param name="OutOffset">The starting offset within the Output array</param> /// /// <returns>Size of Hash value</returns> /// /// <exception cref="CryptoHashException">Thrown if Output array is too small</exception> public int DoFinal(byte[] Output, int OutOffset) { if (Output.Length - OutOffset < DigestSize) { throw new CryptoHashException("Blake512:DoFinal", "The Output buffer is too short!", new ArgumentOutOfRangeException()); } byte[] msgLen = new byte[16]; IntUtils.Be64ToBytes(_T + ((ulong)_dataLen << 3), msgLen, 8); // special case of one padding byte if (_dataLen == PAD_LENGTH) { _T -= 8; BlockUpdate(new byte[1] { 0x81 }, 0, 1); } else { if (_dataLen < PAD_LENGTH) { // enough space to fill the block if (_dataLen == 0) { _isNullT = true; } _T -= TN_888 - ((ulong)_dataLen << 3); BlockUpdate(_Padding, 0, PAD_LENGTH - _dataLen); } else { // not enough space, need 2 compressions _T -= TN_1024 - ((ulong)_dataLen << 3); BlockUpdate(_Padding, 0, 128 - _dataLen); _T -= TN_888; BlockUpdate(_Padding, 1, PAD_LENGTH); _isNullT = true; } BlockUpdate(new byte[1] { 0x01 }, 0, 1); _T -= 8; } _T -= 128; BlockUpdate(msgLen, 0, 16); byte[] digest = new byte[64]; IntUtils.Be64ToBytes(_hashVal[0], digest, 0); IntUtils.Be64ToBytes(_hashVal[1], digest, 8); IntUtils.Be64ToBytes(_hashVal[2], digest, 16); IntUtils.Be64ToBytes(_hashVal[3], digest, 24); IntUtils.Be64ToBytes(_hashVal[4], digest, 32); IntUtils.Be64ToBytes(_hashVal[5], digest, 40); IntUtils.Be64ToBytes(_hashVal[6], digest, 48); IntUtils.Be64ToBytes(_hashVal[7], digest, 56); Buffer.BlockCopy(digest, 0, Output, OutOffset, digest.Length); Reset(); return(Output.Length); }