gloox  1.0.9
sha.cpp
1 /*
2  Copyright (c) 2006-2013 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  if( !m_finished )
59  finalize();
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 
68  const std::string SHA::binary()
69  {
70  if( !m_finished )
71  finalize();
72 
73  unsigned char digest[20];
74  for( int i = 0; i < 20; ++i )
75  digest[i] = (unsigned char)( H[i >> 2] >> ( ( 3 - ( i & 3 ) ) << 3 ) );
76 
77  return std::string( (char*)digest, 20 );
78  }
79 
81  {
82  if( !m_finished )
83  {
84  pad();
85  m_finished = true;
86  }
87  }
88 
89  void SHA::feed( const unsigned char* data, unsigned length )
90  {
91  if( !length )
92  return;
93 
94  if( m_finished || m_corrupted )
95  {
96  m_corrupted = true;
97  return;
98  }
99 
100  while( length-- && !m_corrupted )
101  {
102  Message_Block[Message_Block_Index++] = ( *data & 0xFF );
103 
104  Length_Low += 8;
105  Length_Low &= 0xFFFFFFFF;
106  if( Length_Low == 0 )
107  {
108  Length_High++;
109  Length_High &= 0xFFFFFFFF;
110  if( Length_High == 0 )
111  {
112  m_corrupted = true;
113  }
114  }
115 
116  if( Message_Block_Index == 64 )
117  {
118  process();
119  }
120 
121  ++data;
122  }
123  }
124 
125  void SHA::feed( const std::string& data )
126  {
127  feed( (const unsigned char*)data.c_str(), (int)data.length() );
128  }
129 
130  void SHA::process()
131  {
132  const unsigned K[] = { 0x5A827999,
133  0x6ED9EBA1,
134  0x8F1BBCDC,
135  0xCA62C1D6
136  };
137  int t;
138  unsigned temp;
139  unsigned W[80];
140  unsigned A, B, C, D, E;
141 
142  for( t = 0; t < 16; t++ )
143  {
144  W[t] = ((unsigned) Message_Block[t * 4]) << 24;
145  W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16;
146  W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8;
147  W[t] |= ((unsigned) Message_Block[t * 4 + 3]);
148  }
149 
150  for( t = 16; t < 80; ++t )
151  {
152  W[t] = shift( 1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16] );
153  }
154 
155  A = H[0];
156  B = H[1];
157  C = H[2];
158  D = H[3];
159  E = H[4];
160 
161  for( t = 0; t < 20; ++t )
162  {
163  temp = shift( 5, A ) + ( ( B & C ) | ( ( ~B ) & D ) ) + E + W[t] + K[0];
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 = 20; t < 40; ++t )
173  {
174  temp = shift( 5, A ) + ( B ^ C ^ D ) + E + W[t] + K[1];
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 = 40; t < 60; ++t )
184  {
185  temp = shift( 5, A ) + ( ( B & C ) | ( B & D ) | ( C & D ) ) + E + W[t] + K[2];
186  temp &= 0xFFFFFFFF;
187  E = D;
188  D = C;
189  C = shift( 30, B );
190  B = A;
191  A = temp;
192  }
193 
194  for( t = 60; t < 80; ++t )
195  {
196  temp = shift( 5, A ) + ( B ^ C ^ D ) + E + W[t] + K[3];
197  temp &= 0xFFFFFFFF;
198  E = D;
199  D = C;
200  C = shift( 30, B );
201  B = A;
202  A = temp;
203  }
204 
205  H[0] = ( H[0] + A ) & 0xFFFFFFFF;
206  H[1] = ( H[1] + B ) & 0xFFFFFFFF;
207  H[2] = ( H[2] + C ) & 0xFFFFFFFF;
208  H[3] = ( H[3] + D ) & 0xFFFFFFFF;
209  H[4] = ( H[4] + E ) & 0xFFFFFFFF;
210 
211  Message_Block_Index = 0;
212  }
213 
214  void SHA::pad()
215  {
216  Message_Block[Message_Block_Index++] = 0x80;
217 
218  if( Message_Block_Index > 56 )
219  {
220  while( Message_Block_Index < 64 )
221  {
222  Message_Block[Message_Block_Index++] = 0;
223  }
224 
225  process();
226  }
227 
228  while( Message_Block_Index < 56 )
229  {
230  Message_Block[Message_Block_Index++] = 0;
231  }
232 
233  Message_Block[56] = static_cast<unsigned char>( ( Length_High >> 24 ) & 0xFF );
234  Message_Block[57] = static_cast<unsigned char>( ( Length_High >> 16 ) & 0xFF );
235  Message_Block[58] = static_cast<unsigned char>( ( Length_High >> 8 ) & 0xFF );
236  Message_Block[59] = static_cast<unsigned char>( ( Length_High ) & 0xFF );
237  Message_Block[60] = static_cast<unsigned char>( ( Length_Low >> 24 ) & 0xFF );
238  Message_Block[61] = static_cast<unsigned char>( ( Length_Low >> 16 ) & 0xFF );
239  Message_Block[62] = static_cast<unsigned char>( ( Length_Low >> 8 ) & 0xFF );
240  Message_Block[63] = static_cast<unsigned char>( ( Length_Low ) & 0xFF );
241 
242  process();
243  }
244 
245 
246  unsigned SHA::shift( int bits, unsigned word )
247  {
248  return ( ( word << bits ) & 0xFFFFFFFF) | ( ( word & 0xFFFFFFFF ) >> ( 32-bits ) );
249  }
250 
251 }