diff options
Diffstat (limited to '')
-rw-r--r-- | src/sha1.cpp | 216 |
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 | ||
14 | Sha1::Sha1() : | 14 | Bu::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 | ||
25 | Sha1::~Sha1() | 26 | Bu::Sha1::~Sha1() |
26 | { | 27 | { |
27 | } | 28 | } |
28 | 29 | ||
29 | void Sha1::process() | 30 | void 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 ); | 41 | void Bu::Sha1::setSalt( const Bu::FString & /*sSalt*/ ) |
82 | /* all bytes have been processed */ | 42 | { |
83 | unprocessedBytes = 0; | ||
84 | } | 43 | } |
85 | 44 | ||
86 | void Sha1::update( const char* data, int num ) | 45 | void 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 | ||
113 | unsigned char* Sha1::getDigest() | 76 | Bu::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 | ||
156 | uint32_t Sha1::lrot( uint32_t x, int bits ) | 120 | void Bu::Sha1::writeResult( Bu::Stream &sOut ) |
121 | { | ||
122 | sOut.write( getResult() ); | ||
123 | } | ||
124 | |||
125 | void 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 | |||
182 | uint32_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 | ||
161 | void Sha1::toBigEndian( uint32_t num, unsigned char* byte ) | 187 | void 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); |