Created
December 13, 2022 08:19
-
-
Save Infarh/7569103b56758771ba4357544768ddb0 to your computer and use it in GitHub Desktop.
Hash
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MD5 | |
{ | |
private MD5() { } | |
public static byte[] Compute(string str, Encoding? encoding = null) => Compute((encoding ?? Encoding.UTF8).GetBytes(str)); | |
private static void SetLength(byte[] buffer64, ulong length) | |
{ | |
buffer64[^8] = (byte)(length << 3); | |
buffer64[^7] = (byte)(length >> 5); | |
buffer64[^6] = (byte)(length >> 13); | |
buffer64[^5] = (byte)(length >> 21); | |
buffer64[^4] = (byte)(length >> 29); | |
buffer64[^3] = (byte)(length >> 37); | |
buffer64[^2] = (byte)(length >> 45); | |
buffer64[^1] = (byte)(length >> 53); | |
} | |
public static byte[] Compute(byte[] data) | |
{ | |
uint[] h = { 0x67452301U, 0xefcdab89U, 0x98badcfeU, 0x10325476U }; | |
const int length_0x80 = 1; | |
const int length_end = 8; | |
var length = data.Length; | |
var zero_length = 64 - length % 64 - length_0x80 - length_end; | |
if (zero_length < 0) zero_length += 64; | |
var buffer64_length = length + length_0x80 + zero_length + length_end; | |
var buffer64 = new byte[buffer64_length]; | |
Array.Copy(data, buffer64, length); | |
buffer64[length] = 0x80; | |
SetLength(buffer64, (ulong)length); | |
var words = new uint[16]; | |
for (var i = 0; i < buffer64_length / 64; i++) | |
{ | |
Buffer.BlockCopy(buffer64, i * 64, words, 0, 64); | |
Compute(words, ref h[0], ref h[1], ref h[2], ref h[3]); | |
} | |
var result_bytes = new byte[16]; | |
Buffer.BlockCopy(h, 0, result_bytes, 0, result_bytes.Length); | |
return result_bytes; | |
} | |
public static byte[] Compute(Stream data) | |
{ | |
uint[] result = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 }; | |
var buffer64 = new byte[64]; | |
var words = new uint[16]; | |
var completed = false; | |
var length = 0UL; | |
int readed; | |
do | |
{ | |
readed = data.FillBuffer(buffer64); | |
length += (ulong)readed; | |
if (readed < 64) | |
{ | |
Array.Clear(buffer64, readed, 64 - readed); | |
buffer64[readed] = 0x80; | |
if (64 - readed > 8) | |
{ | |
SetLength(buffer64, length); | |
completed = true; | |
} | |
} | |
Buffer.BlockCopy(buffer64, 0, words, 0, 64); | |
Compute(words, ref result[0], ref result[1], ref result[2], ref result[3]); | |
} | |
while (readed == 64); | |
if (readed > 0 && !completed) | |
{ | |
Array.Clear(buffer64, 0, 64); | |
SetLength(buffer64, length); | |
Buffer.BlockCopy(buffer64, 0, words, 0, 64); | |
Compute(words, ref result[0], ref result[1], ref result[2], ref result[3]); | |
} | |
var result_bytes = new byte[16]; | |
Buffer.BlockCopy(result, 0, result_bytes, 0, result_bytes.Length); | |
return result_bytes; | |
} | |
public static async Task<byte[]> ComputeAsync(Stream data, CancellationToken Cancel = default) | |
{ | |
uint[] result = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 }; | |
var buffer64 = new byte[64]; | |
var words = new uint[16]; | |
var completed = false; | |
var length = 0UL; | |
int readed; | |
do | |
{ | |
readed = await data.FillBufferAsync(buffer64, Cancel).ConfigureAwait(false); | |
length += (ulong)readed; | |
if (readed < 64) | |
{ | |
Array.Clear(buffer64, readed, 64 - readed); | |
buffer64[readed] = 0x80; | |
if (64 - readed > 8) | |
{ | |
SetLength(buffer64, length); | |
completed = true; | |
} | |
} | |
Buffer.BlockCopy(buffer64, 0, words, 0, 64); | |
Compute(words, ref result[0], ref result[1], ref result[2], ref result[3]); | |
} | |
while (readed == 64); | |
if (readed > 0 && !completed) | |
{ | |
Array.Clear(buffer64, 0, 64); | |
SetLength(buffer64, length); | |
Buffer.BlockCopy(buffer64, 0, words, 0, 64); | |
Compute(words, ref result[0], ref result[1], ref result[2], ref result[3]); | |
} | |
var result_bytes = new byte[16]; | |
Buffer.BlockCopy(result, 0, result_bytes, 0, result_bytes.Length); | |
return result_bytes; | |
} | |
private static void Compute(uint[] buffer16, ref uint a0, ref uint b0, ref uint c0, ref uint d0) | |
{ | |
var (A, B, C, D) = (a0, b0, c0, d0); | |
static uint LeftRotate(uint x, int c) => (x << c) | (x >> (32 - c)); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0xd76aa478 + buffer16[00], 07), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0xe8c7b756 + buffer16[01], 12), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0x242070db + buffer16[02], 17), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0xc1bdceee + buffer16[03], 22), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0xf57c0faf + buffer16[04], 07), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0x4787c62a + buffer16[05], 12), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0xa8304613 + buffer16[06], 17), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0xfd469501 + buffer16[07], 22), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0x698098d8 + buffer16[08], 07), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0x8b44f7af + buffer16[09], 12), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0xffff5bb1 + buffer16[10], 17), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0x895cd7be + buffer16[11], 22), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0x6b901122 + buffer16[12], 07), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0xfd987193 + buffer16[13], 12), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0xa679438e + buffer16[14], 17), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B & C | ~B & D) + 0x49b40821 + buffer16[15], 22), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0xf61e2562 + buffer16[(5 * 16 + 1) % 16], 05), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0xc040b340 + buffer16[(5 * 17 + 1) % 16], 09), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0x265e5a51 + buffer16[(5 * 18 + 1) % 16], 14), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0xe9b6c7aa + buffer16[(5 * 19 + 1) % 16], 20), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0xd62f105d + buffer16[(5 * 20 + 1) % 16], 05), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0x02441453 + buffer16[(5 * 21 + 1) % 16], 09), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0xd8a1e681 + buffer16[(5 * 22 + 1) % 16], 14), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0xe7d3fbc8 + buffer16[(5 * 23 + 1) % 16], 20), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0x21e1cde6 + buffer16[(5 * 24 + 1) % 16], 05), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0xc33707d6 + buffer16[(5 * 25 + 1) % 16], 09), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0xf4d50d87 + buffer16[(5 * 26 + 1) % 16], 14), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0x455a14ed + buffer16[(5 * 27 + 1) % 16], 20), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0xa9e3e905 + buffer16[(5 * 28 + 1) % 16], 05), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0xfcefa3f8 + buffer16[(5 * 29 + 1) % 16], 09), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0x676f02d9 + buffer16[(5 * 30 + 1) % 16], 14), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (D & B | ~D & C) + 0x8d2a4c8a + buffer16[(5 * 31 + 1) % 16], 20), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0xfffa3942 + buffer16[(3 * 32 + 5) % 16], 04), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0x8771f681 + buffer16[(3 * 33 + 5) % 16], 11), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0x6d9d6122 + buffer16[(3 * 34 + 5) % 16], 16), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0xfde5380c + buffer16[(3 * 35 + 5) % 16], 23), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0xa4beea44 + buffer16[(3 * 36 + 5) % 16], 04), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0x4bdecfa9 + buffer16[(3 * 37 + 5) % 16], 11), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0xf6bb4b60 + buffer16[(3 * 38 + 5) % 16], 16), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0xbebfbc70 + buffer16[(3 * 39 + 5) % 16], 23), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0x289b7ec6 + buffer16[(3 * 40 + 5) % 16], 04), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0xeaa127fa + buffer16[(3 * 41 + 5) % 16], 11), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0xd4ef3085 + buffer16[(3 * 42 + 5) % 16], 16), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0x04881d05 + buffer16[(3 * 43 + 5) % 16], 23), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0xd9d4d039 + buffer16[(3 * 44 + 5) % 16], 04), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0xe6db99e5 + buffer16[(3 * 45 + 5) % 16], 11), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0x1fa27cf8 + buffer16[(3 * 46 + 5) % 16], 16), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (B ^ C ^ D) + 0xc4ac5665 + buffer16[(3 * 47 + 5) % 16], 23), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0xf4292244 + buffer16[7 * 48 % 16], 06), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0x432aff97 + buffer16[7 * 49 % 16], 10), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0xab9423a7 + buffer16[7 * 50 % 16], 15), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0xfc93a039 + buffer16[7 * 51 % 16], 21), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0x655b59c3 + buffer16[7 * 52 % 16], 06), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0x8f0ccc92 + buffer16[7 * 53 % 16], 10), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0xffeff47d + buffer16[7 * 54 % 16], 15), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0x85845dd1 + buffer16[7 * 55 % 16], 21), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0x6fa87e4f + buffer16[7 * 56 % 16], 06), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0xfe2ce6e0 + buffer16[7 * 57 % 16], 10), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0xa3014314 + buffer16[7 * 58 % 16], 15), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0x4e0811a1 + buffer16[7 * 59 % 16], 21), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0xf7537e82 + buffer16[7 * 60 % 16], 06), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0xbd3af235 + buffer16[7 * 61 % 16], 10), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0x2ad7d2bb + buffer16[7 * 62 % 16], 15), B, C); | |
(A, B, C, D) = (D, B + LeftRotate(A + (C ^ (B | ~D)) + 0xeb86d391 + buffer16[7 * 63 % 16], 21), B, C); | |
a0 += A; | |
b0 += B; | |
c0 += C; | |
d0 += D; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class SHA256 | |
{ | |
private static readonly uint[] K = | |
{ | |
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, | |
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, | |
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, | |
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, | |
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, | |
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, | |
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, | |
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, | |
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, | |
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, | |
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, | |
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, | |
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, | |
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, | |
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, | |
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 | |
}; | |
private static void SetLength(byte[] buffer64, ulong length) | |
{ | |
buffer64[^8] = (byte)(length >> 53); | |
buffer64[^7] = (byte)(length >> 45); | |
buffer64[^6] = (byte)(length >> 37); | |
buffer64[^5] = (byte)(length >> 29); | |
buffer64[^4] = (byte)(length >> 21); | |
buffer64[^3] = (byte)(length >> 13); | |
buffer64[^2] = (byte)(length >> 5); | |
buffer64[^1] = (byte)(length << 3); | |
} | |
public static byte[] Compute(string str, Encoding? encoding = null) => Compute((encoding ?? Encoding.UTF8).GetBytes(str)); | |
public static byte[] Compute(byte[] data) | |
{ | |
uint[] h = | |
{ | |
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, | |
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 | |
}; | |
var length = (ulong)data.LongLength; | |
const int length_0x80 = 1; | |
const int length_end = 8; | |
var zero_length = 64 - data.LongLength % 64 - length_0x80 - length_end; | |
if (zero_length < 0) zero_length += 64; | |
var buffer64_length = data.LongLength + length_0x80 + zero_length + length_end; | |
var buffer64 = new byte[buffer64_length]; | |
Array.Copy(data, buffer64, (long)length); | |
buffer64[length] = 0x80; | |
SetLength(buffer64, length); | |
var words = new uint[64]; | |
for (var i = 0; i < buffer64.LongLength; i += 64) | |
{ | |
for (var (j, k) = (0, i); j < 16; j++, k = i + j * 4) | |
words[j] = (uint)buffer64[k] << 24 | (uint)buffer64[k + 1] << 16 | (uint)buffer64[k + 2] << 8 | buffer64[k + 3]; | |
Compute(words, | |
ref h[0], ref h[1], ref h[2], ref h[3], | |
ref h[4], ref h[5], ref h[6], ref h[7]); | |
} | |
var result = CreateResult(h); | |
return result; | |
} | |
private static int FillBuffer(Stream stream, byte[] buffer) | |
{ | |
var length = buffer.Length; | |
var readed = stream.Read(buffer, 0, length); | |
if (readed == 0) | |
return 0; | |
while (readed < length) | |
{ | |
var last_readed = stream.Read(buffer, readed, length - readed); | |
if (last_readed == 0) | |
return readed; | |
readed += last_readed; | |
} | |
return readed; | |
} | |
public static byte[] Compute(Stream data) | |
{ | |
uint[] h = | |
{ | |
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, | |
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 | |
}; | |
var buffer64 = new byte[64]; | |
var words = new uint[64]; | |
var completed = false; | |
var length = 0UL; | |
int readed; | |
do | |
{ | |
readed = FillBuffer(data, buffer64); | |
length += (ulong)readed; | |
if (readed < 64) | |
{ | |
Array.Clear(buffer64, readed, 64 - readed); | |
buffer64[readed] = 0x80; | |
if (64 - readed > 8) | |
{ | |
SetLength(buffer64, length); | |
completed = true; | |
} | |
} | |
for (var (j, k) = (0, 0); j < 16; j++, k = j * 4) | |
words[j] = (uint)buffer64[k] << 24 | (uint)buffer64[k + 1] << 16 | (uint)buffer64[k + 2] << 8 | buffer64[k + 3]; | |
Compute(words, | |
ref h[0], ref h[1], ref h[2], ref h[3], | |
ref h[4], ref h[5], ref h[6], ref h[7]); | |
} | |
while (readed == 64); | |
if (readed > 0 && !completed) | |
{ | |
Array.Clear(buffer64, 0, 64); | |
SetLength(buffer64, length); | |
for (var (j, k) = (0, 0); j < 16; j++, k = j * 4) | |
words[j] = (uint)buffer64[k] << 24 | (uint)buffer64[k + 1] << 16 | (uint)buffer64[k + 2] << 8 | buffer64[k + 3]; | |
Compute(words, | |
ref h[0], ref h[1], ref h[2], ref h[3], | |
ref h[4], ref h[5], ref h[6], ref h[7]); | |
} | |
var result = CreateResult(h); | |
return result; | |
} | |
private static async Task<int> FillBufferAsync(Stream stream, byte[] buffer, CancellationToken Cancel = default) | |
{ | |
var length = buffer.Length; | |
var readed = await stream.ReadAsync(buffer, 0, length, Cancel).ConfigureAwait(false); | |
if (readed == 0) | |
return 0; | |
while (readed < length) | |
{ | |
var last_readed = await stream.ReadAsync(buffer, readed, length - readed, Cancel).ConfigureAwait(false); | |
if (last_readed == 0) | |
return readed; | |
readed += last_readed; | |
} | |
return readed; | |
} | |
public static async Task<byte[]> ComputeAsync(Stream data, CancellationToken Cancel = default) | |
{ | |
uint[] h = | |
{ | |
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, | |
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 | |
}; | |
var buffer64 = new byte[64]; | |
var words = new uint[64]; | |
var completed = false; | |
var length = 0UL; | |
int readed; | |
do | |
{ | |
readed = await FillBufferAsync(data, buffer64, Cancel).ConfigureAwait(false); | |
length += (ulong)readed; | |
if (readed < 64) | |
{ | |
Array.Clear(buffer64, readed, 64 - readed); | |
buffer64[readed] = 0x80; | |
if (64 - readed > 8) | |
{ | |
SetLength(buffer64, length); | |
completed = true; | |
} | |
} | |
for (var (j, k) = (0, 0); j < 16; j++, k = j * 4) | |
words[j] = (uint)buffer64[k] << 24 | (uint)buffer64[k + 1] << 16 | (uint)buffer64[k + 2] << 8 | buffer64[k + 3]; | |
Compute(words, | |
ref h[0], ref h[1], ref h[2], ref h[3], | |
ref h[4], ref h[5], ref h[6], ref h[7]); | |
} | |
while (readed == 64); | |
if (readed > 0 && !completed) | |
{ | |
Array.Clear(buffer64, 0, 64); | |
SetLength(buffer64, length); | |
for (var (j, k) = (0, 0); j < 16; j++, k = j * 4) | |
words[j] = (uint)buffer64[k] << 24 | (uint)buffer64[k + 1] << 16 | (uint)buffer64[k + 2] << 8 | buffer64[k + 3]; | |
Compute(words, | |
ref h[0], ref h[1], ref h[2], ref h[3], | |
ref h[4], ref h[5], ref h[6], ref h[7]); | |
} | |
var result = CreateResult(h); | |
return result; | |
} | |
private static byte[] CreateResult(uint[] h) | |
{ | |
var result = new byte[32]; | |
for (var i = 0; i < 8; i++) | |
{ | |
result[4 * i + 0] = (byte)(h[i] >> 24); | |
result[4 * i + 1] = (byte)(h[i] >> 16); | |
result[4 * i + 2] = (byte)(h[i] >> 08); | |
result[4 * i + 3] = (byte)(h[i] >> 00); | |
} | |
return result; | |
} | |
private static void Compute(uint[] words, | |
ref uint h0, ref uint h1, ref uint h2, ref uint h3, | |
ref uint h4, ref uint h5, ref uint h6, ref uint h7) | |
{ | |
static uint S0(uint x) => RightRotate(x, 7) ^ RightRotate(x, 18) ^ x >> 3; | |
static uint S1(uint x) => RightRotate(x, 17) ^ RightRotate(x, 19) ^ x >> 10; | |
for (var j = 16; j < 64; j++) | |
words[j] = words[j - 16] + S0(words[j - 15]) + words[j - 7] + S1(words[j - 2]); | |
var (a, b, c, d, e, f, g, h) = (h0, h1, h2, h3, h4, h5, h6, h7); | |
for (var i = 0; i < 64; i++) | |
{ | |
static uint Ch(uint x, uint y, uint z) => x & y ^ ~x & z; | |
static uint Maj(uint x, uint y, uint z) => x & y ^ x & z ^ y & z; | |
static uint RightRotate(uint x, int c) => (x >> c) | (x << (32 - c)); | |
static uint E0(uint x) => RightRotate(x, 2) ^ RightRotate(x, 13) ^ RightRotate(x, 22); | |
static uint E1(uint x) => RightRotate(x, 6) ^ RightRotate(x, 11) ^ RightRotate(x, 25); | |
var t1 = h + E1(e) + Ch(e, f, g) + K[i] + words[i]; | |
var t2 = E0(a) + Maj(a, b, c); | |
(h, g, f, e, d, c, b, a) = (g, f, e, d + t1, c, b, a, t1 + t2); | |
} | |
(h0, h1, h2, h3, h4, h5, h6, h7) = (h0 + a, h1 + b, h2 + c, h3 + d, h4 + e, h5 + f, h6 + g, h7 + h); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class SHA512 | |
{ | |
private static readonly ulong[] K = | |
{ | |
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, | |
0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, | |
0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, | |
0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, | |
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab, | |
0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, | |
0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, | |
0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, | |
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, | |
0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, | |
0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, | |
0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, | |
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c, | |
0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6, | |
0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, | |
0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 | |
}; | |
private static void SetLength(byte[] buffer64, ulong length) | |
{ | |
buffer64[^8] = (byte)(length >> 53); | |
buffer64[^7] = (byte)(length >> 45); | |
buffer64[^6] = (byte)(length >> 37); | |
buffer64[^5] = (byte)(length >> 29); | |
buffer64[^4] = (byte)(length >> 21); | |
buffer64[^3] = (byte)(length >> 13); | |
buffer64[^2] = (byte)(length >> 5); | |
buffer64[^1] = (byte)(length << 3); | |
} | |
public static byte[] Compute(string str, Encoding? encoding = null) => Compute((encoding ?? Encoding.UTF8).GetBytes(str)); | |
public static byte[] Compute(byte[] data) | |
{ | |
ulong[] h = | |
{ | |
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, | |
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 | |
}; | |
var length = (ulong)data.LongLength; | |
const int length_0x80 = 1; | |
var l0 = 128 - (length % 128 + length_0x80); | |
var buffer128_length = length + l0 + 1; | |
if (l0 < 16) buffer128_length += 128; | |
var buffer128 = new byte[buffer128_length]; | |
Array.Copy(data, buffer128, (long)length); | |
buffer128[length] = 0x80; | |
SetLength(buffer128, length); | |
var words = new ulong[80]; | |
for (var i = 0; i < buffer128.LongLength; i += 128) | |
{ | |
for (var (j, k) = (0, i); j < 16; j++, k = i + j * 8) | |
words[j] = | |
(ulong)buffer128[k] << 56 | | |
(ulong)buffer128[k + 1] << 48 | | |
(ulong)buffer128[k + 2] << 40 | | |
(ulong)buffer128[k + 3] << 32 | | |
(ulong)buffer128[k + 4] << 24 | | |
(ulong)buffer128[k + 5] << 16 | | |
(ulong)buffer128[k + 6] << 8 | | |
buffer128[k + 7]; | |
Compute(words, | |
ref h[0], ref h[1], ref h[2], ref h[3], | |
ref h[4], ref h[5], ref h[6], ref h[7]); | |
} | |
var result = CreateResult(h); | |
return result; | |
} | |
private static int FillBuffer(Stream stream, byte[] buffer) | |
{ | |
var length = buffer.Length; | |
var readed = stream.Read(buffer, 0, length); | |
if (readed == 0) | |
return 0; | |
while (readed < length) | |
{ | |
var last_readed = stream.Read(buffer, readed, length - readed); | |
if (last_readed == 0) | |
return readed; | |
readed += last_readed; | |
} | |
return readed; | |
} | |
public static byte[] Compute(Stream data) | |
{ | |
ulong[] h = | |
{ | |
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, | |
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 | |
}; | |
var buffer128 = new byte[128]; | |
var words = new ulong[80]; | |
var completed = false; | |
var length = 0UL; | |
int readed; | |
do | |
{ | |
readed = FillBuffer(data, buffer128); | |
length += (ulong)readed; | |
if (readed < 128) | |
{ | |
Array.Clear(buffer128, readed, 128 - readed); | |
buffer128[readed] = 0x80; | |
if (128 - readed > 16) | |
{ | |
SetLength(buffer128, length); | |
completed = true; | |
} | |
} | |
for (var (j, k) = (0, 0); j < 16; j++, k = j * 8) | |
words[j] = | |
(ulong)buffer128[k] << 56 | | |
(ulong)buffer128[k + 1] << 48 | | |
(ulong)buffer128[k + 2] << 40 | | |
(ulong)buffer128[k + 3] << 32 | | |
(ulong)buffer128[k + 4] << 24 | | |
(ulong)buffer128[k + 5] << 16 | | |
(ulong)buffer128[k + 6] << 8 | | |
buffer128[k + 7]; | |
Compute(words, | |
ref h[0], ref h[1], ref h[2], ref h[3], | |
ref h[4], ref h[5], ref h[6], ref h[7]); | |
} | |
while (readed == 128); | |
if (readed > 0 && !completed) | |
{ | |
Array.Clear(buffer128, 0, 128); | |
SetLength(buffer128, length); | |
for (var (j, k) = (0, 0); j < 16; j++, k = j * 8) | |
words[j] = | |
(ulong)buffer128[k] << 56 | | |
(ulong)buffer128[k + 1] << 48 | | |
(ulong)buffer128[k + 2] << 40 | | |
(ulong)buffer128[k + 3] << 32 | | |
(ulong)buffer128[k + 4] << 24 | | |
(ulong)buffer128[k + 5] << 16 | | |
(ulong)buffer128[k + 6] << 8 | | |
buffer128[k + 7]; | |
Compute(words, | |
ref h[0], ref h[1], ref h[2], ref h[3], | |
ref h[4], ref h[5], ref h[6], ref h[7]); | |
} | |
var result = CreateResult(h); | |
return result; | |
} | |
private static async Task<int> FillBufferAsync(Stream stream, byte[] buffer, CancellationToken Cancel = default) | |
{ | |
var length = buffer.Length; | |
var readed = await stream.ReadAsync(buffer, 0, length, Cancel).ConfigureAwait(false); | |
if (readed == 0) | |
return 0; | |
while (readed < length) | |
{ | |
var last_readed = await stream.ReadAsync(buffer, readed, length - readed, Cancel).ConfigureAwait(false); | |
if (last_readed == 0) | |
return readed; | |
readed += last_readed; | |
} | |
return readed; | |
} | |
public static async Task<byte[]> ComputeAsync(Stream data, CancellationToken Cancel = default) | |
{ | |
ulong[] h = | |
{ | |
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, | |
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 | |
}; | |
var buffer128 = new byte[128]; | |
var words = new ulong[80]; | |
var completed = false; | |
var length = 0UL; | |
int readed; | |
do | |
{ | |
readed = await FillBufferAsync(data, buffer128, Cancel).ConfigureAwait(false); | |
length += (ulong)readed; | |
if (readed < 128) | |
{ | |
Array.Clear(buffer128, readed, 128 - readed); | |
buffer128[readed] = 0x80; | |
if (128 - readed > 16) | |
{ | |
SetLength(buffer128, length); | |
completed = true; | |
} | |
} | |
for (var (j, k) = (0, 0); j < 16; j++, k = j * 8) | |
words[j] = | |
(ulong)buffer128[k] << 56 | | |
(ulong)buffer128[k + 1] << 48 | | |
(ulong)buffer128[k + 2] << 40 | | |
(ulong)buffer128[k + 3] << 32 | | |
(ulong)buffer128[k + 4] << 24 | | |
(ulong)buffer128[k + 5] << 16 | | |
(ulong)buffer128[k + 6] << 8 | | |
buffer128[k + 7]; | |
Compute(words, | |
ref h[0], ref h[1], ref h[2], ref h[3], | |
ref h[4], ref h[5], ref h[6], ref h[7]); | |
} | |
while (readed == 128); | |
if (readed > 0 && !completed) | |
{ | |
Array.Clear(buffer128, 0, 128); | |
SetLength(buffer128, length); | |
for (var (j, k) = (0, 0); j < 16; j++, k = j * 8) | |
words[j] = | |
(ulong)buffer128[k] << 56 | | |
(ulong)buffer128[k + 1] << 48 | | |
(ulong)buffer128[k + 2] << 40 | | |
(ulong)buffer128[k + 3] << 32 | | |
(ulong)buffer128[k + 4] << 24 | | |
(ulong)buffer128[k + 5] << 16 | | |
(ulong)buffer128[k + 6] << 8 | | |
buffer128[k + 7]; | |
Compute(words, | |
ref h[0], ref h[1], ref h[2], ref h[3], | |
ref h[4], ref h[5], ref h[6], ref h[7]); | |
} | |
var result = CreateResult(h); | |
return result; | |
} | |
private static byte[] CreateResult(ulong[] h) | |
{ | |
var hash = new byte[64]; | |
for (var i = 0; i < 8; i++) | |
{ | |
hash[8 * i + 0] = (byte)(h[i] >> 56); | |
hash[8 * i + 1] = (byte)(h[i] >> 48); | |
hash[8 * i + 2] = (byte)(h[i] >> 40); | |
hash[8 * i + 3] = (byte)(h[i] >> 32); | |
hash[8 * i + 4] = (byte)(h[i] >> 24); | |
hash[8 * i + 5] = (byte)(h[i] >> 16); | |
hash[8 * i + 6] = (byte)(h[i] >> 08); | |
hash[8 * i + 7] = (byte)(h[i] >> 00); | |
} | |
return hash; | |
} | |
private static void Compute(ulong[] words, | |
ref ulong h0, ref ulong h1, ref ulong h2, ref ulong h3, | |
ref ulong h4, ref ulong h5, ref ulong h6, ref ulong h7) | |
{ | |
static ulong S0(ulong x) => RightRotate(x, 1) ^ RightRotate(x, 8) ^ x >> 7; | |
static ulong S1(ulong x) => RightRotate(x, 19) ^ RightRotate(x, 61) ^ x >> 6; | |
for (var j = 16; j < 80; j++) | |
words[j] = words[j - 16] + S0(words[j - 15]) + words[j - 7] + S1(words[j - 2]); | |
var (a, b, c, d, e, f, g, h) = (h0, h1, h2, h3, h4, h5, h6, h7); | |
for (var i = 0; i < 80; i += 1) | |
{ | |
static ulong Ch(ulong x, ulong y, ulong z) => x & y ^ ~x & z; | |
static ulong Maj(ulong x, ulong y, ulong z) => x & y ^ x & z ^ y & z; | |
static ulong RightRotate(ulong x, int c) => (x >> c) | (x << (64 - c)); | |
static ulong E0(ulong x) => RightRotate(x, 28) ^ RightRotate(x, 34) ^ RightRotate(x, 39); | |
static ulong E1(ulong x) => RightRotate(x, 14) ^ RightRotate(x, 18) ^ RightRotate(x, 41); | |
var t1 = h + E1(e) + Ch(e, f, g) + K[i] + words[i]; | |
var t2 = E0(a) + Maj(a, b, c); | |
(h, g, f, e, d, c, b, a) = (g, f, e, d + t1, c, b, a, t1 + t2); | |
} | |
(h0, h1, h2, h3, h4, h5, h6, h7) = (h0 + a, h1 + b, h2 + c, h3 + d, h4 + e, h5 + f, h6 + g, h7 + h); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment