Skip to content

Commit dafc61c

Browse files
author
Eptagone
committed
Sha256 C# hash code
This file contains the sha256 algorith implemented in C#
1 parent 8bf1a12 commit dafc61c

File tree

2 files changed

+159
-2
lines changed

2 files changed

+159
-2
lines changed

.gitattributes

Lines changed: 0 additions & 2 deletions
This file was deleted.

sha256.cs

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
///-------------------------------------------------------------------------
2+
/// Author: Quetzal Rivera Email: quetzaldev122@outlook.com
3+
/// Bitcoin Donation Address: 3FUskDSShN4kh71NARrsbbWJmsXtWXkrC3
4+
/// Name: Sha256 algorithm Create Date: 25-12-2017
5+
/// Description: The cryptographic hash function SHA-256 algorithm
6+
/// implemented in C# language
7+
/// Revision History:
8+
/// Name: Creation Date: 25-12-2017 Descripcion: -
9+
///-------------------------------------------------------------------------
10+
using System;
11+
using System.Linq;
12+
13+
namespace PRUEBA
14+
{
15+
/// <summary>
16+
/// Sha256 Class.
17+
/// </summary>
18+
class Sha256
19+
{
20+
/// <summary>Sha256 instance</summary>
21+
/// You call a new Sha256 instance with:
22+
/// <c> Sha256 name = new Sha256(); </c>
23+
public Sha256() { }
24+
25+
/// <summary>Hash Function of message.</summary>
26+
/// <param name="message">Input message to hash</param>
27+
/// <returns>Hash of the message</returns>
28+
public byte[] HashComputation(byte[] message)
29+
{
30+
/// Step 1: Padding
31+
/// To ensure that the message has lenght multiple of 512 bits:
32+
/// ► First, a bit 1 is appended,
33+
/// ► next. k bits 0 e appended, with k being the smallest positive integer
34+
/// such that: message + 1 + k + L) mod 512, where L is the initial lenght message.
35+
/// ► finally, the lengh L is represented with exactly 64 bits, and these bits are added at
36+
/// the end of the message.
37+
/// The message shall always be padded, even if the initial lenght is already a multiple of 512.
38+
Byte[] L = BitConverter.GetBytes(Convert.ToUInt64(message.Length * 8)).Reverse().ToArray();
39+
// 1 byte = 8 bits | mod(%) | When A is multiple of B: A % B = 0
40+
int k = 0;
41+
while ((message.Length * 8 + 8 + k + 64) % 512 != 0) { k += 8; }
42+
byte[] paddedmessage = new byte[(message.Length * 8 + 8 + k + 64) / 8];
43+
44+
message.CopyTo(paddedmessage, 0);
45+
paddedmessage[message.Length] = 0x80; // 0x80 = b10000000 = the bit 1
46+
for (int i = 1; i < (1 + (k / 8)); i++)
47+
paddedmessage[message.Length + i] = 0x00; // 0x00 = b00000000
48+
L.CopyTo(paddedmessage, message.Length + 1 + (k / 8));
49+
50+
/// M[i] blocks are formed with paddedmessage.
51+
/// Each block constains 512 bits of paddedmessage.
52+
// 64 bytes = 512 bits
53+
int N = paddedmessage.Length / 64;
54+
byte[][] M = new byte[N][];
55+
for (int i = 0; i < N; i++)
56+
{
57+
byte[] temp = new byte[64];
58+
for (int j = 0; j < 64; j++)
59+
temp[j] = paddedmessage[(i * 64) + j];
60+
M[i] = temp;
61+
}
62+
63+
/// Step 2: Hash Computation
64+
/// ► First, eight variables are set to ther initial values, given by the first 32 bits of the
65+
/// fractional part of the square roots of the first 8 prime numbers.
66+
/// ► Next, the blocks M[i] are processed one at a time.
67+
uint[] H = new uint[8];
68+
H[0] = 0x6a09e667; H[1] = 0xbb67ae85; H[2] = 0x3c6ef372; H[3] = 0xa54ff53a;
69+
H[4] = 0x510e527f; H[5] = 0x9b05688c; H[6] = 0x1f83d9ab; H[7] = 0x5be0cd19;
70+
71+
for(int t = 0; t < N; t++)
72+
{
73+
/// For each block M, 64 words W[i] are constructed as follows:
74+
/// ► the first 16 are obteined by splitting M in 32-bit blocks
75+
/// M = W[1] || W[2] || ... || W[15] || W[16]
76+
/// ► the remaining 48 are obteined withe formula:
77+
/// W[i] = S1(W[i - 2]) + W[i - 7] + S0(W[i - 15]) + W[i - 16]
78+
uint[] W = new uint[64];
79+
for (int i = 0, j = 0; i < 16; ++i, j += 4)
80+
W[i] = (uint)((M[t][j] << 24) | (M[t][j + 1] << 16) | (M[t][j + 2] << 8) | (M[t][j + 3]));
81+
for (uint i = 16; i < 64; i++)
82+
W[i] = S1(W[i - 2]) + W[i - 7] + S0(W[i - 15]) + W[i - 16];
83+
84+
uint
85+
a = H[0],
86+
b = H[1],
87+
c = H[2],
88+
d = H[3],
89+
e = H[4],
90+
f = H[5],
91+
g = H[6],
92+
h = H[7],
93+
T1,
94+
T2;
95+
96+
for(int i = 0; i < 64; i++)
97+
{
98+
T1 = h + Z1(e) + Ch(e, f, g) + K[i] + W[i];
99+
T2 = Z0(a) + Maj(a, b, c);
100+
h = g;
101+
g = f;
102+
f = e;
103+
e = d + T1;
104+
d = c;
105+
c = b;
106+
b = a;
107+
a = T1 + T2;
108+
}
109+
110+
H[0] = H[0] + a;
111+
H[1] = H[1] + b;
112+
H[2] = H[2] + c;
113+
H[3] = H[3] + d;
114+
H[4] = H[4] + e;
115+
H[5] = H[5] + f;
116+
H[6] = H[6] + g;
117+
H[7] = H[7] + h;
118+
}
119+
/// The has of the message is the concatenation of the new variables H[i]
120+
/// after the las block has been processed.
121+
byte[] Hash = new byte[32];
122+
for (int i = 0; i < 8; i++)
123+
(BitConverter.GetBytes(H[i]).Reverse().ToArray()).CopyTo(Hash, i * 4);
124+
125+
return Hash; // Return the final hash of 32 bytes (256 bits)
126+
}
127+
128+
// Functions and constans
129+
/// <summary>Circular right shift of n bits of the binary word a.</summary>
130+
/// <param name="a">32-bits word </param>
131+
/// <param name="n">Bits for rotate shift </param>
132+
/// <returns>A new 32-bits word</returns>
133+
static uint RotR(uint a, byte n) => (((a) >> (n)) | ((a) << (32 - (n))));
134+
/// <summary>Right shift of n bits of the binary word a.</summary>
135+
/// <param name="a">32-bits word </param>
136+
/// <param name="n"> Bits for rotate shift </param>
137+
/// <returns></returns>
138+
static uint ShR(uint a, byte n) => (a >> n);
139+
140+
private static uint Ch(uint x, uint y, uint z) => (((x) & (y)) ^ ((~x) & (z)));
141+
private static uint Maj(uint x, uint y, uint z) => (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)));
142+
private static uint Z0(uint x) => (RotR(x, 2) ^ RotR(x, 13) ^ RotR(x, 22));
143+
private static uint Z1(uint x) => (RotR(x, 6) ^ RotR(x, 11) ^ RotR(x, 25));
144+
private static uint S0(uint x) => (RotR(x, 7) ^ RotR(x, 18) ^ ShR(x, 3));
145+
private static uint S1(uint x) => (RotR(x, 17) ^ RotR(x, 19) ^ ShR(x, 10));
146+
/// <summary>
147+
/// The 64 binary words K[i], given by the 32 first bits of the fractional parts
148+
/// of the cube root of the first 64 prime numbers.
149+
/// </summary>
150+
private static uint[] K = { 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
151+
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
152+
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
153+
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
154+
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
155+
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
156+
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
157+
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2};
158+
}
159+
}

0 commit comments

Comments
 (0)