summaryrefslogtreecommitdiff
path: root/src/stable/sha1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/stable/sha1.cpp')
-rw-r--r--src/stable/sha1.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/stable/sha1.cpp b/src/stable/sha1.cpp
new file mode 100644
index 0000000..bfe4c5a
--- /dev/null
+++ b/src/stable/sha1.cpp
@@ -0,0 +1,194 @@
1/*
2 * Copyright (C) 2007-2011 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include <string.h>
9
10#include "bu/stream.h"
11
12#include "bu/sha1.h"
13
14Bu::Sha1::Sha1() :
15 uH0( 0x67452301 ),
16 uH1( 0xefcdab89 ),
17 uH2( 0x98badcfe ),
18 uH3( 0x10325476 ),
19 uH4( 0xc3d2e1f0 ),
20 iUnprocessedBytes( 0 ),
21 uTotalBytes( 0 )
22{
23 reset();
24}
25
26Bu::Sha1::~Sha1()
27{
28}
29
30void Bu::Sha1::reset()
31{
32 uH0 = 0x67452301;
33 uH1 = 0xefcdab89;
34 uH2 = 0x98badcfe;
35 uH3 = 0x10325476;
36 uH4 = 0xc3d2e1f0;
37 iUnprocessedBytes = 0;
38 uTotalBytes = 0;
39}
40
41void Bu::Sha1::setSalt( const Bu::String & /*sSalt*/ )
42{
43}
44
45void Bu::Sha1::addData( const void *sDataRaw, int iSize )
46{
47 const unsigned char *sData = (const unsigned char *)sDataRaw;
48 // add these bytes to the running total
49 uTotalBytes += iSize;
50
51 // repeat until all data is processed
52 while( iSize > 0 )
53 {
54 // number of bytes required to complete block
55 int iNeeded = 64 - iUnprocessedBytes;
56
57 // number of bytes to copy (use smaller of two)
58 int iToCopy = (iSize < iNeeded) ? iSize : iNeeded;
59
60 // Copy the bytes
61 memcpy( uBytes + iUnprocessedBytes, sData, iToCopy );
62
63 // Bytes have been copied
64 iSize -= iToCopy;
65 sData += iToCopy;
66 iUnprocessedBytes += iToCopy;
67
68 // there is a full block
69 if( iUnprocessedBytes == 64 )
70 {
71 process();
72 }
73 }
74}
75
76Bu::String Bu::Sha1::getResult()
77{
78 // save the message size
79 uint32_t totalBitsL = uTotalBytes << 3;
80 uint32_t totalBitsH = uTotalBytes >> 29;
81
82 // add 0x80 to the message
83 addData( "\x80", 1 );
84
85 unsigned char footer[64] = {
86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
87 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
88 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
89 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
90
91 // block has no room for 8-byte filesize, so finish it
92 if( iUnprocessedBytes > 56 )
93 addData( (char*)footer, 64 - iUnprocessedBytes);
94
95 // how many zeros do we need
96 int iNeededZeros = 56 - iUnprocessedBytes;
97
98 // store file size (in bits) in big-endian format
99 toBigEndian( totalBitsH, footer + iNeededZeros );
100 toBigEndian( totalBitsL, footer + iNeededZeros + 4 );
101
102 // finish the final block
103 addData( (char*)footer, iNeededZeros + 8 );
104
105 Bu::String sRet( 20 );
106
107 unsigned char *digest = (unsigned char *)sRet.getStr();
108
109 // copy the digest bytes
110 toBigEndian( uH0, digest );
111 toBigEndian( uH1, digest + 4 );
112 toBigEndian( uH2, digest + 8 );
113 toBigEndian( uH3, digest + 12 );
114 toBigEndian( uH4, digest + 16 );
115
116 // return the digest
117 return sRet;
118}
119
120void Bu::Sha1::writeResult( Bu::Stream &sOut )
121{
122 sOut.write( getResult() );
123}
124
125void Bu::Sha1::process()
126{
127 int t;
128 uint32_t a, b, c, d, e, K, f, W[80];
129
130 // starting values
131 a = uH0;
132 b = uH1;
133 c = uH2;
134 d = uH3;
135 e = uH4;
136
137 // copy and expand the message block
138 for( t = 0; t < 16; t++ ) W[t] = (uBytes[t*4] << 24)
139 +(uBytes[t*4 + 1] << 16)
140 +(uBytes[t*4 + 2] << 8)
141 + uBytes[t*4 + 3];
142 for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 );
143
144 /* main loop */
145 uint32_t temp;
146 for( t = 0; t < 80; t++ )
147 {
148 if( t < 20 ) {
149 K = 0x5a827999;
150 f = (b & c) | ((~b) & d);
151 } else if( t < 40 ) {
152 K = 0x6ed9eba1;
153 f = b ^ c ^ d;
154 } else if( t < 60 ) {
155 K = 0x8f1bbcdc;
156 f = (b & c) | (b & d) | (c & d);
157 } else {
158 K = 0xca62c1d6;
159 f = b ^ c ^ d;
160 }
161 temp = lrot(a,5) + f + e + W[t] + K;
162 e = d;
163 d = c;
164 c = lrot(b,30);
165 b = a;
166 a = temp;
167 //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e );
168 }
169
170 /* add variables */
171 uH0 += a;
172 uH1 += b;
173 uH2 += c;
174 uH3 += d;
175 uH4 += e;
176
177 //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 );
178 /* all bytes have been processed */
179 iUnprocessedBytes = 0;
180}
181
182uint32_t Bu::Sha1::lrot( uint32_t x, int bits )
183{
184 return (x<<bits) | (x>>(32 - bits));
185}
186
187void Bu::Sha1::toBigEndian( uint32_t num, unsigned char* byte )
188{
189 byte[0] = (unsigned char)(num>>24);
190 byte[1] = (unsigned char)(num>>16);
191 byte[2] = (unsigned char)(num>>8);
192 byte[3] = (unsigned char)num;
193}
194