1
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
* Modified by Barry Leslie on 10/21/08.
20
* I have put a C++ wrapper around the data and functions to create an sha1 class.
24
Original Source from: http://www.faqs.org/rfcs/rfc3174.html
25
and MySQL mysys/sha1.c build 5.1.24.
28
This file implements the Secure Hashing Algorithm 1 as
29
defined in FIPS PUB 180-1 published April 17, 1995.
31
The SHA-1, produces a 160-bit message digest for a given data
32
stream. It should take about 2**n steps to find a message with the
33
same digest as a given message and 2**(n/2) to find any two
34
messages with the same digest, when n is the digest size in bits.
35
Therefore, this algorithm can serve as a means of providing a
36
"fingerprint" for a message.
39
SHA-1 is defined in terms of 32-bit "words". This code uses
40
<stdint.h> (included via "sha1.h" to define 32 and 8 bit unsigned
41
integer types. If your C compiler does not support 32 bit unsigned
42
integers, this code is not appropriate.
45
SHA-1 is designed to work with messages less than 2^64 bits long.
46
Although SHA-1 allows a message digest to be generated for messages
47
of any number of bits less than 2^64, this implementation only
48
works with messages with a length that is a multiple of the size of
52
2002 by Peter Zaitsev to
53
- fit to new prototypes according to MySQL standard
55
- All checking is now done in debug only mode
68
#define SHA1CircularShift(bits,word) (((word) << (bits)) | ((word) >> (32-(bits))))
70
void CSSha1::sha1_reset()
73
Message_Block_Index = 0;
75
Intermediate_Hash[0] = 0x67452301;
76
Intermediate_Hash[1] = 0xEFCDAB89;
77
Intermediate_Hash[2] = 0x98BADCFE;
78
Intermediate_Hash[3] = 0x10325476;
79
Intermediate_Hash[4] = 0xC3D2E1F0;
85
//------------------------------
86
void CSSha1::sha1_digest(Sha1Digest *digest)
90
memset(Message_Block, 0, 64);
95
for (int i = 0; i < SHA1_HASH_SIZE; i++)
96
digest->val[i] = (int8_t)((Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) )));
99
//------------------------------
100
void CSSha1::sha1_input(const void *data, size_t len)
102
uint8_t *message_array = (u_char *) data;
111
Message_Block[Message_Block_Index++]= (*message_array & 0xFF);
112
Length += 8; /* Length is in bits */
114
if (Message_Block_Index == 64)
121
//------------------------------
122
void CSSha1::sha1_pad()
125
Check to see if the current message block is too small to hold
126
the initial padding bits and length. If so, we will pad the
127
block, process it, and then continue padding into a second
131
int i = Message_Block_Index;
134
Message_Block[i++] = 0x80;
135
memset(&Message_Block[i], 0, sizeof(Message_Block[0]) * 64-i);
136
Message_Block_Index=64;
138
/* This function sets Message_Block_Index to zero */
141
memset(Message_Block, 0, sizeof(Message_Block[0]) * 56);
142
Message_Block_Index=56;
144
Message_Block[i++] = 0x80;
145
memset(&Message_Block[i], 0, sizeof(Message_Block[0])*(56-i));
146
Message_Block_Index=56;
150
Store the message length as the last 8 octets
153
Message_Block[56] = (int8_t) (Length >> 56);
154
Message_Block[57] = (int8_t) (Length >> 48);
155
Message_Block[58] = (int8_t) (Length >> 40);
156
Message_Block[59] = (int8_t) (Length >> 32);
157
Message_Block[60] = (int8_t) (Length >> 24);
158
Message_Block[61] = (int8_t) (Length >> 16);
159
Message_Block[62] = (int8_t) (Length >> 8);
160
Message_Block[63] = (int8_t) (Length);
165
//------------------------------
166
void CSSha1::sha1_process()
168
const uint32_t K[] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
169
int t; /* Loop counter */
170
uint32_t temp; /* Temporary word value */
171
uint32_t W[80]; /* Word sequence */
172
uint32_t A, B, C, D, E; /* Word buffers */
176
Initialize the first 16 words in the array W
179
for (t = 0; t < 16; t++) {
181
W[t] = Message_Block[idx] << 24;
182
W[t] |= Message_Block[idx + 1] << 16;
183
W[t] |= Message_Block[idx + 2] << 8;
184
W[t] |= Message_Block[idx + 3];
188
for (t = 16; t < 80; t++) {
189
W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
192
A = Intermediate_Hash[0];
193
B = Intermediate_Hash[1];
194
C = Intermediate_Hash[2];
195
D = Intermediate_Hash[3];
196
E = Intermediate_Hash[4];
198
for (t = 0; t < 20; t++) {
199
temp= SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
202
C = SHA1CircularShift(30,B);
207
for (t = 20; t < 40; t++) {
208
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
211
C = SHA1CircularShift(30,B);
216
for (t = 40; t < 60; t++) {
217
temp= (SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]);
220
C = SHA1CircularShift(30,B);
225
for (t = 60; t < 80; t++) {
226
temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
229
C = SHA1CircularShift(30,B);
234
Intermediate_Hash[0] += A;
235
Intermediate_Hash[1] += B;
236
Intermediate_Hash[2] += C;
237
Intermediate_Hash[3] += D;
238
Intermediate_Hash[4] += E;
240
Message_Block_Index = 0;