<PackageReference Include="SshNet.Security.Cryptography" Version="1.1.0-beta1" />

MD5HashProvider

namespace SshNet.Security.Cryptography { internal class MD5HashProvider : HashProviderBase { private readonly byte[] _buffer = new byte[4]; private int _bufferOffset; private long _byteCount; private int _h1; private int _h2; private int _h3; private int _h4; private readonly int[] _x = new int[16]; private int _offset; private const int S11 = 7; private const int S12 = 12; private const int S13 = 17; private const int S14 = 22; private const int S21 = 5; private const int S22 = 9; private const int S23 = 14; private const int S24 = 20; private const int S31 = 4; private const int S32 = 11; private const int S33 = 16; private const int S34 = 23; private const int S41 = 6; private const int S42 = 10; private const int S43 = 15; private const int S44 = 21; public override int HashSize => 128; public override int InputBlockSize => 64; public override int OutputBlockSize => 64; public MD5HashProvider() { InternalInitialize(); } 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; _byteCount += _buffer.Length; } while (cbSize > 0) { Update(array[ibStart]); ibStart++; cbSize--; } } public override byte[] HashFinal() { long num = _byteCount << 3; Update(128); while (_bufferOffset != 0) { Update(0); } if (_offset > 14) ProcessBlock(); _x[14] = (int)(num & uint.MaxValue); _x[15] = (int)((ulong)num >> 32); ProcessBlock(); byte[] array = new byte[16]; UnpackWord(_h1, array, 0); UnpackWord(_h2, array, 4); UnpackWord(_h3, array, 8); UnpackWord(_h4, array, 12); Initialize(); return array; } public override void Initialize() { InternalInitialize(); } private void InternalInitialize() { _byteCount = 0; _bufferOffset = 0; for (int i = 0; i < 4; i++) { _buffer[i] = 0; } _h1 = 1732584193; _h2 = -271733879; _h3 = -1732584194; _h4 = 271733878; _offset = 0; for (int j = 0; j != _x.Length; j++) { _x[j] = 0; } } private void Update(byte input) { _buffer[_bufferOffset++] = input; if (_bufferOffset == _buffer.Length) { ProcessWord(_buffer, 0); _bufferOffset = 0; } _byteCount++; } private void ProcessWord(byte[] input, int inOff) { _x[_offset++] = ((input[inOff] & 255) | ((input[inOff + 1] & 255) << 8) | ((input[inOff + 2] & 255) << 16) | ((input[inOff + 3] & 255) << 24)); if (_offset == 16) ProcessBlock(); } private static void UnpackWord(int word, byte[] outBytes, int outOff) { outBytes[outOff] = (byte)word; outBytes[outOff + 1] = (byte)((uint)word >> 8); outBytes[outOff + 2] = (byte)((uint)word >> 16); outBytes[outOff + 3] = (byte)((uint)word >> 24); } private static int RotateLeft(int x, int n) { return (x << n) | (int)((uint)x >> 32 - n); } private static int F(int u, int v, int w) { return (u & v) | (~u & w); } private static int G(int u, int v, int w) { return (u & w) | (v & ~w); } private static int H(int u, int v, int w) { return u ^ v ^ w; } private static int K(int u, int v, int w) { return v ^ (u | ~w); } private void ProcessBlock() { int h = _h1; int h2 = _h2; int h3 = _h3; int h4 = _h4; h = RotateLeft(h + F(h2, h3, h4) + _x[0] + -680876936, 7) + h2; h4 = RotateLeft(h4 + F(h, h2, h3) + _x[1] + -389564586, 12) + h; h3 = RotateLeft(h3 + F(h4, h, h2) + _x[2] + 606105819, 17) + h4; h2 = RotateLeft(h2 + F(h3, h4, h) + _x[3] + -1044525330, 22) + h3; h = RotateLeft(h + F(h2, h3, h4) + _x[4] + -176418897, 7) + h2; h4 = RotateLeft(h4 + F(h, h2, h3) + _x[5] + 1200080426, 12) + h; h3 = RotateLeft(h3 + F(h4, h, h2) + _x[6] + -1473231341, 17) + h4; h2 = RotateLeft(h2 + F(h3, h4, h) + _x[7] + -45705983, 22) + h3; h = RotateLeft(h + F(h2, h3, h4) + _x[8] + 1770035416, 7) + h2; h4 = RotateLeft(h4 + F(h, h2, h3) + _x[9] + -1958414417, 12) + h; h3 = RotateLeft(h3 + F(h4, h, h2) + _x[10] + -42063, 17) + h4; h2 = RotateLeft(h2 + F(h3, h4, h) + _x[11] + -1990404162, 22) + h3; h = RotateLeft(h + F(h2, h3, h4) + _x[12] + 1804603682, 7) + h2; h4 = RotateLeft(h4 + F(h, h2, h3) + _x[13] + -40341101, 12) + h; h3 = RotateLeft(h3 + F(h4, h, h2) + _x[14] + -1502002290, 17) + h4; h2 = RotateLeft(h2 + F(h3, h4, h) + _x[15] + 1236535329, 22) + h3; h = RotateLeft(h + G(h2, h3, h4) + _x[1] + -165796510, 5) + h2; h4 = RotateLeft(h4 + G(h, h2, h3) + _x[6] + -1069501632, 9) + h; h3 = RotateLeft(h3 + G(h4, h, h2) + _x[11] + 643717713, 14) + h4; h2 = RotateLeft(h2 + G(h3, h4, h) + _x[0] + -373897302, 20) + h3; h = RotateLeft(h + G(h2, h3, h4) + _x[5] + -701558691, 5) + h2; h4 = RotateLeft(h4 + G(h, h2, h3) + _x[10] + 38016083, 9) + h; h3 = RotateLeft(h3 + G(h4, h, h2) + _x[15] + -660478335, 14) + h4; h2 = RotateLeft(h2 + G(h3, h4, h) + _x[4] + -405537848, 20) + h3; h = RotateLeft(h + G(h2, h3, h4) + _x[9] + 568446438, 5) + h2; h4 = RotateLeft(h4 + G(h, h2, h3) + _x[14] + -1019803690, 9) + h; h3 = RotateLeft(h3 + G(h4, h, h2) + _x[3] + -187363961, 14) + h4; h2 = RotateLeft(h2 + G(h3, h4, h) + _x[8] + 1163531501, 20) + h3; h = RotateLeft(h + G(h2, h3, h4) + _x[13] + -1444681467, 5) + h2; h4 = RotateLeft(h4 + G(h, h2, h3) + _x[2] + -51403784, 9) + h; h3 = RotateLeft(h3 + G(h4, h, h2) + _x[7] + 1735328473, 14) + h4; h2 = RotateLeft(h2 + G(h3, h4, h) + _x[12] + -1926607734, 20) + h3; h = RotateLeft(h + H(h2, h3, h4) + _x[5] + -378558, 4) + h2; h4 = RotateLeft(h4 + H(h, h2, h3) + _x[8] + -2022574463, 11) + h; h3 = RotateLeft(h3 + H(h4, h, h2) + _x[11] + 1839030562, 16) + h4; h2 = RotateLeft(h2 + H(h3, h4, h) + _x[14] + -35309556, 23) + h3; h = RotateLeft(h + H(h2, h3, h4) + _x[1] + -1530992060, 4) + h2; h4 = RotateLeft(h4 + H(h, h2, h3) + _x[4] + 1272893353, 11) + h; h3 = RotateLeft(h3 + H(h4, h, h2) + _x[7] + -155497632, 16) + h4; h2 = RotateLeft(h2 + H(h3, h4, h) + _x[10] + -1094730640, 23) + h3; h = RotateLeft(h + H(h2, h3, h4) + _x[13] + 681279174, 4) + h2; h4 = RotateLeft(h4 + H(h, h2, h3) + _x[0] + -358537222, 11) + h; h3 = RotateLeft(h3 + H(h4, h, h2) + _x[3] + -722521979, 16) + h4; h2 = RotateLeft(h2 + H(h3, h4, h) + _x[6] + 76029189, 23) + h3; h = RotateLeft(h + H(h2, h3, h4) + _x[9] + -640364487, 4) + h2; h4 = RotateLeft(h4 + H(h, h2, h3) + _x[12] + -421815835, 11) + h; h3 = RotateLeft(h3 + H(h4, h, h2) + _x[15] + 530742520, 16) + h4; h2 = RotateLeft(h2 + H(h3, h4, h) + _x[2] + -995338651, 23) + h3; h = RotateLeft(h + K(h2, h3, h4) + _x[0] + -198630844, 6) + h2; h4 = RotateLeft(h4 + K(h, h2, h3) + _x[7] + 1126891415, 10) + h; h3 = RotateLeft(h3 + K(h4, h, h2) + _x[14] + -1416354905, 15) + h4; h2 = RotateLeft(h2 + K(h3, h4, h) + _x[5] + -57434055, 21) + h3; h = RotateLeft(h + K(h2, h3, h4) + _x[12] + 1700485571, 6) + h2; h4 = RotateLeft(h4 + K(h, h2, h3) + _x[3] + -1894986606, 10) + h; h3 = RotateLeft(h3 + K(h4, h, h2) + _x[10] + -1051523, 15) + h4; h2 = RotateLeft(h2 + K(h3, h4, h) + _x[1] + -2054922799, 21) + h3; h = RotateLeft(h + K(h2, h3, h4) + _x[8] + 1873313359, 6) + h2; h4 = RotateLeft(h4 + K(h, h2, h3) + _x[15] + -30611744, 10) + h; h3 = RotateLeft(h3 + K(h4, h, h2) + _x[6] + -1560198380, 15) + h4; h2 = RotateLeft(h2 + K(h3, h4, h) + _x[13] + 1309151649, 21) + h3; h = RotateLeft(h + K(h2, h3, h4) + _x[4] + -145523070, 6) + h2; h4 = RotateLeft(h4 + K(h, h2, h3) + _x[11] + -1120210379, 10) + h; h3 = RotateLeft(h3 + K(h4, h, h2) + _x[2] + 718787259, 15) + h4; h2 = RotateLeft(h2 + K(h3, h4, h) + _x[9] + -343485551, 21) + h3; _h1 += h; _h2 += h2; _h3 += h3; _h4 += h4; _offset = 0; for (int i = 0; i != _x.Length; i++) { _x[i] = 0; } } } }