Serialbox  2.2.0
Data serialization library and tools for C/C++, Python and Fortran
SHA256.cpp
Go to the documentation of this file.
1 //===-- serialbox/core/SHA256.cpp ---------------------------------------------------*- C++ -*-===//
2 //
3 // S E R I A L B O X
4 //
5 // This file is distributed under terms of BSD license.
6 // See LICENSE.txt for more information
7 //
8 //===------------------------------------------------------------------------------------------===//
9 //
19 //===------------------------------------------------------------------------------------------===//
20 
22 #include <cstdlib>
23 #include <cstring>
24 #include <sstream>
25 
26 namespace serialbox {
27 
28 namespace sha256 {
29 
30 using byte_t = unsigned char; // 8-bit byte
31 using word_t = std::int32_t; // 32-bit word, change to "long" for 16-bit machines
32 
33 typedef struct {
34  byte_t data[64];
35  word_t datalen;
36  unsigned long long bitlen;
37  word_t state[8];
38 } ctx_t;
39 
40 #define ROTLEFT(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
41 #define ROTRIGHT(a, b) (((a) >> (b)) | ((a) << (32 - (b))))
42 
43 #define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
44 #define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
45 #define EP0(x) (ROTRIGHT(x, 2) ^ ROTRIGHT(x, 13) ^ ROTRIGHT(x, 22))
46 #define EP1(x) (ROTRIGHT(x, 6) ^ ROTRIGHT(x, 11) ^ ROTRIGHT(x, 25))
47 #define SIG0(x) (ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ ((x) >> 3))
48 #define SIG1(x) (ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ ((x) >> 10))
49 
50 static const word_t k[64] = {static_cast<word_t>(1116352408), static_cast<word_t>(1899447441),
51  static_cast<word_t>(3049323471), static_cast<word_t>(3921009573),
52  static_cast<word_t>(961987163), static_cast<word_t>(1508970993),
53  static_cast<word_t>(2453635748), static_cast<word_t>(2870763221),
54  static_cast<word_t>(3624381080), static_cast<word_t>(310598401),
55  static_cast<word_t>(607225278), static_cast<word_t>(1426881987),
56  static_cast<word_t>(1925078388), static_cast<word_t>(2162078206),
57  static_cast<word_t>(2614888103), static_cast<word_t>(3248222580),
58  static_cast<word_t>(3835390401), static_cast<word_t>(4022224774),
59  static_cast<word_t>(264347078), static_cast<word_t>(604807628),
60  static_cast<word_t>(770255983), static_cast<word_t>(1249150122),
61  static_cast<word_t>(1555081692), static_cast<word_t>(1996064986),
62  static_cast<word_t>(2554220882), static_cast<word_t>(2821834349),
63  static_cast<word_t>(2952996808), static_cast<word_t>(3210313671),
64  static_cast<word_t>(3336571891), static_cast<word_t>(3584528711),
65  static_cast<word_t>(113926993), static_cast<word_t>(338241895),
66  static_cast<word_t>(666307205), static_cast<word_t>(773529912),
67  static_cast<word_t>(1294757372), static_cast<word_t>(1396182291),
68  static_cast<word_t>(1695183700), static_cast<word_t>(1986661051),
69  static_cast<word_t>(2177026350), static_cast<word_t>(2456956037),
70  static_cast<word_t>(2730485921), static_cast<word_t>(2820302411),
71  static_cast<word_t>(3259730800), static_cast<word_t>(3345764771),
72  static_cast<word_t>(3516065817), static_cast<word_t>(3600352804),
73  static_cast<word_t>(4094571909), static_cast<word_t>(275423344),
74  static_cast<word_t>(430227734), static_cast<word_t>(506948616),
75  static_cast<word_t>(659060556), static_cast<word_t>(883997877),
76  static_cast<word_t>(958139571), static_cast<word_t>(1322822218),
77  static_cast<word_t>(1537002063), static_cast<word_t>(1747873779),
78  static_cast<word_t>(1955562222), static_cast<word_t>(2024104815),
79  static_cast<word_t>(2227730452), static_cast<word_t>(2361852424),
80  static_cast<word_t>(2428436474), static_cast<word_t>(2756734187),
81  static_cast<word_t>(3204031479), static_cast<word_t>(3329325298)};
82 
83 static inline void sha256_transform(ctx_t* ctx, const byte_t data[]) {
84  word_t a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
85 
86  for(i = 0, j = 0; i < 16; ++i, j += 4)
87  m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
88  for(; i < 64; ++i)
89  m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
90 
91  a = ctx->state[0];
92  b = ctx->state[1];
93  c = ctx->state[2];
94  d = ctx->state[3];
95  e = ctx->state[4];
96  f = ctx->state[5];
97  g = ctx->state[6];
98  h = ctx->state[7];
99 
100  for(i = 0; i < 64; ++i) {
101  t1 = h + EP1(e) + CH(e, f, g) + k[i] + m[i];
102  t2 = EP0(a) + MAJ(a, b, c);
103  h = g;
104  g = f;
105  f = e;
106  e = d + t1;
107  d = c;
108  c = b;
109  b = a;
110  a = t1 + t2;
111  }
112 
113  ctx->state[0] += a;
114  ctx->state[1] += b;
115  ctx->state[2] += c;
116  ctx->state[3] += d;
117  ctx->state[4] += e;
118  ctx->state[5] += f;
119  ctx->state[6] += g;
120  ctx->state[7] += h;
121 }
122 
123 static void sha256_init(ctx_t* ctx) {
124  ctx->datalen = 0;
125  ctx->bitlen = 0;
126  ctx->state[0] = 0x6a09e667;
127  ctx->state[1] = 0xbb67ae85;
128  ctx->state[2] = 0x3c6ef372;
129  ctx->state[3] = 0xa54ff53a;
130  ctx->state[4] = 0x510e527f;
131  ctx->state[5] = 0x9b05688c;
132  ctx->state[6] = 0x1f83d9ab;
133  ctx->state[7] = 0x5be0cd19;
134 }
135 
136 static void sha256_update(ctx_t* ctx, const byte_t data[], size_t len) {
137  word_t i;
138 
139  for(i = 0; i < len; ++i) {
140  ctx->data[ctx->datalen] = data[i];
141  ctx->datalen++;
142  if(ctx->datalen == 64) {
143  sha256_transform(ctx, ctx->data);
144  ctx->bitlen += 512;
145  ctx->datalen = 0;
146  }
147  }
148 }
149 
150 static void sha256_final(ctx_t* ctx, byte_t hash[32]) {
151  word_t i;
152 
153  i = ctx->datalen;
154 
155  // Pad whatever data is left in the buffer.
156  if(ctx->datalen < 56) {
157  ctx->data[i++] = 0x80;
158  while(i < 56)
159  ctx->data[i++] = 0x00;
160  } else {
161  ctx->data[i++] = 0x80;
162  while(i < 64)
163  ctx->data[i++] = 0x00;
164  sha256_transform(ctx, ctx->data);
165  std::memset(ctx->data, 0, 56);
166  }
167 
168  // Append to the padding the total message's length in bits and transform.
169  ctx->bitlen += ctx->datalen * 8;
170  ctx->data[63] = ctx->bitlen;
171  ctx->data[62] = ctx->bitlen >> 8;
172  ctx->data[61] = ctx->bitlen >> 16;
173  ctx->data[60] = ctx->bitlen >> 24;
174  ctx->data[59] = ctx->bitlen >> 32;
175  ctx->data[58] = ctx->bitlen >> 40;
176  ctx->data[57] = ctx->bitlen >> 48;
177  ctx->data[56] = ctx->bitlen >> 56;
178  sha256_transform(ctx, ctx->data);
179 
180  // Since this implementation uses little endian byte ordering and SHA uses big endian,
181  // reverse all the bytes when copying the final state to the output hash.
182  for(i = 0; i < 4; ++i) {
183  hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
184  hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
185  hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
186  hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
187  hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
188  hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
189  hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
190  hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
191  }
192 }
193 
194 static void sha256(const void* data, int size, byte_t hash[32]) {
195  ctx_t context;
196 
197  sha256_init(&context);
198  sha256_update(&context, (const byte_t*)data, size);
199  sha256_final(&context, hash);
200 }
201 
202 } // sha256
203 
204 const char* SHA256::Name = "SHA256";
205 
206 std::string SHA256::hash(const void* data, int length) {
207  sha256::byte_t hash[32];
208  sha256::sha256(data, length, hash);
209 
210  std::ostringstream ss;
211  for(int i = 0; i < 32; ++i)
212  ss << std::hex << std::uppercase << static_cast<int>(hash[i]);
213 
214  return ss.str();
215 }
216 
217 } // namespace serialbox
virtual std::string hash(const void *data, int length) override
Compute 256 bit hash using SHA-1.
Definition: SHA256.cpp:206
static const char * Name
Identifier of the hash.
Definition: SHA256.h:31
Namespace of the serialbox library.
Definition: Archive.h:25