source: XMLIO_V2/external/src/POCO/Foundation.save/SHA1Engine.cpp @ 80

Last change on this file since 80 was 80, checked in by ymipsl, 14 years ago

ajout lib externe

  • Property svn:eol-style set to native
File size: 9.2 KB
Line 
1//
2// SHA1Engine.cpp
3//
4// $Id: //poco/1.3/Foundation/src/SHA1Engine.cpp#2 $
5//
6// Library: Foundation
7// Package: Crypt
8// Module:  SHA1Engine
9//
10// Based on the public domain implementation by Peter C. Gutmann
11// on 2 Sep 1992, modified by Carl Ellison to be SHA-1.
12//
13// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
14// and Contributors.
15//
16// Permission is hereby granted, free of charge, to any person or organization
17// obtaining a copy of the software and accompanying documentation covered by
18// this license (the "Software") to use, reproduce, display, distribute,
19// execute, and transmit the Software, and to prepare derivative works of the
20// Software, and to permit third-parties to whom the Software is furnished to
21// do so, all subject to the following:
22//
23// The copyright notices in the Software and this entire statement, including
24// the above license grant, this restriction and the following disclaimer,
25// must be included in all copies of the Software, in whole or in part, and
26// all derivative works of the Software, unless such copies or derivative
27// works are solely in the form of machine-executable object code generated by
28// a source language processor.
29//
30// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
33// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
34// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
35// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
36// DEALINGS IN THE SOFTWARE.
37//
38
39
40#include "Poco/SHA1Engine.h"
41#include <cstring>
42
43
44#ifdef POCO_ARCH_LITTLE_ENDIAN
45        #define SHA1_BYTE_REVERSE(x, y) byteReverse(x, y)
46#else
47        #define SHA1_BYTE_REVERSE(x, y)
48#endif
49
50
51namespace Poco {
52
53
54SHA1Engine::SHA1Engine()
55{
56        _digest.reserve(16);
57        reset();
58}
59
60
61SHA1Engine::~SHA1Engine()
62{
63        reset();
64}
65
66
67inline void SHA1Engine::byteReverse(UInt32* buffer, int byteCount)
68{
69#ifdef POCO_ARCH_LITTLE_ENDIAN
70        byteCount /= sizeof(UInt32);
71        for(int count = 0; count < byteCount; count++)
72        {
73                UInt32 value = (buffer[ count ] << 16) | (buffer[ count ] >> 16);
74                buffer[count] = ((value & 0xFF00FF00L) >> 8) | ((value & 0x00FF00FFL) << 8);
75        }
76#endif // POCO_ARCH_LITTLE_ENDIAN
77}
78
79       
80void SHA1Engine::updateImpl(const void* buffer_, unsigned count)
81{
82        const BYTE* buffer = (const BYTE*) buffer_;
83        BYTE* db = (BYTE*) &_context.data[0];
84
85        /* Update bitcount */
86        if ((_context.countLo + ((UInt32) count << 3)) < _context.countLo)
87                _context.countHi++; /* Carry from low to high bitCount */
88        _context.countLo += ((UInt32) count << 3);
89        _context.countHi += ((UInt32 ) count >> 29);
90
91        /* Process data in BLOCK_SIZE chunks */
92        while (count-- > 0)
93        {
94                db[_context.slop++] = *(buffer++);
95                if (_context.slop == BLOCK_SIZE)
96                { 
97                        /* transform this one block */
98                        SHA1_BYTE_REVERSE(_context.data, BLOCK_SIZE);
99                        transform();
100                        _context.slop = 0 ;     /* no slop left */
101                }
102        }
103}
104
105
106unsigned SHA1Engine::digestLength() const
107{
108        return DIGEST_SIZE;
109}
110
111
112void SHA1Engine::reset()
113{
114        _context.digest[0] = 0x67452301L;
115        _context.digest[1] = 0xEFCDAB89L;
116        _context.digest[2] = 0x98BADCFEL;
117        _context.digest[3] = 0x10325476L;
118        _context.digest[4] = 0xC3D2E1F0L;
119        _context.countLo   = 0;
120        _context.countHi   = 0;
121        _context.slop      = 0;
122        std::memset(_context.data, 0, sizeof(_context.data));
123}
124
125
126const DigestEngine::Digest& SHA1Engine::digest()
127{
128        int count;
129        UInt32 lowBitcount  = _context.countLo;
130        UInt32 highBitcount = _context.countHi;
131
132        /* Compute number of bytes mod 64 */
133        count = (int) ((_context.countLo >> 3) & 0x3F);
134
135        /* Set the first char of padding to 0x80.  This is safe since there is
136                always at least one byte free */
137        ((BYTE*) _context.data)[count++] = 0x80;
138
139        /* Pad out to 56 mod 64 */
140        if (count > 56)
141        {
142                /* Two lots of padding:  Pad the first block to 64 bytes */
143                std::memset((BYTE*) &_context.data + count, 0, 64 - count);
144                SHA1_BYTE_REVERSE(_context.data, BLOCK_SIZE);
145                transform();
146
147                /* Now fill the next block with 56 bytes */
148                std::memset(&_context.data, 0, 56);
149        }
150        else
151        {
152                /* Pad block to 56 bytes */
153                std::memset((BYTE*) &_context.data + count, 0, 56 - count);
154        }
155        SHA1_BYTE_REVERSE(_context.data, BLOCK_SIZE);
156
157        /* Append length in bits and transform */
158        _context.data[14] = highBitcount;
159        _context.data[15] = lowBitcount;
160
161        transform();
162        SHA1_BYTE_REVERSE(_context.data, DIGEST_SIZE);
163
164        unsigned char hash[DIGEST_SIZE];
165        for (count = 0; count < DIGEST_SIZE; count++)
166                hash[count] = (BYTE) ((_context.digest[count>>2]) >> (8*(3-(count & 0x3)))) & 0xff;
167        _digest.clear();
168        _digest.insert(_digest.begin(), hash, hash + DIGEST_SIZE);
169        reset();
170        return _digest;
171}
172
173
174/* The SHA f()-functions */
175#define f1(x,y,z)   ( ( x & y ) | ( ~x & z ) )              /* Rounds  0-19 */
176#define f2(x,y,z)   ( x ^ y ^ z )                           /* Rounds 20-39 */
177#define f3(x,y,z)   ( ( x & y ) | ( x & z ) | ( y & z ) )   /* Rounds 40-59 */
178#define f4(x,y,z)   ( x ^ y ^ z )                           /* Rounds 60-79 */
179
180
181/* The SHA Mysterious Constants */
182#define K1  0x5A827999L     /* Rounds  0-19 */
183#define K2  0x6ED9EBA1L     /* Rounds 20-39 */
184#define K3  0x8F1BBCDCL     /* Rounds 40-59 */
185#define K4  0xCA62C1D6L     /* Rounds 60-79 */
186
187
188/* 32-bit rotate - kludged with shifts */
189typedef UInt32 UL;      /* to save space */
190
191
192#define S(n,X)  ( ( ((UL)X) << n ) | ( ((UL)X) >> ( 32 - n ) ) )
193
194
195/* The initial expanding function */
196#define expand(count)   W[ count ] = S(1,(W[ count - 3 ] ^ W[ count - 8 ] ^ W[ count - 14 ] ^ W[ count - 16 ])) /* to make this SHA-1 */
197
198
199/* The four SHA sub-rounds */
200#define subRound1(count)    \
201{ \
202    temp = S( 5, A ) + f1( B, C, D ) + E + W[ count ] + K1; \
203    E = D; \
204    D = C; \
205    C = S( 30, B ); \
206    B = A; \
207    A = temp; \
208}
209
210#define subRound2(count)    \
211{ \
212    temp = S( 5, A ) + f2( B, C, D ) + E + W[ count ] + K2; \
213    E = D; \
214    D = C; \
215    C = S( 30, B ); \
216    B = A; \
217    A = temp; \
218}
219
220#define subRound3(count)    \
221{ \
222    temp = S( 5, A ) + f3( B, C, D ) + E + W[ count ] + K3; \
223    E = D; \
224    D = C; \
225    C = S( 30, B ); \
226    B = A; \
227    A = temp; \
228}
229
230#define subRound4(count)    \
231{ \
232    temp = S( 5, A ) + f4( B, C, D ) + E + W[ count ] + K4; \
233    E = D; \
234    D = C; \
235    C = S( 30, B ); \
236    B = A; \
237    A = temp; \
238}
239
240
241void SHA1Engine::transform()
242{
243        UInt32 W[80];
244        UInt32 temp;
245        UInt32 A, B, C, D, E;
246        int i;
247
248        /* Step A.  Copy the data buffer into the local work buffer */
249        for( i = 0; i < 16; i++ )
250        W[ i ] = _context.data[ i ];
251
252        /* Step B.  Expand the 16 words into 64 temporary data words */
253        expand( 16 ); expand( 17 ); expand( 18 ); expand( 19 ); expand( 20 );
254        expand( 21 ); expand( 22 ); expand( 23 ); expand( 24 ); expand( 25 );
255        expand( 26 ); expand( 27 ); expand( 28 ); expand( 29 ); expand( 30 );
256        expand( 31 ); expand( 32 ); expand( 33 ); expand( 34 ); expand( 35 );
257        expand( 36 ); expand( 37 ); expand( 38 ); expand( 39 ); expand( 40 );
258        expand( 41 ); expand( 42 ); expand( 43 ); expand( 44 ); expand( 45 );
259        expand( 46 ); expand( 47 ); expand( 48 ); expand( 49 ); expand( 50 );
260        expand( 51 ); expand( 52 ); expand( 53 ); expand( 54 ); expand( 55 );
261        expand( 56 ); expand( 57 ); expand( 58 ); expand( 59 ); expand( 60 );
262        expand( 61 ); expand( 62 ); expand( 63 ); expand( 64 ); expand( 65 );
263        expand( 66 ); expand( 67 ); expand( 68 ); expand( 69 ); expand( 70 );
264        expand( 71 ); expand( 72 ); expand( 73 ); expand( 74 ); expand( 75 );
265        expand( 76 ); expand( 77 ); expand( 78 ); expand( 79 );
266
267        /* Step C.  Set up first buffer */
268        A = _context.digest[ 0 ];
269        B = _context.digest[ 1 ];
270        C = _context.digest[ 2 ];
271        D = _context.digest[ 3 ];
272        E = _context.digest[ 4 ];
273
274        /* Step D.  Serious mangling, divided into four sub-rounds */
275        subRound1( 0 ); subRound1( 1 ); subRound1( 2 ); subRound1( 3 );
276        subRound1( 4 ); subRound1( 5 ); subRound1( 6 ); subRound1( 7 );
277        subRound1( 8 ); subRound1( 9 ); subRound1( 10 ); subRound1( 11 );
278        subRound1( 12 ); subRound1( 13 ); subRound1( 14 ); subRound1( 15 );
279        subRound1( 16 ); subRound1( 17 ); subRound1( 18 ); subRound1( 19 );
280        subRound2( 20 ); subRound2( 21 ); subRound2( 22 ); subRound2( 23 );
281        subRound2( 24 ); subRound2( 25 ); subRound2( 26 ); subRound2( 27 );
282        subRound2( 28 ); subRound2( 29 ); subRound2( 30 ); subRound2( 31 );
283        subRound2( 32 ); subRound2( 33 ); subRound2( 34 ); subRound2( 35 );
284        subRound2( 36 ); subRound2( 37 ); subRound2( 38 ); subRound2( 39 );
285        subRound3( 40 ); subRound3( 41 ); subRound3( 42 ); subRound3( 43 );
286        subRound3( 44 ); subRound3( 45 ); subRound3( 46 ); subRound3( 47 );
287        subRound3( 48 ); subRound3( 49 ); subRound3( 50 ); subRound3( 51 );
288        subRound3( 52 ); subRound3( 53 ); subRound3( 54 ); subRound3( 55 );
289        subRound3( 56 ); subRound3( 57 ); subRound3( 58 ); subRound3( 59 );
290        subRound4( 60 ); subRound4( 61 ); subRound4( 62 ); subRound4( 63 );
291        subRound4( 64 ); subRound4( 65 ); subRound4( 66 ); subRound4( 67 );
292        subRound4( 68 ); subRound4( 69 ); subRound4( 70 ); subRound4( 71 );
293        subRound4( 72 ); subRound4( 73 ); subRound4( 74 ); subRound4( 75 );
294        subRound4( 76 ); subRound4( 77 ); subRound4( 78 ); subRound4( 79 );
295
296        /* Step E.  Build message digest */
297        _context.digest[ 0 ] += A;
298        _context.digest[ 1 ] += B;
299        _context.digest[ 2 ] += C;
300        _context.digest[ 3 ] += D;
301        _context.digest[ 4 ] += E;
302}
303
304
305} // namespace Poco
Note: See TracBrowser for help on using the repository browser.