private void ProcessBlock(ref SHA512_DATA sha, byte[] block) { ulong[] W = new ulong[80]; ulong a, b, c, d, e, f, g, h; ulong temp, temp2; int t; /* Unpack the block into 80 64-bit words */ for (t = 0; t < 16; ++t) { W[t] = (((ulong)(block[t * 8 + 0])) << 56) | (((ulong)(block[t * 8 + 1])) << 48) | (((ulong)(block[t * 8 + 2])) << 40) | (((ulong)(block[t * 8 + 3])) << 32) | (((ulong)(block[t * 8 + 4])) << 24) | (((ulong)(block[t * 8 + 5])) << 16) | (((ulong)(block[t * 8 + 6])) << 8) | ((ulong)(block[t * 8 + 7])); } for (t = 16; t < 80; ++t) { W[t] = RHO1(W[t - 2]) + W[t - 7] + RHO0(W[t - 15]) + W[t - 16]; } /* Load the SHA-512 state into local variables */ a = sha.A; b = sha.B; c = sha.C; d = sha.D; e = sha.E; f = sha.F; g = sha.G; h = sha.H; /* Perform 80 rounds of hash computations */ for (t = 0; t < 80; ++t) { temp = h + SUM1(e) + CH(e, f, g) + K[t] + W[t]; temp2 = SUM0(a) + MAJ(a, b, c); h = g; g = f; f = e; e = d + temp; d = c; c = b; b = a; a = temp + temp2; } /* Combine the previous SHA-512 state with the new state */ sha.A += a; sha.B += b; sha.C += c; sha.D += d; sha.E += e; sha.F += f; sha.G += g; sha.H += h; }
public void Sha512_data(ref SHA512_DATA sha, ref byte[] buffer, uint len) { uint templen; /* Add to the total length of the input stream */ sha.totalLen += (ulong)len; /* Copy the blocks into the input buffer and process them */ while (len > 0) { if ((sha.inputLen == 0) && len >= 128) { /* Short cut: no point copying the data twice */ ProcessBlock(ref sha, buffer); buffer = ChangeBufPointer(buffer, 128); len -= 128; } else { templen = len; if (templen > (128 - sha.inputLen)) { templen = 128 - sha.inputLen; } BufCopy(ref sha.input, sha.inputLen, buffer, 0, templen); if ((sha.inputLen += templen) >= 128) { ProcessBlock(ref sha, sha.input); sha.inputLen = 0; } buffer = ChangeBufPointer(buffer, templen); len -= templen; } } }
private void Sha512_init(ref SHA512_DATA sha) { sha.input = new byte[128]; sha.inputLen = 0; sha.A = (ulong)(0x6a09e667f3bcc908); sha.B = (ulong)(0xbb67ae8584caa73b); sha.C = (ulong)(0x3c6ef372fe94f82b); sha.D = (ulong)(0xa54ff53a5f1d36f1); sha.E = (ulong)(0x510e527fade682d1); sha.F = (ulong)(0x9b05688c2b3e6c1f); sha.G = (ulong)(0x1f83d9abfb41bd6b); sha.H = (ulong)(0x5be0cd19137e2179); sha.totalLen = 0; }
public void Sha512_finalize(ref SHA512_DATA sha, byte[] hash) { ulong totalBits; /* Compute the final hash if necessary */ /* Pad the input data to a multiple of 1024 bits */ if (sha.inputLen >= (128 - 16)) { /* Need two blocks worth of padding */ sha.input[(sha.inputLen)++] = (byte)0x80; while (sha.inputLen < 128) { sha.input[(sha.inputLen)++] = (byte)0x00; } ProcessBlock(ref sha, sha.input); sha.inputLen = 0; } else { /* Need one block worth of padding */ sha.input[(sha.inputLen)++] = (byte)0x80; } while (sha.inputLen < (128 - 16)) { sha.input[(sha.inputLen)++] = (byte)0x00; } totalBits = (sha.totalLen << 3); BufSet(ref sha.input, (128 - 16), 0, 8); WriteLong(sha.input, 128 - 8, totalBits); ProcessBlock(ref sha, sha.input); /* Write the final hash value to the supplied buffer */ if (hash != null) { WriteLong(hash, 0, sha.A); WriteLong(hash, 8, sha.B); WriteLong(hash, 16, sha.C); WriteLong(hash, 24, sha.D); WriteLong(hash, 32, sha.E); WriteLong(hash, 40, sha.F); WriteLong(hash, 48, sha.G); WriteLong(hash, 56, sha.H); } }