Update changelog and call this 0.3.3
[oweals/minetest.git] / src / sha1.cpp
1 /* sha1.cpp
2
3 Copyright (c) 2005 Michael D. Leonhard
4
5 http://tamale.net/
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy of
8 this software and associated documentation files (the "Software"), to deal in
9 the Software without restriction, including without limitation the rights to
10 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11 of the Software, and to permit persons to whom the Software is furnished to do
12 so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24
25 */
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <assert.h>
31
32 #include "sha1.h"
33
34 // print out memory in hexadecimal
35 void SHA1::hexPrinter( unsigned char* c, int l )
36 {
37         assert( c );
38         assert( l > 0 );
39         while( l > 0 )
40         {
41                 printf( " %02x", *c );
42                 l--;
43                 c++;
44         }
45 }
46
47 // circular left bit rotation.  MSB wraps around to LSB
48 Uint32 SHA1::lrot( Uint32 x, int bits )
49 {
50         return (x<<bits) | (x>>(32 - bits));
51 };
52
53 // Save a 32-bit unsigned integer to memory, in big-endian order
54 void SHA1::storeBigEndianUint32( unsigned char* byte, Uint32 num )
55 {
56         assert( byte );
57         byte[0] = (unsigned char)(num>>24);
58         byte[1] = (unsigned char)(num>>16);
59         byte[2] = (unsigned char)(num>>8);
60         byte[3] = (unsigned char)num;
61 }
62
63
64 // Constructor *******************************************************
65 SHA1::SHA1()
66 {
67         // make sure that the data type is the right size
68         assert( sizeof( Uint32 ) * 5 == 20 );
69         
70         // initialize
71         H0 = 0x67452301;
72         H1 = 0xefcdab89;
73         H2 = 0x98badcfe;
74         H3 = 0x10325476;
75         H4 = 0xc3d2e1f0;
76         unprocessedBytes = 0;
77         size = 0;
78 }
79
80 // Destructor ********************************************************
81 SHA1::~SHA1()
82 {
83         // erase data
84         H0 = H1 = H2 = H3 = H4 = 0;
85         for( int c = 0; c < 64; c++ ) bytes[c] = 0;
86         unprocessedBytes = size = 0;
87 }
88
89 // process ***********************************************************
90 void SHA1::process()
91 {
92         assert( unprocessedBytes == 64 );
93         //printf( "process: " ); hexPrinter( bytes, 64 ); printf( "\n" );
94         int t;
95         Uint32 a, b, c, d, e, K, f, W[80];
96         // starting values
97         a = H0;
98         b = H1;
99         c = H2;
100         d = H3;
101         e = H4;
102         // copy and expand the message block
103         for( t = 0; t < 16; t++ ) W[t] = (bytes[t*4] << 24)
104                                                                         +(bytes[t*4 + 1] << 16)
105                                                                         +(bytes[t*4 + 2] << 8)
106                                                                         + bytes[t*4 + 3];
107         for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 );
108         
109         /* main loop */
110         Uint32 temp;
111         for( t = 0; t < 80; t++ )
112         {
113                 if( t < 20 ) {
114                         K = 0x5a827999;
115                         f = (b & c) | ((b ^ 0xFFFFFFFF) & d);//TODO: try using ~
116                 } else if( t < 40 ) {
117                         K = 0x6ed9eba1;
118                         f = b ^ c ^ d;
119                 } else if( t < 60 ) {
120                         K = 0x8f1bbcdc;
121                         f = (b & c) | (b & d) | (c & d);
122                 } else {
123                         K = 0xca62c1d6;
124                         f = b ^ c ^ d;
125                 }
126                 temp = lrot(a,5) + f + e + W[t] + K;
127                 e = d;
128                 d = c;
129                 c = lrot(b,30);
130                 b = a;
131                 a = temp;
132                 //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e );
133         }
134         /* add variables */
135         H0 += a;
136         H1 += b;
137         H2 += c;
138         H3 += d;
139         H4 += e;
140         //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 );
141         /* all bytes have been processed */
142         unprocessedBytes = 0;
143 }
144
145 // addBytes **********************************************************
146 void SHA1::addBytes( const char* data, int num )
147 {
148         assert( data );
149         assert( num > 0 );
150         // add these bytes to the running total
151         size += num;
152         // repeat until all data is processed
153         while( num > 0 )
154         {
155                 // number of bytes required to complete block
156                 int needed = 64 - unprocessedBytes;
157                 assert( needed > 0 );
158                 // number of bytes to copy (use smaller of two)
159                 int toCopy = (num < needed) ? num : needed;
160                 // Copy the bytes
161                 memcpy( bytes + unprocessedBytes, data, toCopy );
162                 // Bytes have been copied
163                 num -= toCopy;
164                 data += toCopy;
165                 unprocessedBytes += toCopy;
166                 
167                 // there is a full block
168                 if( unprocessedBytes == 64 ) process();
169         }
170 }
171
172 // digest ************************************************************
173 unsigned char* SHA1::getDigest()
174 {
175         // save the message size
176         Uint32 totalBitsL = size << 3;
177         Uint32 totalBitsH = size >> 29;
178         // add 0x80 to the message
179         addBytes( "\x80", 1 );
180         
181         unsigned char footer[64] = {
182                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
183                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
184                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
185                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
186         // block has no room for 8-byte filesize, so finish it
187         if( unprocessedBytes > 56 )
188                 addBytes( (char*)footer, 64 - unprocessedBytes);
189         assert( unprocessedBytes <= 56 );
190         // how many zeros do we need
191         int neededZeros = 56 - unprocessedBytes;
192         // store file size (in bits) in big-endian format
193         storeBigEndianUint32( footer + neededZeros    , totalBitsH );
194         storeBigEndianUint32( footer + neededZeros + 4, totalBitsL );
195         // finish the final block
196         addBytes( (char*)footer, neededZeros + 8 );
197         // allocate memory for the digest bytes
198         unsigned char* digest = (unsigned char*)malloc( 20 );
199         // copy the digest bytes
200         storeBigEndianUint32( digest, H0 );
201         storeBigEndianUint32( digest + 4, H1 );
202         storeBigEndianUint32( digest + 8, H2 );
203         storeBigEndianUint32( digest + 12, H3 );
204         storeBigEndianUint32( digest + 16, H4 );
205         // return the digest
206         return digest;
207 }