SHA-256(Source Code in C#) - Part I

SHA-256 (Secure Hash Algorithm), is one of the cryptographic hash function, commonly used in Blockchain. It generates an almost-unique 256-bit (32-byte) signature for a text. 

SHA-256 is successor hash functions to SHA-1. it is one of the strongest hash functions available and has not yet been compromised in any way.  

Here is source code written in C#. I will try to give more details in next Part II

using System;
using System.Text;
namespace SecureHashingProject
{
public class SecureHashingAlgorithm2
{
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
};
//initial hash value
private static readonly uint[] H =
{
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
};
static void Main()
{
var msg = Console.ReadLine();
if (string.IsNullOrEmpty(msg))
{
Console.WriteLine("No data to generate hash");
return;
}
var msgBytes = new byte[64];
var bitLength = new uint[2];
uint length = 0;
var hash = new byte[32];
var hashStr = string.Empty;
var data = Encoding.Default.GetBytes(msg);
for (uint i = 0; i < msg.Length; ++i)
{
msgBytes[length] = data[i];
length++;
if (length != 64) continue;
ComputingHash(ref msgBytes);
InitBitBlock(ref bitLength[0], ref length, 512);
length = 0;
}
GenerateSha256(ref msgBytes, ref bitLength, ref length, hash);
for (var i = 0; i < 32; i++)
hashStr += $"{hash[i]:X2}";
Console.WriteLine(hashStr);
Console.ReadLine();
}
private static void ComputingHash(ref byte[] data)
{
uint i, j;
var m = new uint[64];
//prepare message schedule 'm'
for (i = 0, j = 0; i < 16; ++i, j += 4)
m[i] = (uint)((data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | data[j + 3]);
for (; i < 64; ++i)
m[i] = Σ4(m[i - 2]) + m[i - 7] + Σ3(m[i - 15]) + m[i - 16];
//Initialise working variables a, b, c, d, e, f, g, h with previous hash value
var a = H[0];
var b = H[1];
var c = H[2];
var d = H[3];
var e = H[4];
var f = H[5];
var g = H[6];
var h = H[7];
//main loop
for (i = 0; i < 64; ++i)
{
var t1 = h + Σ1(e) + Choice(e, f, g) + K[i] + m[i];
var t2 = Σ0(a) + Majority(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
//compute the new intermediate hash value
H[0] += a;
H[1] += b;
H[2] += c;
H[3] += d;
H[4] += e;
H[5] += f;
H[6] += g;
H[7] += h;
}
private static void GenerateSha256(ref byte[] msgBytes, ref uint[] bitLength, ref uint length, byte[] hash)
{
var i = length;
if (length < 56)
{
msgBytes[i++] = 0x80; // add trailing '1' bit (+ 0's padding) to string
while (i < 56)
msgBytes[i++] = 0x00;
}
else
{
msgBytes[i++] = 0x80; // add trailing '1' bit (+ 0's padding) to string
while (i < 64)
msgBytes[i++] = 0x00;
ComputingHash(ref msgBytes);
}
InitBitBlock(ref bitLength[0], ref bitLength[1], length * 8);
msgBytes[63] = (byte)bitLength[0];
msgBytes[62] = (byte)(bitLength[0] >> 8);
msgBytes[61] = (byte)(bitLength[0] >> 16);
msgBytes[60] = (byte)(bitLength[0] >> 24);
msgBytes[59] = (byte)bitLength[1];
msgBytes[58] = (byte)(bitLength[1] >> 8);
msgBytes[57] = (byte)(bitLength[1] >> 16);
msgBytes[56] = (byte)(bitLength[1] >> 24);
ComputingHash(ref msgBytes);
for (i = 0; i < 4; ++i)
{
hash[i] = (byte)((H[0] >> (int)(24 - i * 8)) & 0x000000ff);
hash[i + 4] = (byte)((H[1] >> (int)(24 - i * 8)) & 0x000000ff);
hash[i + 8] = (byte)((H[2] >> (int)(24 - i * 8)) & 0x000000ff);
hash[i + 12] = (byte)((H[3] >> (int)(24 - i * 8)) & 0x000000ff);
hash[i + 16] = (byte)((H[4] >> (int)(24 - i * 8)) & 0x000000ff);
hash[i + 20] = (byte)((H[5] >> (int)(24 - i * 8)) & 0x000000ff);
hash[i + 24] = (byte)((H[6] >> (int)(24 - i * 8)) & 0x000000ff);
hash[i + 28] = (byte)((H[7] >> (int)(24 - i * 8)) & 0x000000ff);
}
}
private static uint Choice(uint x, uint y, uint z)
{
return (x & y) ^ (~x & z);
}
private static uint Majority(uint x, uint y, uint z)
{
return (x & y) ^ (x & z) ^ (y & z);
}
private static uint Σ0(uint x)
{
return RotateRight(x, 2) ^ RotateRight(x, 13) ^ RotateRight(x, 22);
}
private static uint Σ1(uint x)
{
return RotateRight(x, 6) ^ RotateRight(x, 11) ^ RotateRight(x, 25);
}
private static uint Σ3(uint x)
{
return RotateRight(x, 7) ^ RotateRight(x, 18) ^ (x >> 3);
}
private static uint Σ4(uint x)
{
return RotateRight(x, 17) ^ RotateRight(x, 19) ^ (x >> 10);
}
private static void InitBitBlock(ref uint a, ref uint b, uint c)
{
if (a > 0xffffffff - c) ++b; a += c;
}
private static uint RotateRight(uint a, byte b) //Rotates right (circular right shift) value a by b positions
{
return (a >> b) | (a << (32 - b));
}
}
}

Comments

Popular posts from this blog

SHA-256(Source Code in C# using .Net in-built Cryptography library) - Part II

Basic of Cryptography (Type of Cryptography)- Part II