gloox  0.9.9.12
sha.cpp
1 /*
2  Copyright (c) 2006-2008 by Jakob Schroeter <js@camaya.net>
3  This file is part of the gloox library. http://camaya.net/gloox
4 
5  This software is distributed under a license. The full license
6  agreement can be found in the file LICENSE in this distribution.
7  This software may not be copied, modified, sold or distributed
8  other than expressed in the named license agreement.
9 
10  This software is distributed without any warranty.
11 */
12 
13 #include "sha.h"
14 
15 #include <cstdio>
16 
17 namespace gloox
18 {
19 
21  {
22  init();
23  }
24 
26  {
27  }
28 
29  void SHA::init()
30  {
31  Length_Low = 0;
32  Length_High = 0;
33  Message_Block_Index = 0;
34 
35  H[0] = 0x67452301;
36  H[1] = 0xEFCDAB89;
37  H[2] = 0x98BADCFE;
38  H[3] = 0x10325476;
39  H[4] = 0xC3D2E1F0;
40 
41  m_finished = false;
42  m_corrupted = false;
43  }
44 
45  void SHA::reset()
46  {
47  init();
48  }
49 
50  const std::string SHA::hex()
51  {
52  if( m_corrupted )
53  return "";
54 
55  if( !m_finished )
56  {
57  pad();
58  m_finished = true;
59  }
60 
61  char buf[41];
62  for( int i = 0; i < 20; ++i )
63  sprintf( buf + i * 2, "%02x", (unsigned char)( H[i >> 2] >> ( ( 3 - ( i & 3 ) ) << 3 ) ) );
64 
65  return std::string( buf, 40 );
66  }
67 
69  {
70  if( !m_finished )
71  {
72  pad();
73  m_finished = true;
74  return;
75  }
76  }
77 
78  void SHA::feed( const unsigned char *data, unsigned length )
79  {
80  if( !length )
81  return;
82 
83  if( m_finished || m_corrupted )
84  {
85  m_corrupted = true;
86  return;
87  }
88 
89  while( length-- && !m_corrupted )
90  {
91  Message_Block[Message_Block_Index++] = ( *data & 0xFF );
92 
93  Length_Low += 8;
94  Length_Low &= 0xFFFFFFFF;
95  if( Length_Low == 0 )
96  {
97  Length_High++;
98  Length_High &= 0xFFFFFFFF;
99  if( Length_High == 0 )
100  {
101  m_corrupted = true;
102  }
103  }
104 
105  if( Message_Block_Index == 64 )
106  {
107  process();
108  }
109 
110  ++data;
111  }
112  }
113 
114  void SHA::feed( const std::string& data )
115  {
116  feed( (const unsigned char*)data.c_str(), data.length() );
117  }
118 
119  void SHA::process()
120  {
121  const unsigned K[] = { 0x5A827999,
122  0x6ED9EBA1,
123  0x8F1BBCDC,
124  0xCA62C1D6
125  };
126  int t;
127  unsigned temp;
128  unsigned W[80];
129  unsigned A, B, C, D, E;
130 
131  for( t = 0; t < 16; t++ )
132  {
133  W[t] = ((unsigned) Message_Block[t * 4]) << 24;
134  W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16;
135  W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8;
136  W[t] |= ((unsigned) Message_Block[t * 4 + 3]);
137  }
138 
139  for( t = 16; t < 80; ++t )
140  {
141  W[t] = shift( 1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16] );
142  }
143 
144  A = H[0];
145  B = H[1];
146  C = H[2];
147  D = H[3];
148  E = H[4];
149 
150  for( t = 0; t < 20; ++t )
151  {
152  temp = shift( 5, A ) + ( ( B & C ) | ( ( ~B ) & D ) ) + E + W[t] + K[0];
153  temp &= 0xFFFFFFFF;
154  E = D;
155  D = C;
156  C = shift( 30, B );
157  B = A;
158  A = temp;
159  }
160 
161  for( t = 20; t < 40; ++t )
162  {
163  temp = shift( 5, A ) + ( B ^ C ^ D ) + E + W[t] + K[1];
164  temp &= 0xFFFFFFFF;
165  E = D;
166  D = C;
167  C = shift( 30, B );
168  B = A;
169  A = temp;
170  }
171 
172  for( t = 40; t < 60; ++t )
173  {
174  temp = shift( 5, A ) + ( ( B & C ) | ( B & D ) | ( C & D ) ) + E + W[t] + K[2];
175  temp &= 0xFFFFFFFF;
176  E = D;
177  D = C;
178  C = shift( 30, B );
179  B = A;
180  A = temp;
181  }
182 
183  for( t = 60; t < 80; ++t )
184  {
185  temp = shift( 5, A ) + ( B ^ C ^ D ) + E + W[t] + K[3];
186  temp &= 0xFFFFFFFF;
187  E = D;
188  D = C;
189  C = shift( 30, B );
190  B = A;
191  A = temp;
192  }
193 
194  H[0] = ( H[0] + A ) & 0xFFFFFFFF;
195  H[1] = ( H[1] + B ) & 0xFFFFFFFF;
196  H[2] = ( H[2] + C ) & 0xFFFFFFFF;
197  H[3] = ( H[3] + D ) & 0xFFFFFFFF;
198  H[4] = ( H[4] + E ) & 0xFFFFFFFF;
199 
200  Message_Block_Index = 0;
201  }
202 
203  void SHA::pad()
204  {
205  if( Message_Block_Index > 55 )
206  {
207  Message_Block[Message_Block_Index++] = 0x80;
208  while( Message_Block_Index < 64 )
209  {
210  Message_Block[Message_Block_Index++] = 0;
211  }
212 
213  process();
214 
215  while( Message_Block_Index < 56 )
216  {
217  Message_Block[Message_Block_Index++] = 0;
218  }
219  }
220  else
221  {
222  Message_Block[Message_Block_Index++] = 0x80;
223  while( Message_Block_Index < 56 )
224  {
225  Message_Block[Message_Block_Index++] = 0;
226  }
227 
228  }
229 
230  Message_Block[56] = ( Length_High >> 24 ) & 0xFF;
231  Message_Block[57] = ( Length_High >> 16 ) & 0xFF;
232  Message_Block[58] = ( Length_High >> 8 ) & 0xFF;
233  Message_Block[59] = ( Length_High ) & 0xFF;
234  Message_Block[60] = ( Length_Low >> 24 ) & 0xFF;
235  Message_Block[61] = ( Length_Low >> 16 ) & 0xFF;
236  Message_Block[62] = ( Length_Low >> 8 ) & 0xFF;
237  Message_Block[63] = ( Length_Low ) & 0xFF;
238 
239  process();
240  }
241 
242 
243  unsigned SHA::shift( int bits, unsigned word )
244  {
245  return ( ( word << bits ) & 0xFFFFFFFF) | ( ( word & 0xFFFFFFFF ) >> ( 32-bits ) );
246  }
247 
248 }