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

SHA1HashProvider

Implements SHA-1.
using System; namespace SshNet.Security.Cryptography { internal class SHA1HashProvider : HashProviderBase { private const int DigestSize = 20; private const int BlockSize = 64; private const uint Y1 = 1518500249; private const uint Y2 = 1859775393; private const uint Y3 = 2400959708; private const uint Y4 = 3395469782; private uint _h1; private uint _h2; private uint _h3; private uint _h4; private uint _h5; private readonly uint[] _words; private readonly byte[] _buffer; private int _bufferByteCount; private long _messageByteCount; public override int HashSize => 160; public override int InputBlockSize => 64; public override int OutputBlockSize => 64; public SHA1HashProvider() { _buffer = new byte[64]; _words = new uint[80]; InitializeHashValue(); } public override void HashCore(byte[] array, int ibStart, int cbSize) { _messageByteCount += cbSize; if (_bufferByteCount > 0 && cbSize + _bufferByteCount >= 64) { int num = 64 - _bufferByteCount; Buffer.BlockCopy(array, ibStart, _buffer, _bufferByteCount, num); ProcessBlock(_buffer, 0); ibStart += num; cbSize -= num; _bufferByteCount = 0; } while (cbSize >= 64) { ProcessBlock(array, ibStart); ibStart += 64; cbSize -= 64; } if (cbSize > 0) { Buffer.BlockCopy(array, ibStart, _buffer, _bufferByteCount, cbSize); _bufferByteCount += cbSize; } } public override byte[] HashFinal() { byte[] array = new byte[20]; long number = _messageByteCount << 3; long num = 64 - _messageByteCount % 64; if (num <= 8) num += 64; byte[] array2 = new byte[num]; array2[0] = 128; UInt64ToBigEndian((ulong)number, array2, array2.Length - 8); HashCore(array2, 0, array2.Length); UInt32ToBigEndian(_h1, array, 0); UInt32ToBigEndian(_h2, array, 4); UInt32ToBigEndian(_h3, array, 8); UInt32ToBigEndian(_h4, array, 12); UInt32ToBigEndian(_h5, array, 16); return array; } public override void Reset() { InitializeHashValue(); _messageByteCount = 0; _bufferByteCount = 0; for (int i = 0; i < _buffer.Length; i++) { _buffer[i] = 0; } for (int j = 0; j != _words.Length; j++) { _words[j] = 0; } } private void InitializeHashValue() { _h1 = 1732584193; _h2 = 4023233417; _h3 = 2562383102; _h4 = 271733878; _h5 = 3285377520; } private static uint F(uint u, uint v, uint w) { return (u & v) | (~u & w); } private static uint H(uint u, uint v, uint w) { return u ^ v ^ w; } private static uint G(uint u, uint v, uint w) { return (u & v) | (u & w) | (v & w); } private void ProcessBlock(byte[] buffer, int offset) { for (int i = 0; i < 16; i++) { _words[i] = BigEndianToUInt32(buffer, offset); offset += 4; } for (int j = 16; j < 80; j++) { uint num = _words[j - 3] ^ _words[j - 8] ^ _words[j - 14] ^ _words[j - 16]; _words[j] = ((num << 1) | (num >> 31)); } uint num2 = _h1; uint num3 = _h2; uint num4 = _h3; uint num5 = _h4; uint num6 = _h5; int num7 = 0; for (int k = 0; k < 4; k++) { num6 += ((num2 << 5) | (num2 >> 27)) + F(num3, num4, num5) + _words[num7++] + 1518500249; num3 = ((num3 << 30) | (num3 >> 2)); num5 += ((num6 << 5) | (num6 >> 27)) + F(num2, num3, num4) + _words[num7++] + 1518500249; num2 = ((num2 << 30) | (num2 >> 2)); num4 += ((num5 << 5) | (num5 >> 27)) + F(num6, num2, num3) + _words[num7++] + 1518500249; num6 = ((num6 << 30) | (num6 >> 2)); num3 += ((num4 << 5) | (num4 >> 27)) + F(num5, num6, num2) + _words[num7++] + 1518500249; num5 = ((num5 << 30) | (num5 >> 2)); num2 += ((num3 << 5) | (num3 >> 27)) + F(num4, num5, num6) + _words[num7++] + 1518500249; num4 = ((num4 << 30) | (num4 >> 2)); } for (int l = 0; l < 4; l++) { num6 += ((num2 << 5) | (num2 >> 27)) + H(num3, num4, num5) + _words[num7++] + 1859775393; num3 = ((num3 << 30) | (num3 >> 2)); num5 += ((num6 << 5) | (num6 >> 27)) + H(num2, num3, num4) + _words[num7++] + 1859775393; num2 = ((num2 << 30) | (num2 >> 2)); num4 += ((num5 << 5) | (num5 >> 27)) + H(num6, num2, num3) + _words[num7++] + 1859775393; num6 = ((num6 << 30) | (num6 >> 2)); num3 += ((num4 << 5) | (num4 >> 27)) + H(num5, num6, num2) + _words[num7++] + 1859775393; num5 = ((num5 << 30) | (num5 >> 2)); num2 += ((num3 << 5) | (num3 >> 27)) + H(num4, num5, num6) + _words[num7++] + 1859775393; num4 = ((num4 << 30) | (num4 >> 2)); } for (int m = 0; m < 4; m++) { num6 = (uint)((int)num6 + ((int)(((num2 << 5) | (num2 >> 27)) + G(num3, num4, num5) + _words[num7++]) + -1894007588)); num3 = ((num3 << 30) | (num3 >> 2)); num5 = (uint)((int)num5 + ((int)(((num6 << 5) | (num6 >> 27)) + G(num2, num3, num4) + _words[num7++]) + -1894007588)); num2 = ((num2 << 30) | (num2 >> 2)); num4 = (uint)((int)num4 + ((int)(((num5 << 5) | (num5 >> 27)) + G(num6, num2, num3) + _words[num7++]) + -1894007588)); num6 = ((num6 << 30) | (num6 >> 2)); num3 = (uint)((int)num3 + ((int)(((num4 << 5) | (num4 >> 27)) + G(num5, num6, num2) + _words[num7++]) + -1894007588)); num5 = ((num5 << 30) | (num5 >> 2)); num2 = (uint)((int)num2 + ((int)(((num3 << 5) | (num3 >> 27)) + G(num4, num5, num6) + _words[num7++]) + -1894007588)); num4 = ((num4 << 30) | (num4 >> 2)); } for (int n = 0; n < 4; n++) { num6 = (uint)((int)num6 + ((int)(((num2 << 5) | (num2 >> 27)) + H(num3, num4, num5) + _words[num7++]) + -899497514)); num3 = ((num3 << 30) | (num3 >> 2)); num5 = (uint)((int)num5 + ((int)(((num6 << 5) | (num6 >> 27)) + H(num2, num3, num4) + _words[num7++]) + -899497514)); num2 = ((num2 << 30) | (num2 >> 2)); num4 = (uint)((int)num4 + ((int)(((num5 << 5) | (num5 >> 27)) + H(num6, num2, num3) + _words[num7++]) + -899497514)); num6 = ((num6 << 30) | (num6 >> 2)); num3 = (uint)((int)num3 + ((int)(((num4 << 5) | (num4 >> 27)) + H(num5, num6, num2) + _words[num7++]) + -899497514)); num5 = ((num5 << 30) | (num5 >> 2)); num2 = (uint)((int)num2 + ((int)(((num3 << 5) | (num3 >> 27)) + H(num4, num5, num6) + _words[num7++]) + -899497514)); num4 = ((num4 << 30) | (num4 >> 2)); } _h1 += num2; _h2 += num3; _h3 += num4; _h4 += num5; _h5 += num6; } private static uint BigEndianToUInt32(byte[] bs, int off) { return (uint)((bs[off] << 24) | (bs[++off] << 16) | (bs[++off] << 8) | bs[++off]); } private static void UInt32ToBigEndian(uint number, byte[] buffer, int offset) { buffer[offset] = (byte)(number >> 24); buffer[offset + 1] = (byte)(number >> 16); buffer[offset + 2] = (byte)(number >> 8); buffer[offset + 3] = (byte)number; } private static void UInt64ToBigEndian(ulong number, byte[] buffer, int offset) { UInt32ToBigEndian((uint)(number >> 32), buffer, offset); UInt32ToBigEndian((uint)number, buffer, offset + 4); } } }