websocketpp  0.3.0
C++/Boost Asio based websocket client/server library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
sha1.hpp
1 /*
2 *****
3 sha1.hpp is a repackaging of the sha1.cpp and sha1.h files from the shallsha1
4 library (http://code.google.com/p/smallsha1/) into a single header suitable for
5 use as a header only library. This conversion was done by Peter Thorson
6 (webmaster@zaphoyd.com) in 2013. All modifications to the code are redistributed
7 under the same license as the original, which is listed below.
8 *****
9 
10  Copyright (c) 2011, Micael Hildenborg
11  All rights reserved.
12 
13  Redistribution and use in source and binary forms, with or without
14  modification, are permitted provided that the following conditions are met:
15  * Redistributions of source code must retain the above copyright
16  notice, this list of conditions and the following disclaimer.
17  * Redistributions in binary form must reproduce the above copyright
18  notice, this list of conditions and the following disclaimer in the
19  documentation and/or other materials provided with the distribution.
20  * Neither the name of Micael Hildenborg nor the
21  names of its contributors may be used to endorse or promote products
22  derived from this software without specific prior written permission.
23 
24  THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY
25  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY
28  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #ifndef SHA1_DEFINED
37 #define SHA1_DEFINED
38 
39 namespace websocketpp {
40 namespace sha1 {
41 
42  namespace // local
43  {
44  // Rotate an integer value to left.
45  inline const unsigned int rol(const unsigned int value,
46  const unsigned int steps)
47  {
48  return ((value << steps) | (value >> (32 - steps)));
49  }
50 
51  // Sets the first 16 integers in the buffert to zero.
52  // Used for clearing the W buffert.
53  inline void clearWBuffert(unsigned int* buffert)
54  {
55  for (int pos = 16; --pos >= 0;)
56  {
57  buffert[pos] = 0;
58  }
59  }
60 
61  inline void innerHash(unsigned int* result, unsigned int* w)
62  {
63  unsigned int a = result[0];
64  unsigned int b = result[1];
65  unsigned int c = result[2];
66  unsigned int d = result[3];
67  unsigned int e = result[4];
68 
69  int round = 0;
70 
71  #define sha1macro(func,val) \
72  { \
73  const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \
74  e = d; \
75  d = c; \
76  c = rol(b, 30); \
77  b = a; \
78  a = t; \
79  }
80 
81  while (round < 16)
82  {
83  sha1macro((b & c) | (~b & d), 0x5a827999)
84  ++round;
85  }
86  while (round < 20)
87  {
88  w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
89  sha1macro((b & c) | (~b & d), 0x5a827999)
90  ++round;
91  }
92  while (round < 40)
93  {
94  w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
95  sha1macro(b ^ c ^ d, 0x6ed9eba1)
96  ++round;
97  }
98  while (round < 60)
99  {
100  w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
101  sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc)
102  ++round;
103  }
104  while (round < 80)
105  {
106  w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
107  sha1macro(b ^ c ^ d, 0xca62c1d6)
108  ++round;
109  }
110 
111  #undef sha1macro
112 
113  result[0] += a;
114  result[1] += b;
115  result[2] += c;
116  result[3] += d;
117  result[4] += e;
118  }
119  } // namespace
120 
126  inline void calc(const void* src, const int bytelength, unsigned char* hash) {
127  // Init the result array.
128  unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
129 
130  // Cast the void src pointer to be the byte array we can work with.
131  const unsigned char* sarray = (const unsigned char*) src;
132 
133  // The reusable round buffer
134  unsigned int w[80];
135 
136  // Loop through all complete 64byte blocks.
137  const int endOfFullBlocks = bytelength - 64;
138  int endCurrentBlock;
139  int currentBlock = 0;
140 
141  while (currentBlock <= endOfFullBlocks)
142  {
143  endCurrentBlock = currentBlock + 64;
144 
145  // Init the round buffer with the 64 byte block data.
146  for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4)
147  {
148  // This line will swap endian on big endian and keep endian on little endian.
149  w[roundPos++] = (unsigned int) sarray[currentBlock + 3]
150  | (((unsigned int) sarray[currentBlock + 2]) << 8)
151  | (((unsigned int) sarray[currentBlock + 1]) << 16)
152  | (((unsigned int) sarray[currentBlock]) << 24);
153  }
154  innerHash(result, w);
155  }
156 
157  // Handle the last and not full 64 byte block if existing.
158  endCurrentBlock = bytelength - currentBlock;
159  clearWBuffert(w);
160  int lastBlockBytes = 0;
161  for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes)
162  {
163  w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3);
164  }
165  w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3);
166  if (endCurrentBlock >= 56)
167  {
168  innerHash(result, w);
169  clearWBuffert(w);
170  }
171  w[15] = bytelength << 3;
172  innerHash(result, w);
173 
174  // Store hash in result pointer, and make sure we get in in the correct order on both endian models.
175  for (int hashByte = 20; --hashByte >= 0;)
176  {
177  hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff;
178  }
179  }
180 
181 } // namespace sha1
182 } // namespace websocketpp
183 
184 #endif // SHA1_DEFINED
uint16_t value
The type of a close code value.
Definition: close.hpp:49
Namespace for the WebSocket++ project.
Definition: base64.hpp:41