Mana
Loading...
Searching...
No Matches
sha256.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2008-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file has been slightly modified as part of The Mana Client.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2, as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21/* +------------------------------------+
22 * | Inspire Internet Relay Chat Daemon |
23 * +------------------------------------+
24 *
25 * InspIRCd: (C) 2002-2008 InspIRCd Development Team
26 * See: http://www.inspircd.org/wiki/index.php/Credits
27 *
28 * This program is free but copyrighted software; see
29 * the file COPYING for details.
30 *
31 * ---------------------------------------------------
32 */
33
34/* m_sha256 - Based on m_opersha256 written by Special <john@yarbbles.com>
35 * Modified and improved by Craig Edwards, December 2006.
36 *
37 *
38 * FIPS 180-2 SHA-224/256/384/512 implementation
39 * Last update: 05/23/2005
40 * Issue date: 04/30/2005
41 *
42 * Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
43 * All rights reserved.
44 *
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
47 * are met:
48 * 1. Redistributions of source code must retain the above copyright
49 * notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 * notice, this list of conditions and the following disclaimer in the
52 * documentation and/or other materials provided with the distribution.
53 * 3. Neither the name of the project nor the names of its contributors
54 * may be used to endorse or promote products derived from this software
55 * without specific prior written permission.
56 *
57 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 * SUCH DAMAGE.
68 */
69
70#include "utils/sha256.h"
71
72#ifdef HAVE_CONFIG_H
73#include "config.h"
74#endif
75
76#include <memory.h>
77
78#ifdef HAVE_STDINT_H
79#include <stdint.h>
80#else
81using uint8_t = unsigned char;
82using uint32_t = unsigned int;
83#endif
84
85#define SHA256_BLOCK_SIZE (512 / 8)
86
89{
90 public:
91 unsigned int tot_len;
92 unsigned int len;
93 unsigned char block[2 * SHA256_BLOCK_SIZE];
95};
96
97#define SHA256_DIGEST_SIZE (256 / 8)
98
99#define SHFR(x, n) (x >> n)
100#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
101#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
102#define CH(x, y, z) ((x & y) ^ (~x & z))
103#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
104
105#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
106#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
107#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
108#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
109
110#define UNPACK32(x, str) \
111{ \
112 *((str) + 3) = (uint8_t) ((x) ); \
113 *((str) + 2) = (uint8_t) ((x) >> 8); \
114 *((str) + 1) = (uint8_t) ((x) >> 16); \
115 *((str) + 0) = (uint8_t) ((x) >> 24); \
116}
117
118#define PACK32(str, x) \
119{ \
120 *(x) = ((uint32_t) *((str) + 3) ) \
121 | ((uint32_t) *((str) + 2) << 8) \
122 | ((uint32_t) *((str) + 1) << 16) \
123 | ((uint32_t) *((str) + 0) << 24); \
124}
125
126/* Macros used for loops unrolling */
127
128#define SHA256_SCR(i) \
129{ \
130 w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
131 + SHA256_F3(w[i - 15]) + w[i - 16]; \
132}
133
134const unsigned int sha256_h0[8] =
135{
136 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
137 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
138};
139
141{
142 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
143 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
144 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
145 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
146 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
147 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
148 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
149 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
150 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
151 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
152 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
153 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
154 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
155 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
156 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
157 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
158};
159
161{
162 for (int i = 0; i < 8; i++)
163 ctx->h[i] = sha256_h0[i];
164 ctx->len = 0;
165 ctx->tot_len = 0;
166}
167
169 unsigned char *message,
170 unsigned int block_nb)
171{
172 uint32_t w[64];
173 uint32_t wv[8];
174 unsigned char *sub_block;
175 for (unsigned int i = 1; i <= block_nb; i++)
176 {
177 int j;
178 sub_block = message + ((i - 1) << 6);
179
180 for (j = 0; j < 16; j++)
181 PACK32(&sub_block[j << 2], &w[j]);
182 for (j = 16; j < 64; j++)
183 SHA256_SCR(j);
184 for (j = 0; j < 8; j++)
185 wv[j] = ctx->h[j];
186 for (j = 0; j < 64; j++)
187 {
188 uint32_t t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j];
189 uint32_t t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
190 wv[7] = wv[6];
191 wv[6] = wv[5];
192 wv[5] = wv[4];
193 wv[4] = wv[3] + t1;
194 wv[3] = wv[2];
195 wv[2] = wv[1];
196 wv[1] = wv[0];
197 wv[0] = t1 + t2;
198 }
199 for (j = 0; j < 8; j++)
200 ctx->h[j] += wv[j];
201 }
202}
203
205 unsigned char *message,
206 unsigned int len)
207{
208 /*
209 * XXX here be dragons!
210 * After many hours of pouring over this, I think I've found the problem.
211 * When Special created our module from the reference one, he used:
212 *
213 * unsigned int rem_len = SHA256_BLOCK_SIZE - ctx->len;
214 *
215 * instead of the reference's version of:
216 *
217 * unsigned int tmp_len = SHA256_BLOCK_SIZE - ctx->len;
218 * unsigned int rem_len = len < tmp_len ? len : tmp_len;
219 *
220 * I've changed back to the reference version of this code, and it seems to work with no errors.
221 * So I'm inclined to believe this was the problem..
222 * -- w00t (January 06, 2008)
223 */
224 unsigned int tmp_len = SHA256_BLOCK_SIZE - ctx->len;
225 unsigned int rem_len = len < tmp_len ? len : tmp_len;
226
227 memcpy(&ctx->block[ctx->len], message, rem_len);
228 if (ctx->len + len < SHA256_BLOCK_SIZE)
229 {
230 ctx->len += len;
231 return;
232 }
233 unsigned int new_len = len - rem_len;
234 unsigned int block_nb = new_len / SHA256_BLOCK_SIZE;
235 unsigned char *shifted_message = message + rem_len;
236 SHA256Transform(ctx, ctx->block, 1);
237 SHA256Transform(ctx, shifted_message, block_nb);
238 rem_len = new_len % SHA256_BLOCK_SIZE;
239 memcpy(ctx->block, &shifted_message[block_nb << 6],rem_len);
240 ctx->len = rem_len;
241 ctx->tot_len += (block_nb + 1) << 6;
242}
243
244void SHA256Final(SHA256Context *ctx, unsigned char *digest)
245{
246 unsigned int block_nb = (1 + ((SHA256_BLOCK_SIZE - 9) < (ctx->len % SHA256_BLOCK_SIZE)));
247 unsigned int len_b = (ctx->tot_len + ctx->len) << 3;
248 unsigned int pm_len = block_nb << 6;
249 memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
250 ctx->block[ctx->len] = 0x80;
251 UNPACK32(len_b, ctx->block + pm_len - 4);
252 SHA256Transform(ctx, ctx->block, block_nb);
253 for (int i = 0 ; i < 8; i++)
254 UNPACK32(ctx->h[i], &digest[i << 2]);
255}
256
257std::string SHA256Hash(const char *src, int len)
258{
259 // Generate the hash
260 unsigned char bytehash[SHA256_DIGEST_SIZE];
261 SHA256Context ctx;
262 SHA256Init(&ctx);
263 SHA256Update(&ctx, (unsigned char *)src, (unsigned int)len);
264 SHA256Final(&ctx, bytehash);
265 // Convert it to hex
266 const char* hxc = "0123456789abcdef";
267 std::string hash;
268 for (unsigned char i : bytehash)
269 {
270 hash += hxc[i / 16];
271 hash += hxc[i % 16];
272 }
273 return hash;
274}
275
276std::string sha256(const std::string &string)
277{
278 return SHA256Hash(string.c_str(), string.length());
279}
An sha 256 context, used by original m_opersha256.
Definition sha256.cpp:89
uint32_t h[8]
Definition sha256.cpp:94
unsigned int tot_len
Definition sha256.cpp:91
unsigned int len
Definition sha256.cpp:92
unsigned char block[2 *SHA256_BLOCK_SIZE]
Definition sha256.cpp:93
#define SHA256_F1(x)
Definition sha256.cpp:105
unsigned char uint8_t
Definition sha256.cpp:81
#define CH(x, y, z)
Definition sha256.cpp:102
std::string SHA256Hash(const char *src, int len)
Definition sha256.cpp:257
unsigned int uint32_t
Definition sha256.cpp:82
const unsigned int sha256_h0[8]
Definition sha256.cpp:134
#define SHA256_SCR(i)
Definition sha256.cpp:128
void SHA256Final(SHA256Context *ctx, unsigned char *digest)
Definition sha256.cpp:244
void SHA256Transform(SHA256Context *ctx, unsigned char *message, unsigned int block_nb)
Definition sha256.cpp:168
#define SHA256_DIGEST_SIZE
Definition sha256.cpp:97
#define UNPACK32(x, str)
Definition sha256.cpp:110
#define PACK32(str, x)
Definition sha256.cpp:118
std::string sha256(const std::string &string)
Returns the SHA-256 hash for the given string.
Definition sha256.cpp:276
#define SHA256_BLOCK_SIZE
Definition sha256.cpp:85
uint32_t sha256_k[64]
Definition sha256.cpp:140
void SHA256Init(SHA256Context *ctx)
Definition sha256.cpp:160
void SHA256Update(SHA256Context *ctx, unsigned char *message, unsigned int len)
Definition sha256.cpp:204
#define MAJ(x, y, z)
Definition sha256.cpp:103
#define SHA256_F2(x)
Definition sha256.cpp:106