static byte[] Sha512Algorithm(byte[] plaintext, Word64[] H0, int numberBits) { Block1024[] blocks = ConvertPaddedMessageToBlock1024Array(PadPlainText1024(plaintext)); // Define the hash variable and set its initial values. Word64[] H = H0; for (int i = 0; i < blocks.Length; i++) { Word64[] W = CreateMessageScheduleSha512(blocks[i]); // Set the working variables a,...,h to the current hash values. Word64 a = H[0]; Word64 b = H[1]; Word64 c = H[2]; Word64 d = H[3]; Word64 e = H[4]; Word64 f = H[5]; Word64 g = H[6]; Word64 h = H[7]; for (int t = 0; t < 80; t++) { Word64 T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[t] + W[t]; Word64 T2 = Sigma0_512(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; } // Update the current value of the hash H after processing block i. H[0] += a; H[1] += b; H[2] += c; H[3] += d; H[4] += e; H[5] += f; H[6] += g; H[7] += h; } // Concatenate all the Word64 Hash Values byte[] hash = ShaUtilities.Word64ArrayToByteArray(H); // The number of bytes in the final output hash int numberBytes = numberBits / 8; byte[] truncatedHash = new byte[numberBytes]; Array.Copy(hash, truncatedHash, numberBytes); return(truncatedHash); }
public byte[] Compute(byte[] message, int numberBits = 512) { DefineH0Sha512(); DefineK512(); byte[] paddedMessage = PadMessage1024(message); Block1024[] blocks = ConvertPaddedMessageToBlock1024Array(paddedMessage); Word64[] H = H0Sha512; for (int i = 0; i < blocks.Length; i++) { Word64[] W = CreateMessageScheduleSha512(blocks[i]); Word64 a = H[0]; Word64 b = H[1]; Word64 c = H[2]; Word64 d = H[3]; Word64 e = H[4]; Word64 f = H[5]; Word64 g = H[6]; Word64 h = H[7]; for (int t = 0; t < 80; t++) { Word64 T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[t] + W[t]; Word64 T2 = Sigma0_512(a) + Maj(a, b, c); h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2; } H[0] += a; H[1] += b; H[2] += c; H[3] += d; H[4] += e; H[5] += f; H[6] += g; H[7] += h; } byte[] hash = ShaUtil.Word64ArrayToByteArray(H); int numberBytes = numberBits / 8; byte[] truncatedHash = new byte[numberBytes]; Array.Copy(hash, truncatedHash, numberBytes); return(truncatedHash); }
public static Word64 ByteArrayToWord64(byte[] B, int startIndex) { // We assume: 0 <= startIndex < B. Length, and startIndex + 8 <= B.Length Word64 c = 256; Word64 output = 0; for (int i = startIndex; i < startIndex + 8; i++) { output = output * c + B[i]; } return(output); }
public static Word64[] ByteArrayToWord64Array(byte[] B) { // We assume B is not null, is not empty and number elements is divisible by 8 int numberWords = B.Length / 8; // 8 bytes for each Word32 Word64[] wordArray = new Word64[numberWords]; for (int i = 0; i < numberWords; i++) { wordArray[i] = ByteArrayToWord64(B, 8 * i); } return(wordArray); }
static Word64[] CreateMessageScheduleSha512(Block1024 block) { Word64[] W = new Word64[80]; for (int t = 0; t < 80; t++) { if (t < 16) { W[t] = block.words[t]; } else { W[t] = sigma1_512(W[t - 2]) + W[t - 7] + sigma0_512(W[t - 15]) + W[t - 16]; } } return(W); }
static Word64[] CreateMessageScheduleSha512(Block1024 block) { // The message schedule. Word64[] W = new Word64[80]; // Prepare the message schedule W. // The first 16 words in W are the same as the words of the block. // The remaining 80-16 =64 words in W are functions of the previously defined words. for (int t = 0; t < 80; t++) { if (t < 16) { W[t] = block.words[t]; } else { W[t] = sigma1_512(W[t - 2]) + W[t - 7] + sigma0_512(W[t - 15]) + W[t - 16]; } } return(W); }
static Word64 Sigma0_512(Word64 x) { return(RotR(28, x) ^ RotR(34, x) ^ RotR(39, x)); }
static Word64 Maj(Word64 x, Word64 y, Word64 z) { return((x & y) ^ (x & z) ^ (y & z)); }
static Word64 Ch(Word64 x, Word64 y, Word64 z) { return((x & y) ^ (~x & z)); }
public static byte[] Word64ToByteArray(Word64 x) { byte[] b = BitConverter.GetBytes(x); Array.Reverse(b); return(b); }
static Word64 ShR(int n, Word64 x) { // should have 0 <= n < 64 return(x >> n); }
static Word64 RotR(int n, Word64 x) { // should have 0 <= n < 64 return((x >> n) | (x << 64 - n)); }
static Word64 Sigma1_512(Word64 x) { return(RotR(14, x) ^ RotR(18, x) ^ RotR(41, x)); }
static Word64 sigma1_512(Word64 x) { return(RotR(19, x) ^ RotR(61, x) ^ ShR(6, x)); }
static Word64 sigma0_512(Word64 x) { return(RotR(1, x) ^ RotR(8, x) ^ ShR(7, x)); }
public static string Word64ToHexString(Word64 x) { return(ByteArrayToHexString(Word64ToByteArray(x))); }