#if NET20 using System; using System.Security; using System.Security.Cryptography; namespace Apewer.Internals { internal class SHA512CryptoServiceProvider : HashAlgorithm { private byte[] _buffer; private ulong _count; private ulong[] _stateSHA512; private ulong[] _W; private static readonly ulong[] _K = new ulong[80] { 4794697086780616226uL, 8158064640168781261uL, 13096744586834688815uL, 16840607885511220156uL, 4131703408338449720uL, 6480981068601479193uL, 10538285296894168987uL, 12329834152419229976uL, 15566598209576043074uL, 1334009975649890238uL, 2608012711638119052uL, 6128411473006802146uL, 8268148722764581231uL, 9286055187155687089uL, 11230858885718282805uL, 13951009754708518548uL, 16472876342353939154uL, 17275323862435702243uL, 1135362057144423861uL, 2597628984639134821uL, 3308224258029322869uL, 5365058923640841347uL, 6679025012923562964uL, 8573033837759648693uL, 10970295158949994411uL, 12119686244451234320uL, 12683024718118986047uL, 13788192230050041572uL, 14330467153632333762uL, 15395433587784984357uL, 489312712824947311uL, 1452737877330783856uL, 2861767655752347644uL, 3322285676063803686uL, 5560940570517711597uL, 5996557281743188959uL, 7280758554555802590uL, 8532644243296465576uL, 9350256976987008742uL, 10552545826968843579uL, 11727347734174303076uL, 12113106623233404929uL, 14000437183269869457uL, 14369950271660146224uL, 15101387698204529176uL, 15463397548674623760uL, 17586052441742319658uL, 1182934255886127544uL, 1847814050463011016uL, 2177327727835720531uL, 2830643537854262169uL, 3796741975233480872uL, 4115178125766777443uL, 5681478168544905931uL, 6601373596472566643uL, 7507060721942968483uL, 8399075790359081724uL, 8693463985226723168uL, 9568029438360202098uL, 10144078919501101548uL, 10430055236837252648uL, 11840083180663258601uL, 13761210420658862357uL, 14299343276471374635uL, 14566680578165727644uL, 15097957966210449927uL, 16922976911328602910uL, 17689382322260857208uL, 500013540394364858uL, 748580250866718886uL, 1242879168328830382uL, 1977374033974150939uL, 2944078676154940804uL, 3659926193048069267uL, 4368137639120453308uL, 4836135668995329356uL, 5532061633213252278uL, 6448918945643986474uL, 6902733635092675308uL, 7801388544844847127uL }; public SHA512CryptoServiceProvider() { HashSizeValue = 512; _stateSHA512 = new ulong[8]; _buffer = new byte[128]; _W = new ulong[80]; InitializeState(); } public override void Initialize() { InitializeState(); Array.Clear(_buffer, 0, _buffer.Length); Array.Clear(_W, 0, _W.Length); } [SecuritySafeCritical] protected override void HashCore(byte[] rgb, int ibStart, int cbSize) { _HashData(rgb, ibStart, cbSize); } [SecuritySafeCritical] protected override byte[] HashFinal() { return _EndHash(); } private void InitializeState() { _count = 0uL; _stateSHA512[0] = 7640891576956012808uL; _stateSHA512[1] = 13503953896175478587uL; _stateSHA512[2] = 4354685564936845355uL; _stateSHA512[3] = 11912009170470909681uL; _stateSHA512[4] = 5840696475078001361uL; _stateSHA512[5] = 11170449401992604703uL; _stateSHA512[6] = 2270897969802886507uL; _stateSHA512[7] = 6620516959819538809uL; } [SecurityCritical] private unsafe void _HashData(byte[] partIn, int ibStart, int cbSize) { int num = cbSize; int num2 = ibStart; int num3 = (int)(_count & 0x7F); _count += (ulong)num; fixed (ulong* state = _stateSHA512) { fixed (byte* block = _buffer) { fixed (ulong* expandedBuffer = _W) { if (num3 > 0 && num3 + num >= 128) { Array.Copy(partIn, num2, _buffer, num3, 128 - num3); num2 += 128 - num3; num -= 128 - num3; SHATransform(expandedBuffer, state, block); num3 = 0; } while (num >= 128) { Array.Copy(partIn, num2, _buffer, 0, 128); num2 += 128; num -= 128; SHATransform(expandedBuffer, state, block); } if (num > 0) { Array.Copy(partIn, num2, _buffer, num3, num); } } } } } [SecurityCritical] private byte[] _EndHash() { byte[] array = new byte[64]; int num = 128 - (int)(_count & 0x7F); if (num <= 16) { num += 128; } byte[] array2 = new byte[num]; array2[0] = 128; ulong num2 = _count * 8; array2[num - 8] = (byte)((num2 >> 56) & 0xFF); array2[num - 7] = (byte)((num2 >> 48) & 0xFF); array2[num - 6] = (byte)((num2 >> 40) & 0xFF); array2[num - 5] = (byte)((num2 >> 32) & 0xFF); array2[num - 4] = (byte)((num2 >> 24) & 0xFF); array2[num - 3] = (byte)((num2 >> 16) & 0xFF); array2[num - 2] = (byte)((num2 >> 8) & 0xFF); array2[num - 1] = (byte)(num2 & 0xFF); _HashData(array2, 0, array2.Length); QuadWordToBigEndian(array, _stateSHA512, 8); HashValue = array; return array; } [SecurityCritical] private unsafe static void SHATransform(ulong* expandedBuffer, ulong* state, byte* block) { ulong num = *state; ulong num2 = state[1]; ulong num3 = state[2]; ulong num4 = state[3]; ulong num5 = state[4]; ulong num6 = state[5]; ulong num7 = state[6]; ulong num8 = state[7]; QuadWordFromBigEndian(expandedBuffer, 16, block); SHA512Expand(expandedBuffer); int num9; for (num9 = 0; num9 < 80; num9++) { ulong num10 = num8 + Sigma_1(num5) + Ch(num5, num6, num7) + _K[num9] + expandedBuffer[num9]; ulong num11 = num4 + num10; ulong num12 = num10 + Sigma_0(num) + Maj(num, num2, num3); num9++; num10 = num7 + Sigma_1(num11) + Ch(num11, num5, num6) + _K[num9] + expandedBuffer[num9]; ulong num13 = num3 + num10; ulong num14 = num10 + Sigma_0(num12) + Maj(num12, num, num2); num9++; num10 = num6 + Sigma_1(num13) + Ch(num13, num11, num5) + _K[num9] + expandedBuffer[num9]; ulong num15 = num2 + num10; ulong num16 = num10 + Sigma_0(num14) + Maj(num14, num12, num); num9++; num10 = num5 + Sigma_1(num15) + Ch(num15, num13, num11) + _K[num9] + expandedBuffer[num9]; ulong num17 = num + num10; ulong num18 = num10 + Sigma_0(num16) + Maj(num16, num14, num12); num9++; num10 = num11 + Sigma_1(num17) + Ch(num17, num15, num13) + _K[num9] + expandedBuffer[num9]; num8 = num12 + num10; num4 = num10 + Sigma_0(num18) + Maj(num18, num16, num14); num9++; num10 = num13 + Sigma_1(num8) + Ch(num8, num17, num15) + _K[num9] + expandedBuffer[num9]; num7 = num14 + num10; num3 = num10 + Sigma_0(num4) + Maj(num4, num18, num16); num9++; num10 = num15 + Sigma_1(num7) + Ch(num7, num8, num17) + _K[num9] + expandedBuffer[num9]; num6 = num16 + num10; num2 = num10 + Sigma_0(num3) + Maj(num3, num4, num18); num9++; num10 = num17 + Sigma_1(num6) + Ch(num6, num7, num8) + _K[num9] + expandedBuffer[num9]; num5 = num18 + num10; num = num10 + Sigma_0(num2) + Maj(num2, num3, num4); } *state += num; state[1] += num2; state[2] += num3; state[3] += num4; state[4] += num5; state[5] += num6; state[6] += num7; state[7] += num8; } private static ulong RotateRight(ulong x, int n) { return (x >> n) | (x << 64 - n); } private static ulong Ch(ulong x, ulong y, ulong z) { return (x & y) ^ (ulong)(((long)x ^ -1L) & (long)z); } private static ulong Maj(ulong x, ulong y, ulong z) { return (x & y) ^ (x & z) ^ (y & z); } private static ulong Sigma_0(ulong x) { return RotateRight(x, 28) ^ RotateRight(x, 34) ^ RotateRight(x, 39); } private static ulong Sigma_1(ulong x) { return RotateRight(x, 14) ^ RotateRight(x, 18) ^ RotateRight(x, 41); } private static ulong sigma_0(ulong x) { return RotateRight(x, 1) ^ RotateRight(x, 8) ^ (x >> 7); } private static ulong sigma_1(ulong x) { return RotateRight(x, 19) ^ RotateRight(x, 61) ^ (x >> 6); } [SecurityCritical] private unsafe static void SHA512Expand(ulong* x) { for (int i = 16; i < 80; i++) { x[i] = sigma_1(x[i - 2]) + x[i - 7] + sigma_0(x[i - 15]) + x[i - 16]; } } private static void QuadWordToBigEndian(byte[] block, ulong[] x, int digits) { int num = 0; int num2 = 0; while (num < digits) { block[num2] = (byte)((x[num] >> 56) & 0xFF); block[num2 + 1] = (byte)((x[num] >> 48) & 0xFF); block[num2 + 2] = (byte)((x[num] >> 40) & 0xFF); block[num2 + 3] = (byte)((x[num] >> 32) & 0xFF); block[num2 + 4] = (byte)((x[num] >> 24) & 0xFF); block[num2 + 5] = (byte)((x[num] >> 16) & 0xFF); block[num2 + 6] = (byte)((x[num] >> 8) & 0xFF); block[num2 + 7] = (byte)(x[num] & 0xFF); num++; num2 += 8; } } [SecurityCritical] private unsafe static void QuadWordFromBigEndian(ulong* x, int digits, byte* block) { int num = 0; int num2 = 0; while (num < digits) { x[num] = (((ulong)block[num2] << 56) | ((ulong)block[num2 + 1] << 48) | ((ulong)block[num2 + 2] << 40) | ((ulong)block[num2 + 3] << 32) | ((ulong)block[num2 + 4] << 24) | ((ulong)block[num2 + 5] << 16) | ((ulong)block[num2 + 6] << 8) | block[num2 + 7]); num++; num2 += 8; } } } } #endif