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