<PackageReference Include="SshNet.Security.Cryptography" Version="1.2.0" />

SHA2HashProviderBase

namespace SshNet.Security.Cryptography { internal abstract class SHA2HashProviderBase : HashProviderBase { protected ulong H1; protected ulong H2; protected ulong H3; protected ulong H4; protected ulong H5; protected ulong H6; protected ulong H7; protected ulong H8; private readonly ulong[] _x; private int _offset; private readonly byte[] _buffer; private int _bufferOffset; private long _byteCount1; private long _byteCount2; private static readonly ulong[] K = new ulong[80] { 4794697086780616226, 8158064640168781261, 13096744586834688815, 16840607885511220156, 4131703408338449720, 6480981068601479193, 10538285296894168987, 12329834152419229976, 15566598209576043074, 1334009975649890238, 2608012711638119052, 6128411473006802146, 8268148722764581231, 9286055187155687089, 11230858885718282805, 13951009754708518548, 16472876342353939154, 17275323862435702243, 1135362057144423861, 2597628984639134821, 3308224258029322869, 5365058923640841347, 6679025012923562964, 8573033837759648693, 10970295158949994411, 12119686244451234320, 12683024718118986047, 13788192230050041572, 14330467153632333762, 15395433587784984357, 489312712824947311, 1452737877330783856, 2861767655752347644, 3322285676063803686, 5560940570517711597, 5996557281743188959, 7280758554555802590, 8532644243296465576, 9350256976987008742, 10552545826968843579, 11727347734174303076, 12113106623233404929, 14000437183269869457, 14369950271660146224, 15101387698204529176, 15463397548674623760, 17586052441742319658, 1182934255886127544, 1847814050463011016, 2177327727835720531, 2830643537854262169, 3796741975233480872, 4115178125766777443, 5681478168544905931, 6601373596472566643, 7507060721942968483, 8399075790359081724, 8693463985226723168, 9568029438360202098, 10144078919501101548, 10430055236837252648, 11840083180663258601, 13761210420658862357, 14299343276471374635, 14566680578165727644, 15097957966210449927, 16922976911328602910, 17689382322260857208, 500013540394364858, 748580250866718886, 1242879168328830382, 1977374033974150939, 2944078676154940804, 3659926193048069267, 4368137639120453308, 4836135668995329356, 5532061633213252278, 6448918945643986474, 6902733635092675308, 7801388544844847127 }; protected SHA2HashProviderBase() { _x = new ulong[80]; _buffer = new byte[8]; } public override void HashCore(byte[] array, int ibStart, int cbSize) { while (_bufferOffset != 0 && cbSize > 0) { Update(array[ibStart]); ibStart++; cbSize--; } while (cbSize > _buffer.Length) { ProcessWord(array, ibStart); ibStart += _buffer.Length; cbSize -= _buffer.Length; _byteCount1 += _buffer.Length; } while (cbSize > 0) { Update(array[ibStart]); ibStart++; cbSize--; } } public override void Reset() { _byteCount1 = 0; _byteCount2 = 0; _bufferOffset = 0; for (int i = 0; i < _buffer.Length; i++) { _buffer[i] = 0; } _offset = 0; for (int j = 0; j < _x.Length; j++) { _x[j] = 0; } } protected void Finish() { AdjustByteCounts(); long lowW = _byteCount1 << 3; long byteCount = _byteCount2; Update(128); while (_bufferOffset != 0) { Update(0); } ProcessLength(lowW, byteCount); ProcessBlock(); } private void Update(byte input) { _buffer[_bufferOffset++] = input; if (_bufferOffset == _buffer.Length) { ProcessWord(_buffer, 0); _bufferOffset = 0; } _byteCount1++; } private void ProcessWord(byte[] input, int inOff) { _x[_offset] = BE_To_UInt64(input, inOff); if (++_offset == 16) ProcessBlock(); } internal void ProcessLength(long lowW, long hiW) { if (_offset > 14) ProcessBlock(); _x[14] = (ulong)hiW; _x[15] = (ulong)lowW; } private void ProcessBlock() { AdjustByteCounts(); for (int i = 16; i <= 79; i++) { _x[i] = Sigma1(_x[i - 2]) + _x[i - 7] + Sigma0(_x[i - 15]) + _x[i - 16]; } ulong num = H1; ulong num2 = H2; ulong num3 = H3; ulong num4 = H4; ulong num5 = H5; ulong num6 = H6; ulong num7 = H7; ulong num8 = H8; int num9 = 0; for (int j = 0; j < 10; j++) { num8 += Sum1(num5) + Ch(num5, num6, num7) + K[num9] + _x[num9++]; num4 += num8; num8 += Sum0(num) + Maj(num, num2, num3); num7 += Sum1(num4) + Ch(num4, num5, num6) + K[num9] + _x[num9++]; num3 += num7; num7 += Sum0(num8) + Maj(num8, num, num2); num6 += Sum1(num3) + Ch(num3, num4, num5) + K[num9] + _x[num9++]; num2 += num6; num6 += Sum0(num7) + Maj(num7, num8, num); num5 += Sum1(num2) + Ch(num2, num3, num4) + K[num9] + _x[num9++]; num += num5; num5 += Sum0(num6) + Maj(num6, num7, num8); num4 += Sum1(num) + Ch(num, num2, num3) + K[num9] + _x[num9++]; num8 += num4; num4 += Sum0(num5) + Maj(num5, num6, num7); num3 += Sum1(num8) + Ch(num8, num, num2) + K[num9] + _x[num9++]; num7 += num3; num3 += Sum0(num4) + Maj(num4, num5, num6); num2 += Sum1(num7) + Ch(num7, num8, num) + K[num9] + _x[num9++]; num6 += num2; num2 += Sum0(num3) + Maj(num3, num4, num5); num += Sum1(num6) + Ch(num6, num7, num8) + K[num9] + _x[num9++]; num5 += num; num += Sum0(num2) + Maj(num2, num3, num4); } H1 += num; H2 += num2; H3 += num3; H4 += num4; H5 += num5; H6 += num6; H7 += num7; H8 += num8; _offset = 0; for (int k = 0; k < _x.Length; k++) { _x[k] = 0; } } private void AdjustByteCounts() { if (_byteCount1 > 2305843009213693951) { _byteCount2 += (long)((ulong)_byteCount1 >> 61); _byteCount1 &= 2305843009213693951; } } private static ulong Ch(ulong x, ulong y, ulong z) { return (x & y) ^ (~x & z); } private static ulong Maj(ulong x, ulong y, ulong z) { return (x & y) ^ (x & z) ^ (y & z); } private static ulong Sum0(ulong x) { return ((x << 36) | (x >> 28)) ^ ((x << 30) | (x >> 34)) ^ ((x << 25) | (x >> 39)); } private static ulong Sum1(ulong x) { return ((x << 50) | (x >> 14)) ^ ((x << 46) | (x >> 18)) ^ ((x << 23) | (x >> 41)); } private static ulong Sigma0(ulong x) { return ((x << 63) | (x >> 1)) ^ ((x << 56) | (x >> 8)) ^ (x >> 7); } private static ulong Sigma1(ulong x) { return ((x << 45) | (x >> 19)) ^ ((x << 3) | (x >> 61)) ^ (x >> 6); } private static void UInt32_To_BE(uint n, byte[] bs, int offset) { bs[offset] = (byte)(n >> 24); bs[++offset] = (byte)(n >> 16); bs[++offset] = (byte)(n >> 8); bs[++offset] = (byte)n; } protected static void UInt64_To_BE(ulong n, byte[] bs, int offset) { UInt32_To_BE((uint)(n >> 32), bs, offset); UInt32_To_BE((uint)n, bs, offset + 4); } private static ulong BE_To_UInt64(byte[] bs, int offset) { uint num = BE_To_UInt32(bs, offset); uint num2 = BE_To_UInt32(bs, offset + 4); return ((ulong)num << 32) | num2; } private static uint BE_To_UInt32(byte[] bs, int offset) { return (uint)((bs[offset] << 24) | (bs[++offset] << 16) | (bs[++offset] << 8) | bs[++offset]); } } }