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