12
12
* used for authenticating software packages and secure password hashing.
13
13
*/
14
14
15
+ #include < array> // / For std::array
15
16
#include < cassert> // / For assert
16
17
#include < cstdint> // / For uint8_t, uint32_t and uint64_t data types
18
+ #include < iomanip> // / For std::setfill and std::setw
17
19
#include < iostream> // / For IO operations
20
+ #include < sstream> // / For std::stringstream
18
21
19
22
/* *
20
23
* @namespace hashing
@@ -27,13 +30,37 @@ namespace hashing {
27
30
* algorithm implementation
28
31
*/
29
32
namespace sha256 {
33
+ /* *
34
+ * @brief Pads the input string to be a multiple of 512-bits
35
+ * @param input Input string
36
+ * @return std::string The padded input string
37
+ */
38
+ std::string prepare_input (std::string input) {
39
+ // Pre-processing
40
+ std::string padded_input = input;
41
+ uint64_t input_size = input.length () * 8 ; // Message length in bits
42
+
43
+ // Append a single '1' bit
44
+ padded_input += ' \x80 ' ;
45
+
46
+ // Pad with zeros
47
+ while ((padded_input.length () * 8 ) % 512 != 448 ) padded_input += ' \x00 ' ;
48
+
49
+ // Append length of the original input string as a 64-bit big-endian integer
50
+ for (uint32_t i = 64 ; i != 0 ; i -= 8 ) {
51
+ padded_input += static_cast <char >((input_size >> (i - 8 )) & 0xFF );
52
+ }
53
+
54
+ return padded_input;
55
+ }
56
+
30
57
/* *
31
58
* @brief Rotates the bits of a 32-bit unsigned integer
32
59
* @param n Integer to rotate
33
60
* @param rotate Number of bits to rotate
34
61
* @return uint32_t The rotated integer
35
62
*/
36
- uint32_t rightRotate (uint32_t n, size_t rotate) {
63
+ uint32_t right_rotate (uint32_t n, size_t rotate) {
37
64
return (n >> rotate) | (n << (32 - rotate));
38
65
}
39
66
@@ -45,12 +72,13 @@ uint32_t rightRotate(uint32_t n, size_t rotate) {
45
72
std::string sha256 (const std::string &input) {
46
73
// Initialize array of hash values with first 32 bits of the fractional
47
74
// parts of the square roots of the first 8 primes 2..19
48
- uint32_t hash[8 ] = {0x6A09E667 , 0xBB67AE85 , 0x3C6EF372 , 0xA54FF53A ,
49
- 0x510E527F , 0x9B05688C , 0x1F83D9AB , 0x5BE0CD19 };
75
+ std::array<uint32_t , 8 > hash = {0x6A09E667 , 0xBB67AE85 , 0x3C6EF372 ,
76
+ 0xA54FF53A , 0x510E527F , 0x9B05688C ,
77
+ 0x1F83D9AB , 0x5BE0CD19 };
50
78
51
79
// Initialize array of round constants with first 32 bits of the fractional
52
80
// parts of the cube roots of the first 64 primes 2..311
53
- const uint32_t k[ 64 ] = {
81
+ const std::array< uint32_t , 64 > k = {
54
82
0x428A2F98 , 0x71374491 , 0xB5C0FBCF , 0xE9B5DBA5 , 0x3956C25B , 0x59F111F1 ,
55
83
0x923F82A4 , 0xAB1C5ED5 , 0xD807AA98 , 0x12835B01 , 0x243185BE , 0x550C7DC3 ,
56
84
0x72BE5D74 , 0x80DEB1FE , 0x9BDC06A7 , 0xC19BF174 , 0xE49B69C1 , 0xEFBE4786 ,
@@ -63,24 +91,11 @@ std::string sha256(const std::string &input) {
63
91
0x5B9CCA4F , 0x682E6FF3 , 0x748F82EE , 0x78A5636F , 0x84C87814 , 0x8CC70208 ,
64
92
0x90BEFFFA , 0xA4506CEB , 0xBEF9A3F7 , 0xC67178F2 };
65
93
66
- // Pre-processing
67
- std::string padded_input = input;
68
- uint64_t input_size = input.length () * 8 ; // Message length in bits
69
-
70
- // Append a single '1' bit
71
- padded_input += ' \x80 ' ;
72
-
73
- // Pad with zeros
74
- while ((padded_input.length () * 8 ) % 512 != 448 ) padded_input += ' \x00 ' ;
75
-
76
- // Append length of the original input string as a 64-bit big-endian integer
77
- for (uint32_t i = 64 ; i != 0 ; i -= 8 ) {
78
- padded_input += static_cast <char >((input_size >> (i - 8 )) & 0xFF );
79
- }
94
+ const std::string padded_input = prepare_input (input);
80
95
81
96
// Process message in successive 512-bit (64-byte) chunks
82
97
for (size_t i = 0 ; i < padded_input.length (); i += 64 ) {
83
- uint32_t blocks[ 64 ] ;
98
+ std::array< uint32_t , 64 > blocks ;
84
99
85
100
// Copy chunk into first 16 words of the message schedule array
86
101
for (size_t j = 0 ; j < 16 ; ++j) {
@@ -92,11 +107,11 @@ std::string sha256(const std::string &input) {
92
107
}
93
108
94
109
for (size_t j = 16 ; j < 64 ; ++j) {
95
- uint32_t s0 = rightRotate (blocks[j - 15 ], 7 ) ^
96
- rightRotate (blocks[j - 15 ], 18 ) ^
110
+ uint32_t s0 = right_rotate (blocks[j - 15 ], 7 ) ^
111
+ right_rotate (blocks[j - 15 ], 18 ) ^
97
112
(blocks[j - 15 ] >> 3 );
98
- uint32_t s1 = rightRotate (blocks[j - 2 ], 17 ) ^
99
- rightRotate (blocks[j - 2 ], 19 ) ^
113
+ uint32_t s1 = right_rotate (blocks[j - 2 ], 17 ) ^
114
+ right_rotate (blocks[j - 2 ], 19 ) ^
100
115
(blocks[j - 2 ] >> 10 );
101
116
blocks[j] = blocks[j - 16 ] + s0 + blocks[j - 7 ] + s1;
102
117
}
@@ -114,11 +129,11 @@ std::string sha256(const std::string &input) {
114
129
// Compression function main loop
115
130
for (size_t j = 0 ; j < 64 ; ++j) {
116
131
uint32_t s1 =
117
- rightRotate (e, 6 ) ^ rightRotate (e, 11 ) ^ rightRotate (e, 25 );
132
+ right_rotate (e, 6 ) ^ right_rotate (e, 11 ) ^ right_rotate (e, 25 );
118
133
uint32_t ch = (e & f) ^ (~e & g);
119
134
uint32_t temp1 = h + s1 + ch + k[j] + blocks[j];
120
135
uint32_t s0 =
121
- rightRotate (a, 2 ) ^ rightRotate (a, 13 ) ^ rightRotate (a, 22 );
136
+ right_rotate (a, 2 ) ^ right_rotate (a, 13 ) ^ right_rotate (a, 22 );
122
137
uint32_t maj = (a & b) ^ (a & c) ^ (b & c);
123
138
uint32_t temp2 = s0 + maj;
124
139
@@ -146,11 +161,11 @@ std::string sha256(const std::string &input) {
146
161
// Convert the hash to a hexadecimal string
147
162
std::string result;
148
163
for (size_t i = 0 ; i < 8 ; ++i) {
149
- for (int j = 0 ; j < 4 ; ++j) {
150
- uint8_t byte = (hash[i] >> (24 - j * 8 )) & 0xFF ;
151
- char buf[ 3 ] ;
152
- sprintf (buf, " %02x " , byte) ;
153
- result += buf ;
164
+ for (size_t j = 0 ; j < 4 ; ++j) {
165
+ uint32_t byte = (hash[i] >> (24 - j * 8 )) & 0xFF ;
166
+ std::stringstream ss ;
167
+ ss << std::hex << std::setfill ( ' 0 ' ) << std::setw ( 2 ) << byte ;
168
+ result += ss. str () ;
154
169
}
155
170
}
156
171
0 commit comments