1+ // Single file sha256
2+ // https://github.com/LekKit/sha256
3+
4+ #include < stdio.h>
5+ #include < string.h>
6+
7+ namespace sha256 {
8+
9+ struct sha256_buff {
10+ unsigned long data_size;
11+ unsigned int h[8 ];
12+ unsigned char last_chunk[64 ];
13+ unsigned char chunk_size;
14+ };
15+
16+ void sha256_init (struct sha256_buff * buff)
17+ {
18+ buff->h [0 ] = 0x6a09e667 ;
19+ buff->h [1 ] = 0xbb67ae85 ;
20+ buff->h [2 ] = 0x3c6ef372 ;
21+ buff->h [3 ] = 0xa54ff53a ;
22+ buff->h [4 ] = 0x510e527f ;
23+ buff->h [5 ] = 0x9b05688c ;
24+ buff->h [6 ] = 0x1f83d9ab ;
25+ buff->h [7 ] = 0x5be0cd19 ;
26+ buff->data_size = 0 ;
27+ buff->chunk_size = 0 ;
28+ }
29+
30+ static const unsigned int k[64 ] = {
31+ 0x428a2f98 , 0x71374491 , 0xb5c0fbcf , 0xe9b5dba5 , 0x3956c25b , 0x59f111f1 , 0x923f82a4 , 0xab1c5ed5 ,
32+ 0xd807aa98 , 0x12835b01 , 0x243185be , 0x550c7dc3 , 0x72be5d74 , 0x80deb1fe , 0x9bdc06a7 , 0xc19bf174 ,
33+ 0xe49b69c1 , 0xefbe4786 , 0x0fc19dc6 , 0x240ca1cc , 0x2de92c6f , 0x4a7484aa , 0x5cb0a9dc , 0x76f988da ,
34+ 0x983e5152 , 0xa831c66d , 0xb00327c8 , 0xbf597fc7 , 0xc6e00bf3 , 0xd5a79147 , 0x06ca6351 , 0x14292967 ,
35+ 0x27b70a85 , 0x2e1b2138 , 0x4d2c6dfc , 0x53380d13 , 0x650a7354 , 0x766a0abb , 0x81c2c92e , 0x92722c85 ,
36+ 0xa2bfe8a1 , 0xa81a664b , 0xc24b8b70 , 0xc76c51a3 , 0xd192e819 , 0xd6990624 , 0xf40e3585 , 0x106aa070 ,
37+ 0x19a4c116 , 0x1e376c08 , 0x2748774c , 0x34b0bcb5 , 0x391c0cb3 , 0x4ed8aa4a , 0x5b9cca4f , 0x682e6ff3 ,
38+ 0x748f82ee , 0x78a5636f , 0x84c87814 , 0x8cc70208 , 0x90befffa , 0xa4506ceb , 0xbef9a3f7 , 0xc67178f2 };
39+
40+ #define rotate_r (val, bits ) (val >> bits | val << (32 - bits))
41+
42+ static void sha256_calc_chunk (struct sha256_buff * buff, const unsigned char * chunk)
43+ {
44+ unsigned int w[64 ];
45+ unsigned int tv[8 ];
46+ unsigned int i;
47+
48+ for (i = 0 ; i < 16 ; ++i) {
49+ w[i] = (unsigned int ) chunk[0 ] << 24 | (unsigned int ) chunk[1 ] << 16
50+ | (unsigned int ) chunk[2 ] << 8 | (unsigned int ) chunk[3 ];
51+ chunk += 4 ;
52+ }
53+
54+ for (i = 16 ; i < 64 ; ++i) {
55+ unsigned int s0 = rotate_r (w[i - 15 ], 7 ) ^ rotate_r (w[i - 15 ], 18 ) ^ (w[i - 15 ] >> 3 );
56+ unsigned int s1 = rotate_r (w[i - 2 ], 17 ) ^ rotate_r (w[i - 2 ], 19 ) ^ (w[i - 2 ] >> 10 );
57+ w[i] = w[i - 16 ] + s0 + w[i - 7 ] + s1;
58+ }
59+
60+ for (i = 0 ; i < 8 ; ++i)
61+ tv[i] = buff->h [i];
62+
63+ for (i = 0 ; i < 64 ; ++i) {
64+ unsigned int S1 = rotate_r (tv[4 ], 6 ) ^ rotate_r (tv[4 ], 11 ) ^ rotate_r (tv[4 ], 25 );
65+ unsigned int ch = (tv[4 ] & tv[5 ]) ^ (~tv[4 ] & tv[6 ]);
66+ unsigned int temp1 = tv[7 ] + S1 + ch + k[i] + w[i];
67+ unsigned int S0 = rotate_r (tv[0 ], 2 ) ^ rotate_r (tv[0 ], 13 ) ^ rotate_r (tv[0 ], 22 );
68+ unsigned int maj = (tv[0 ] & tv[1 ]) ^ (tv[0 ] & tv[2 ]) ^ (tv[1 ] & tv[2 ]);
69+ unsigned int temp2 = S0 + maj;
70+
71+ tv[7 ] = tv[6 ];
72+ tv[6 ] = tv[5 ];
73+ tv[5 ] = tv[4 ];
74+ tv[4 ] = tv[3 ] + temp1;
75+ tv[3 ] = tv[2 ];
76+ tv[2 ] = tv[1 ];
77+ tv[1 ] = tv[0 ];
78+ tv[0 ] = temp1 + temp2;
79+ }
80+
81+ for (i = 0 ; i < 8 ; ++i)
82+ buff->h [i] += tv[i];
83+ }
84+
85+ void sha256_update (struct sha256_buff * buff, const void * data, unsigned long size)
86+ {
87+ const unsigned char * ptr = (const unsigned char *) data;
88+ buff->data_size += size;
89+ /* If there is data left in buff, concatenate it to process as new chunk */
90+ if (size + buff->chunk_size >= 64 ) {
91+ unsigned char tmp_chunk[64 ];
92+ memcpy (tmp_chunk, buff->last_chunk , buff->chunk_size );
93+ memcpy (tmp_chunk + buff->chunk_size , ptr, 64 - buff->chunk_size );
94+ ptr += (64 - buff->chunk_size );
95+ size -= (64 - buff->chunk_size );
96+ buff->chunk_size = 0 ;
97+ sha256_calc_chunk (buff, tmp_chunk);
98+ }
99+ /* Run over data chunks */
100+ while (size >= 64 ) {
101+ sha256_calc_chunk (buff, ptr);
102+ ptr += 64 ;
103+ size -= 64 ;
104+ }
105+
106+ /* Save remaining data in buff, will be reused on next call or finalize */
107+ memcpy (buff->last_chunk + buff->chunk_size , ptr, size);
108+ buff->chunk_size += size;
109+ }
110+
111+ void sha256_finalize (struct sha256_buff * buff)
112+ {
113+ buff->last_chunk [buff->chunk_size ] = 0x80 ;
114+ buff->chunk_size ++;
115+ memset (buff->last_chunk + buff->chunk_size , 0 , 64 - buff->chunk_size );
116+
117+ /* If there isn't enough space to fit int64, pad chunk with zeroes and prepare next chunk */
118+ if (buff->chunk_size > 56 ) {
119+ sha256_calc_chunk (buff, buff->last_chunk );
120+ memset (buff->last_chunk , 0 , 64 );
121+ }
122+
123+ /* Add total size as big-endian int64 x8 */
124+ unsigned long size = buff->data_size * 8 ;
125+ int i;
126+ for (i = 8 ; i > 0 ; --i) {
127+ buff->last_chunk [55 + i] = size & 255 ;
128+ size >>= 8 ;
129+ }
130+
131+ sha256_calc_chunk (buff, buff->last_chunk );
132+ }
133+
134+ void hash_it (const unsigned char * data, unsigned long data_size, unsigned char * hash)
135+ {
136+ struct sha256_buff buff;
137+ sha256_init (&buff);
138+ sha256_update (&buff, data, data_size);
139+ sha256_finalize (&buff);
140+ for (int i = 0 ; i < 8 ; i++) {
141+ hash[i * 4 ] = (buff.h [i] >> 24 ) & 255 ;
142+ hash[i * 4 + 1 ] = (buff.h [i] >> 16 ) & 255 ;
143+ hash[i * 4 + 2 ] = (buff.h [i] >> 8 ) & 255 ;
144+ hash[i * 4 + 3 ] = buff.h [i] & 255 ;
145+ }
146+ }
147+
148+ }
0 commit comments