]> git.lizzy.rs Git - dragonfireclient.git/blob - src/sha1.cpp
Passwords - password entry at main menu, stored and checked by server
[dragonfireclient.git] / src / sha1.cpp
1 /* sha1.cpp
2
3 Copyright (c) 2005 Michael D. Leonhard
4
5 http://tamale.net/
6
7 This file is licensed under the terms described in the
8 accompanying LICENSE file.
9 */
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <assert.h>
15
16 #include "sha1.h"
17
18 // print out memory in hexadecimal
19 void SHA1::hexPrinter( unsigned char* c, int l )
20 {
21         assert( c );
22         assert( l > 0 );
23         while( l > 0 )
24         {
25                 printf( " %02x", *c );
26                 l--;
27                 c++;
28         }
29 }
30
31 // circular left bit rotation.  MSB wraps around to LSB
32 Uint32 SHA1::lrot( Uint32 x, int bits )
33 {
34         return (x<<bits) | (x>>(32 - bits));
35 };
36
37 // Save a 32-bit unsigned integer to memory, in big-endian order
38 void SHA1::storeBigEndianUint32( unsigned char* byte, Uint32 num )
39 {
40         assert( byte );
41         byte[0] = (unsigned char)(num>>24);
42         byte[1] = (unsigned char)(num>>16);
43         byte[2] = (unsigned char)(num>>8);
44         byte[3] = (unsigned char)num;
45 }
46
47
48 // Constructor *******************************************************
49 SHA1::SHA1()
50 {
51         // make sure that the data type is the right size
52         assert( sizeof( Uint32 ) * 5 == 20 );
53         
54         // initialize
55         H0 = 0x67452301;
56         H1 = 0xefcdab89;
57         H2 = 0x98badcfe;
58         H3 = 0x10325476;
59         H4 = 0xc3d2e1f0;
60         unprocessedBytes = 0;
61         size = 0;
62 }
63
64 // Destructor ********************************************************
65 SHA1::~SHA1()
66 {
67         // erase data
68         H0 = H1 = H2 = H3 = H4 = 0;
69         for( int c = 0; c < 64; c++ ) bytes[c] = 0;
70         unprocessedBytes = size = 0;
71 }
72
73 // process ***********************************************************
74 void SHA1::process()
75 {
76         assert( unprocessedBytes == 64 );
77         //printf( "process: " ); hexPrinter( bytes, 64 ); printf( "\n" );
78         int t;
79         Uint32 a, b, c, d, e, K, f, W[80];
80         // starting values
81         a = H0;
82         b = H1;
83         c = H2;
84         d = H3;
85         e = H4;
86         // copy and expand the message block
87         for( t = 0; t < 16; t++ ) W[t] = (bytes[t*4] << 24)
88                                                                         +(bytes[t*4 + 1] << 16)
89                                                                         +(bytes[t*4 + 2] << 8)
90                                                                         + bytes[t*4 + 3];
91         for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 );
92         
93         /* main loop */
94         Uint32 temp;
95         for( t = 0; t < 80; t++ )
96         {
97                 if( t < 20 ) {
98                         K = 0x5a827999;
99                         f = (b & c) | ((b ^ 0xFFFFFFFF) & d);//TODO: try using ~
100                 } else if( t < 40 ) {
101                         K = 0x6ed9eba1;
102                         f = b ^ c ^ d;
103                 } else if( t < 60 ) {
104                         K = 0x8f1bbcdc;
105                         f = (b & c) | (b & d) | (c & d);
106                 } else {
107                         K = 0xca62c1d6;
108                         f = b ^ c ^ d;
109                 }
110                 temp = lrot(a,5) + f + e + W[t] + K;
111                 e = d;
112                 d = c;
113                 c = lrot(b,30);
114                 b = a;
115                 a = temp;
116                 //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e );
117         }
118         /* add variables */
119         H0 += a;
120         H1 += b;
121         H2 += c;
122         H3 += d;
123         H4 += e;
124         //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 );
125         /* all bytes have been processed */
126         unprocessedBytes = 0;
127 }
128
129 // addBytes **********************************************************
130 void SHA1::addBytes( const char* data, int num )
131 {
132         assert( data );
133         assert( num > 0 );
134         // add these bytes to the running total
135         size += num;
136         // repeat until all data is processed
137         while( num > 0 )
138         {
139                 // number of bytes required to complete block
140                 int needed = 64 - unprocessedBytes;
141                 assert( needed > 0 );
142                 // number of bytes to copy (use smaller of two)
143                 int toCopy = (num < needed) ? num : needed;
144                 // Copy the bytes
145                 memcpy( bytes + unprocessedBytes, data, toCopy );
146                 // Bytes have been copied
147                 num -= toCopy;
148                 data += toCopy;
149                 unprocessedBytes += toCopy;
150                 
151                 // there is a full block
152                 if( unprocessedBytes == 64 ) process();
153         }
154 }
155
156 // digest ************************************************************
157 unsigned char* SHA1::getDigest()
158 {
159         // save the message size
160         Uint32 totalBitsL = size << 3;
161         Uint32 totalBitsH = size >> 29;
162         // add 0x80 to the message
163         addBytes( "\x80", 1 );
164         
165         unsigned char footer[64] = {
166                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
167                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
168                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
169                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
170         // block has no room for 8-byte filesize, so finish it
171         if( unprocessedBytes > 56 )
172                 addBytes( (char*)footer, 64 - unprocessedBytes);
173         assert( unprocessedBytes <= 56 );
174         // how many zeros do we need
175         int neededZeros = 56 - unprocessedBytes;
176         // store file size (in bits) in big-endian format
177         storeBigEndianUint32( footer + neededZeros    , totalBitsH );
178         storeBigEndianUint32( footer + neededZeros + 4, totalBitsL );
179         // finish the final block
180         addBytes( (char*)footer, neededZeros + 8 );
181         // allocate memory for the digest bytes
182         unsigned char* digest = (unsigned char*)malloc( 20 );
183         // copy the digest bytes
184         storeBigEndianUint32( digest, H0 );
185         storeBigEndianUint32( digest + 4, H1 );
186         storeBigEndianUint32( digest + 8, H2 );
187         storeBigEndianUint32( digest + 12, H3 );
188         storeBigEndianUint32( digest + 16, H4 );
189         // return the digest
190         return digest;
191 }