94 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) 95 #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) 96 #define H(x, y, z) (((x) ^ (y)) ^ (z)) 97 #define H2(x, y, z) ((x) ^ ((y) ^ (z))) 98 #define I(x, y, z) ((y) ^ ((x) | ~(z))) 103 #define STEP(f, a, b, c, d, x, t, s) \ 104 (a) += f((b), (c), (d)) + (x) + (t); \ 105 (a) = (((a) << (s)) | (((a) & 0xFFFFFFFF) >> (32 - (s)))); \ 116 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) 118 (*const_cast<uint32 *>(reinterpret_cast<const uint32 *>(&ptr[(n) * 4]))) 124 (uint32)ptr[(n) * 4] | \ 125 ((uint32)ptr[(n) * 4 + 1] << 8) | \ 126 ((uint32)ptr[(n) * 4 + 2] << 16) | \ 127 ((uint32)ptr[(n) * 4 + 3] << 24)) 142 const byte *ptr = data;
151 STEP(
F, a, b, c, d,
SET(0), 0xD76AA478, 7)
152 STEP(
F, d, a, b, c,
SET(1), 0xE8C7B756, 12)
153 STEP(
F, c, d, a, b,
SET(2), 0x242070DB, 17)
154 STEP(
F, b, c, d, a,
SET(3), 0xC1BDCEEE, 22)
155 STEP(
F, a, b, c, d,
SET(4), 0xF57C0FAF, 7)
156 STEP(
F, d, a, b, c,
SET(5), 0x4787C62A, 12)
157 STEP(
F, c, d, a, b,
SET(6), 0xA8304613, 17)
158 STEP(
F, b, c, d, a,
SET(7), 0xFD469501, 22)
159 STEP(
F, a, b, c, d,
SET(8), 0x698098D8, 7)
160 STEP(
F, d, a, b, c,
SET(9), 0x8B44F7AF, 12)
161 STEP(
F, c, d, a, b,
SET(10), 0xFFFF5BB1, 17)
162 STEP(
F, b, c, d, a,
SET(11), 0x895CD7BE, 22)
163 STEP(
F, a, b, c, d,
SET(12), 0x6B901122, 7)
164 STEP(
F, d, a, b, c,
SET(13), 0xFD987193, 12)
165 STEP(
F, c, d, a, b,
SET(14), 0xA679438E, 17)
166 STEP(
F, b, c, d, a,
SET(15), 0x49B40821, 22)
169 STEP(
G, a, b, c, d,
GET(1), 0xF61E2562, 5)
171 STEP(
G, c, d, a, b,
GET(11), 0x265E5A51, 14)
172 STEP(
G, b, c, d, a,
GET(0), 0xE9B6C7AA, 20)
173 STEP(
G, a, b, c, d,
GET(5), 0xD62F105D, 5)
174 STEP(
G, d, a, b, c,
GET(10), 0x02441453, 9)
175 STEP(
G, c, d, a, b,
GET(15), 0xD8A1E681, 14)
176 STEP(
G, b, c, d, a,
GET(4), 0xE7D3FBC8, 20)
177 STEP(
G, a, b, c, d,
GET(9), 0x21E1CDE6, 5)
178 STEP(
G, d, a, b, c,
GET(14), 0xC33707D6, 9)
179 STEP(
G, c, d, a, b,
GET(3), 0xF4D50D87, 14)
180 STEP(
G, b, c, d, a,
GET(8), 0x455A14ED, 20)
181 STEP(
G, a, b, c, d,
GET(13), 0xA9E3E905, 5)
182 STEP(
G, d, a, b, c,
GET(2), 0xFCEFA3F8, 9)
183 STEP(
G, c, d, a, b,
GET(7), 0x676F02D9, 14)
184 STEP(
G, b, c, d, a,
GET(12), 0x8D2A4C8A, 20)
187 STEP(
H, a, b, c, d,
GET(5), 0xFFFA3942, 4)
188 STEP(
H2, d, a, b, c,
GET(8), 0x8771F681, 11)
189 STEP(
H, c, d, a, b,
GET(11), 0x6D9D6122, 16)
190 STEP(
H2, b, c, d, a,
GET(14), 0xFDE5380C, 23)
191 STEP(
H, a, b, c, d,
GET(1), 0xA4BEEA44, 4)
192 STEP(
H2, d, a, b, c,
GET(4), 0x4BDECFA9, 11)
193 STEP(
H, c, d, a, b,
GET(7), 0xF6BB4B60, 16)
194 STEP(
H2, b, c, d, a,
GET(10), 0xBEBFBC70, 23)
195 STEP(
H, a, b, c, d,
GET(13), 0x289B7EC6, 4)
196 STEP(
H2, d, a, b, c,
GET(0), 0xEAA127FA, 11)
197 STEP(
H, c, d, a, b,
GET(3), 0xD4EF3085, 16)
198 STEP(
H2, b, c, d, a,
GET(6), 0x04881D05, 23)
199 STEP(
H, a, b, c, d,
GET(9), 0xD9D4D039, 4)
201 STEP(
H, c, d, a, b,
GET(15), 0x1FA27CF8, 16)
202 STEP(
H2, b, c, d, a,
GET(2), 0xC4AC5665, 23)
205 STEP(
I, a, b, c, d,
GET(0), 0xF4292244, 6)
206 STEP(
I, d, a, b, c,
GET(7), 0x432AFF97, 10)
207 STEP(
I, c, d, a, b,
GET(14), 0xAB9423A7, 15)
208 STEP(
I, b, c, d, a,
GET(5), 0xFC93A039, 21)
209 STEP(
I, a, b, c, d,
GET(12), 0x655B59C3, 6)
210 STEP(
I, d, a, b, c,
GET(3), 0x8F0CCC92, 10)
211 STEP(
I, c, d, a, b,
GET(10), 0xFFEFF47D, 15)
212 STEP(
I, b, c, d, a,
GET(1), 0x85845DD1, 21)
213 STEP(
I, a, b, c, d,
GET(8), 0x6FA87E4F, 6)
214 STEP(
I, d, a, b, c,
GET(15), 0xFE2CE6E0, 10)
215 STEP(
I, c, d, a, b,
GET(6), 0xA3014314, 15)
216 STEP(
I, b, c, d, a,
GET(13), 0x4E0811A1, 21)
217 STEP(
I, a, b, c, d,
GET(4), 0xF7537E82, 6)
218 STEP(
I, d, a, b, c,
GET(11), 0xBD3AF235, 10)
219 STEP(
I, c, d, a, b,
GET(2), 0x2AD7D2BB, 15)
220 STEP(
I, b, c, d, a,
GET(9), 0xEB86D391, 21)
228 } while (size -= 64);
240 if ((ctx.lo = (saved_lo + size) & 0x1FFFFFFF) < saved_lo)
242 ctx.hi += size >> 29;
244 size_t used = saved_lo & 0x3F;
247 size_t available = 64 - used;
249 if (size < available) {
250 std::memcpy(&ctx.buffer[used], data, size);
254 std::memcpy(&ctx.buffer[used], data, available);
255 data = data + available;
261 data =
md5Body(ctx, data, size & ~(
size_t)0x3F);
265 std::memcpy(ctx.buffer, data, size);
269 size_t used = ctx.lo & 0x3F;
271 ctx.buffer[used++] = 0x80;
273 size_t available = 64 - used;
276 std::memset(&ctx.buffer[used], 0, available);
282 std::memset(&ctx.buffer[used], 0, available - 8);
285 ctx.buffer[56] = ctx.lo;
286 ctx.buffer[57] = ctx.lo >> 8;
287 ctx.buffer[58] = ctx.lo >> 16;
288 ctx.buffer[59] = ctx.lo >> 24;
289 ctx.buffer[60] = ctx.hi;
290 ctx.buffer[61] = ctx.hi >> 8;
291 ctx.buffer[62] = ctx.hi >> 16;
292 ctx.buffer[63] = ctx.hi >> 24;
297 result[1] = ctx.a >> 8;
298 result[2] = ctx.a >> 16;
299 result[3] = ctx.a >> 24;
301 result[5] = ctx.b >> 8;
302 result[6] = ctx.b >> 16;
303 result[7] = ctx.b >> 24;
305 result[9] = ctx.c >> 8;
306 result[10] = ctx.c >> 16;
307 result[11] = ctx.c >> 24;
309 result[13] = ctx.d >> 8;
310 result[14] = ctx.d >> 16;
311 result[15] = ctx.d >> 24;
316 void hashMD5(ReadStream &stream, std::vector<byte> &digest) {
320 while (!stream.eos()) {
321 size_t bufRead = stream.read(buf, 4096);
330 void hashMD5(
const byte *data,
size_t dataLength, std::vector<byte> &digest) {
339 void hashMD5(
const UString &
string, std::vector<byte> &digest) {
340 hashMD5(reinterpret_cast<const byte *>(
string.c_str()), std::strlen(
string.c_str()), digest);
343 void hashMD5(
const std::vector<byte> &data, std::vector<byte> &digest) {
344 hashMD5(&data[0], data.size(), digest);
348 bool compareMD5Digest(ReadStream &stream,
const std::vector<byte> &digest) {
352 std::vector<byte> newDigest;
355 return std::memcmp(&digest[0], &newDigest[0],
kMD5Length) == 0;
362 std::vector<byte> newDigest;
363 hashMD5(data, dataLength, newDigest);
365 return std::memcmp(&digest[0], &newDigest[0],
kMD5Length) == 0;
368 bool compareMD5Digest(
const UString &
string,
const std::vector<byte> &digest) {
369 return compareMD5Digest(reinterpret_cast<const byte *>(
string.c_str()), std::strlen(
string.c_str()), digest);
372 bool compareMD5Digest(
const std::vector<byte> &data,
const std::vector<byte> &digest) {
void hashMD5(ReadStream &stream, std::vector< byte > &digest)
Hash the stream into an MD5 digest of 16 bytes.
static void md5Update(MD5Context &ctx, const byte *data, size_t size)
static const byte * md5Body(MD5Context &ctx, const byte *data, size_t size)
Basic reading stream interfaces.
bool compareMD5Digest(ReadStream &stream, const std::vector< byte > &digest)
Hash the stream and compare the digests, returning true if they match.
static void md5Final(byte *result, MD5Context &ctx)
Hashing/digesting using the MD5 algorithm.
static const size_t kMD5Length
The length of an MD5 digest in bytes.
#define STEP(f, a, b, c, d, x, t, s)
static uint32 F(const BlowfishContext &ctx, uint32 x)