Skip to content

Commit 0bbc902

Browse files
committed
Commit d5b29e11ec4871b78b370e8e00bd0cd56d798dda
1 parent 29b2f81 commit 0bbc902

File tree

2 files changed

+340
-0
lines changed

2 files changed

+340
-0
lines changed

src/utility/sha1.c

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/*
2+
SHA-1 in C
3+
By Steve Reid <steve@edmweb.com>
4+
100% Public Domain
5+
6+
Test Vectors (from FIPS PUB 180-1)
7+
"abc"
8+
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
9+
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
10+
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
11+
A million repetitions of "a"
12+
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
13+
*/
14+
15+
/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
16+
/* #define SHA1HANDSOFF * Copies data before messing with it. */
17+
18+
#define SHA1HANDSOFF
19+
20+
#include <stdio.h>
21+
#include <string.h>
22+
23+
/* for uint32_t */
24+
#include <stdint.h>
25+
26+
#include "sha1.h"
27+
28+
29+
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
30+
31+
/* blk0() and blk() perform the initial expand. */
32+
/* I got the idea of expanding during the round function from SSLeay */
33+
#if BYTE_ORDER == LITTLE_ENDIAN
34+
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
35+
|(rol(block->l[i],8)&0x00FF00FF))
36+
#elif BYTE_ORDER == BIG_ENDIAN
37+
#define blk0(i) block->l[i]
38+
#else
39+
#error "Endianness not defined!"
40+
#endif
41+
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
42+
^block->l[(i+2)&15]^block->l[i&15],1))
43+
44+
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
45+
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
46+
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
47+
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
48+
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
49+
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
50+
51+
52+
/* Hash a single 512-bit block. This is the core of the algorithm. */
53+
54+
void SHA1Transform(
55+
uint32_t state[5],
56+
const unsigned char buffer[64]
57+
)
58+
{
59+
uint32_t a, b, c, d, e;
60+
61+
typedef union
62+
{
63+
unsigned char c[64];
64+
uint32_t l[16];
65+
} CHAR64LONG16;
66+
67+
#ifdef SHA1HANDSOFF
68+
CHAR64LONG16 block[1]; /* use array to appear as a pointer */
69+
70+
memcpy(block, buffer, 64);
71+
#else
72+
/* The following had better never be used because it causes the
73+
* pointer-to-const buffer to be cast into a pointer to non-const.
74+
* And the result is written through. I threw a "const" in, hoping
75+
* this will cause a diagnostic.
76+
*/
77+
CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer;
78+
#endif
79+
/* Copy context->state[] to working vars */
80+
a = state[0];
81+
b = state[1];
82+
c = state[2];
83+
d = state[3];
84+
e = state[4];
85+
/* 4 rounds of 20 operations each. Loop unrolled. */
86+
R0(a, b, c, d, e, 0);
87+
R0(e, a, b, c, d, 1);
88+
R0(d, e, a, b, c, 2);
89+
R0(c, d, e, a, b, 3);
90+
R0(b, c, d, e, a, 4);
91+
R0(a, b, c, d, e, 5);
92+
R0(e, a, b, c, d, 6);
93+
R0(d, e, a, b, c, 7);
94+
R0(c, d, e, a, b, 8);
95+
R0(b, c, d, e, a, 9);
96+
R0(a, b, c, d, e, 10);
97+
R0(e, a, b, c, d, 11);
98+
R0(d, e, a, b, c, 12);
99+
R0(c, d, e, a, b, 13);
100+
R0(b, c, d, e, a, 14);
101+
R0(a, b, c, d, e, 15);
102+
R1(e, a, b, c, d, 16);
103+
R1(d, e, a, b, c, 17);
104+
R1(c, d, e, a, b, 18);
105+
R1(b, c, d, e, a, 19);
106+
R2(a, b, c, d, e, 20);
107+
R2(e, a, b, c, d, 21);
108+
R2(d, e, a, b, c, 22);
109+
R2(c, d, e, a, b, 23);
110+
R2(b, c, d, e, a, 24);
111+
R2(a, b, c, d, e, 25);
112+
R2(e, a, b, c, d, 26);
113+
R2(d, e, a, b, c, 27);
114+
R2(c, d, e, a, b, 28);
115+
R2(b, c, d, e, a, 29);
116+
R2(a, b, c, d, e, 30);
117+
R2(e, a, b, c, d, 31);
118+
R2(d, e, a, b, c, 32);
119+
R2(c, d, e, a, b, 33);
120+
R2(b, c, d, e, a, 34);
121+
R2(a, b, c, d, e, 35);
122+
R2(e, a, b, c, d, 36);
123+
R2(d, e, a, b, c, 37);
124+
R2(c, d, e, a, b, 38);
125+
R2(b, c, d, e, a, 39);
126+
R3(a, b, c, d, e, 40);
127+
R3(e, a, b, c, d, 41);
128+
R3(d, e, a, b, c, 42);
129+
R3(c, d, e, a, b, 43);
130+
R3(b, c, d, e, a, 44);
131+
R3(a, b, c, d, e, 45);
132+
R3(e, a, b, c, d, 46);
133+
R3(d, e, a, b, c, 47);
134+
R3(c, d, e, a, b, 48);
135+
R3(b, c, d, e, a, 49);
136+
R3(a, b, c, d, e, 50);
137+
R3(e, a, b, c, d, 51);
138+
R3(d, e, a, b, c, 52);
139+
R3(c, d, e, a, b, 53);
140+
R3(b, c, d, e, a, 54);
141+
R3(a, b, c, d, e, 55);
142+
R3(e, a, b, c, d, 56);
143+
R3(d, e, a, b, c, 57);
144+
R3(c, d, e, a, b, 58);
145+
R3(b, c, d, e, a, 59);
146+
R4(a, b, c, d, e, 60);
147+
R4(e, a, b, c, d, 61);
148+
R4(d, e, a, b, c, 62);
149+
R4(c, d, e, a, b, 63);
150+
R4(b, c, d, e, a, 64);
151+
R4(a, b, c, d, e, 65);
152+
R4(e, a, b, c, d, 66);
153+
R4(d, e, a, b, c, 67);
154+
R4(c, d, e, a, b, 68);
155+
R4(b, c, d, e, a, 69);
156+
R4(a, b, c, d, e, 70);
157+
R4(e, a, b, c, d, 71);
158+
R4(d, e, a, b, c, 72);
159+
R4(c, d, e, a, b, 73);
160+
R4(b, c, d, e, a, 74);
161+
R4(a, b, c, d, e, 75);
162+
R4(e, a, b, c, d, 76);
163+
R4(d, e, a, b, c, 77);
164+
R4(c, d, e, a, b, 78);
165+
R4(b, c, d, e, a, 79);
166+
/* Add the working vars back into context.state[] */
167+
state[0] += a;
168+
state[1] += b;
169+
state[2] += c;
170+
state[3] += d;
171+
state[4] += e;
172+
/* Wipe variables */
173+
a = b = c = d = e = 0;
174+
#ifdef SHA1HANDSOFF
175+
memset(block, '\0', sizeof(block));
176+
#endif
177+
}
178+
179+
180+
/* SHA1Init - Initialize new context */
181+
182+
void SHA1Init(
183+
SHA1_CTX * context
184+
)
185+
{
186+
/* SHA1 initialization constants */
187+
context->state[0] = 0x67452301;
188+
context->state[1] = 0xEFCDAB89;
189+
context->state[2] = 0x98BADCFE;
190+
context->state[3] = 0x10325476;
191+
context->state[4] = 0xC3D2E1F0;
192+
context->count[0] = context->count[1] = 0;
193+
}
194+
195+
196+
/* Run your data through this. */
197+
198+
void SHA1Update(
199+
SHA1_CTX * context,
200+
const unsigned char *data,
201+
uint32_t len
202+
)
203+
{
204+
uint32_t i;
205+
206+
uint32_t j;
207+
208+
j = context->count[0];
209+
if ((context->count[0] += len << 3) < j)
210+
context->count[1]++;
211+
context->count[1] += (len >> 29);
212+
j = (j >> 3) & 63;
213+
if ((j + len) > 63)
214+
{
215+
memcpy(&context->buffer[j], data, (i = 64 - j));
216+
SHA1Transform(context->state, context->buffer);
217+
for (; i + 63 < len; i += 64)
218+
{
219+
SHA1Transform(context->state, &data[i]);
220+
}
221+
j = 0;
222+
}
223+
else
224+
i = 0;
225+
memcpy(&context->buffer[j], &data[i], len - i);
226+
}
227+
228+
229+
/* Add padding and return the message digest. */
230+
231+
void SHA1Final(
232+
unsigned char digest[20],
233+
SHA1_CTX * context
234+
)
235+
{
236+
unsigned i;
237+
238+
unsigned char finalcount[8];
239+
240+
unsigned char c;
241+
242+
#if 0 /* untested "improvement" by DHR */
243+
/* Convert context->count to a sequence of bytes
244+
* in finalcount. Second element first, but
245+
* big-endian order within element.
246+
* But we do it all backwards.
247+
*/
248+
unsigned char *fcp = &finalcount[8];
249+
250+
for (i = 0; i < 2; i++)
251+
{
252+
uint32_t t = context->count[i];
253+
254+
int j;
255+
256+
for (j = 0; j < 4; t >>= 8, j++)
257+
*--fcp = (unsigned char) t}
258+
#else
259+
for (i = 0; i < 8; i++)
260+
{
261+
finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */
262+
}
263+
#endif
264+
c = 0200;
265+
SHA1Update(context, &c, 1);
266+
while ((context->count[0] & 504) != 448)
267+
{
268+
c = 0000;
269+
SHA1Update(context, &c, 1);
270+
}
271+
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
272+
for (i = 0; i < 20; i++)
273+
{
274+
digest[i] = (unsigned char)
275+
((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
276+
}
277+
/* Wipe variables */
278+
memset(context, '\0', sizeof(*context));
279+
memset(&finalcount, '\0', sizeof(finalcount));
280+
}
281+
282+
void SHA1(
283+
char *hash_out,
284+
const char *str,
285+
int len)
286+
{
287+
SHA1_CTX ctx;
288+
unsigned int ii;
289+
290+
SHA1Init(&ctx);
291+
for (ii=0; ii<len; ii+=1)
292+
SHA1Update(&ctx, (const unsigned char*)str + ii, 1);
293+
SHA1Final((unsigned char *)hash_out, &ctx);
294+
hash_out[20] = '\0';
295+
}
296+

src/utility/sha1.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#ifndef SHA1_H
2+
#define SHA1_H
3+
4+
/*
5+
SHA-1 in C
6+
By Steve Reid <steve@edmweb.com>
7+
100% Public Domain
8+
*/
9+
10+
#include "stdint.h"
11+
12+
typedef struct
13+
{
14+
uint32_t state[5];
15+
uint32_t count[2];
16+
unsigned char buffer[64];
17+
} SHA1_CTX;
18+
19+
void SHA1Transform(
20+
uint32_t state[5],
21+
const unsigned char buffer[64]
22+
);
23+
24+
void SHA1Init(
25+
SHA1_CTX * context
26+
);
27+
28+
void SHA1Update(
29+
SHA1_CTX * context,
30+
const unsigned char *data,
31+
uint32_t len
32+
);
33+
34+
void SHA1Final(
35+
unsigned char digest[20],
36+
SHA1_CTX * context
37+
);
38+
39+
void SHA1(
40+
char *hash_out,
41+
const char *str,
42+
int len);
43+
44+
#endif /* SHA1_H */

0 commit comments

Comments
 (0)