Descent3/md5/md5.cpp

404 lines
12 KiB
C++
Raw Normal View History

2024-04-16 03:43:29 +00:00
/*
2024-04-16 18:56:40 +00:00
This is the C++ implementation of the MD5 Message-Digest
Algorithm desrcipted in RFC 1321.
I translated the C code from this RFC to C++.
There is now warranty.
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
Feb. 12. 2005
Benjamin Gr<EFBFBD>delbach
2024-04-16 03:43:29 +00:00
*/
/*
2024-04-16 18:56:40 +00:00
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
2024-04-16 03:43:29 +00:00
*/
2024-04-16 18:56:40 +00:00
// md5 class include
2024-04-16 03:43:29 +00:00
#include "md5.h"
#include <BYTESWAP.H>
#include <string.h>
#include "stdio.h"
static FILE *md5log = NULL;
#define MD5_DEBUG_LOG 0
#ifdef OUTRAGE_BIG_ENDIAN
2024-04-16 18:56:40 +00:00
void byteReverse(unsigned char *buf, unsigned longs) {
uint32_t t;
do {
t = (uint32_t)((unsigned)buf[3] << 8 | buf[2]) << 16 | ((unsigned)buf[1] << 8 | buf[0]);
*(uint32_t *)buf = t;
buf += 4;
} while (--longs);
2024-04-16 03:43:29 +00:00
}
#else
2024-04-16 18:56:40 +00:00
#define byteReverse(buf, len) /* Nothing */
2024-04-16 03:43:29 +00:00
#endif
2024-04-16 18:56:40 +00:00
MD5::~MD5() {
2024-04-16 03:43:29 +00:00
#if MD5_DEBUG_LOG
2024-04-16 18:56:40 +00:00
if (md5log) {
fclose(md5log);
md5log = NULL;
}
2024-04-16 03:43:29 +00:00
#endif
}
/* MD5 initialization. Begins an MD5 operation, writing a new context. */
2024-04-16 18:56:40 +00:00
void MD5::MD5Init() {
MD5_CTX *context = &ctx;
context->buf[0] = 0x67452301;
context->buf[1] = 0xefcdab89;
context->buf[2] = 0x98badcfe;
context->buf[3] = 0x10325476;
context->bits[0] = 0;
context->bits[1] = 0;
2024-04-16 03:43:29 +00:00
#if MD5_DEBUG_LOG
2024-04-16 18:56:40 +00:00
if (!md5log) {
md5log = fopen("md5.log", "wt+");
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
if (md5log) {
fprintf(md5log, "Starting new sum...\n");
2024-04-16 03:43:29 +00:00
}
#endif
}
2024-04-16 18:56:40 +00:00
void MD5::MD5Update(float valin) {
2024-04-16 03:43:29 +00:00
float val = INTEL_FLOAT(valin);
unsigned char *p = (unsigned char *)&val;
#if MD5_DEBUG_LOG
2024-04-16 18:56:40 +00:00
if (md5log) {
fprintf(md5log, "[float]");
2024-04-16 03:43:29 +00:00
}
#endif
2024-04-16 18:56:40 +00:00
MD5Update(p, sizeof(float));
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void MD5::MD5Update(int valin) {
2024-04-16 03:43:29 +00:00
int val = INTEL_INT(valin);
unsigned char *p = (unsigned char *)&val;
#if MD5_DEBUG_LOG
2024-04-16 18:56:40 +00:00
if (md5log) {
fprintf(md5log, "[int]");
2024-04-16 03:43:29 +00:00
}
#endif
2024-04-16 18:56:40 +00:00
MD5Update(p, sizeof(int));
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void MD5::MD5Update(short valin) {
2024-04-16 03:43:29 +00:00
short val = INTEL_SHORT(valin);
unsigned char *p = (unsigned char *)&val;
#if MD5_DEBUG_LOG
2024-04-16 18:56:40 +00:00
if (md5log) {
fprintf(md5log, "[short]");
2024-04-16 03:43:29 +00:00
}
#endif
2024-04-16 18:56:40 +00:00
MD5Update(p, sizeof(short));
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void MD5::MD5Update(unsigned int valin) {
2024-04-16 03:43:29 +00:00
unsigned int val = INTEL_INT(valin);
unsigned char *p = (unsigned char *)&val;
#if MD5_DEBUG_LOG
2024-04-16 18:56:40 +00:00
if (md5log) {
fprintf(md5log, "[u_int]");
2024-04-16 03:43:29 +00:00
}
#endif
2024-04-16 18:56:40 +00:00
MD5Update(p, sizeof(unsigned int));
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void MD5::MD5Update(unsigned char val) {
2024-04-16 03:43:29 +00:00
unsigned char *p = (unsigned char *)&val;
#if MD5_DEBUG_LOG
2024-04-16 18:56:40 +00:00
if (md5log) {
fprintf(md5log, "[u_char]");
2024-04-16 03:43:29 +00:00
}
#endif
2024-04-16 18:56:40 +00:00
MD5Update(p, sizeof(unsigned char));
2024-04-16 03:43:29 +00:00
}
/*
2024-04-16 18:56:40 +00:00
MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
2024-04-16 03:43:29 +00:00
*/
2024-04-16 18:56:40 +00:00
void MD5::MD5Update(unsigned char *buf, unsigned int len) {
2024-04-16 03:43:29 +00:00
MD5_CTX *context = &ctx;
#if MD5_DEBUG_LOG
2024-04-16 18:56:40 +00:00
if (md5log) {
fprintf(md5log, "(%d) ", len);
for (unsigned int a = 0; a < len; a++) {
fprintf(md5log, "%x ", buf[a] & 0xff);
}
fprintf(md5log, "\n");
2024-04-16 03:43:29 +00:00
}
#endif
2024-04-16 18:56:40 +00:00
uint32_t t;
/* Update bitcount */
t = context->bits[0];
if ((context->bits[0] = t + ((uint32_t)len << 3)) < t)
context->bits[1]++; /* Carry from low to high */
context->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
unsigned char *p = (unsigned char *)context->in + t;
t = 64 - t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byteReverse(context->in, 16);
MD5Transform(context->buf, (uint32_t *)context->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(context->in, buf, 64);
byteReverse(context->in, 16);
MD5Transform(context->buf, (uint32_t *)context->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(context->in, buf, len);
2024-04-16 03:43:29 +00:00
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
2024-04-16 18:56:40 +00:00
void MD5::MD5Final(unsigned char digest[16]) {
MD5_CTX *context = &ctx;
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (context->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = context->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(context->in, 16);
MD5Transform(context->buf, (uint32_t *)context->in);
/* Now fill the next block with 56 bytes */
memset(context->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
byteReverse(context->in, 14);
/* Append length in bits and transform */
((uint32_t *)context->in)[14] = context->bits[0];
((uint32_t *)context->in)[15] = context->bits[1];
MD5Transform(context->buf, (uint32_t *)context->in);
byteReverse((unsigned char *)context->buf, 4);
memcpy(digest, context->buf, 16);
memset(context, 0, sizeof(*context)); /* In case it's sensitive */
/* The original version of this code omitted the asterisk. In
effect, only the first part of context was wiped
* with zeros, not
the whole thing. Bug found by Derek Jones. Original line: */
// memset(context, 0, sizeof(context)); /* In case it's sensitive */
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
2024-04-16 03:43:29 +00:00
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
2024-04-16 18:56:40 +00:00
* reflect the addition of 16 longwords of new
* data. MD5Update blocks
2024-04-16 03:43:29 +00:00
* the data and converts bytes into longwords for this routine.
2024-04-16 18:56:40 +00:00
*/
void MD5::MD5Transform(uint32_t buf[4], uint32_t const in[16]) {
register uint32_t a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
2024-04-16 03:43:29 +00:00
}
/* Encodes input (unsigned long int) into output (unsigned char). Assumes len is
a multiple of 4.
*/
2024-04-16 18:56:40 +00:00
void MD5::Encode(unsigned char *output, unsigned int *input, unsigned int len) {
2024-04-16 03:43:29 +00:00
unsigned int i, j;
2024-04-16 18:56:40 +00:00
for (i = 0, j = 0; j < len; i++, j += 4) {
unsigned int inp = INTEL_INT(input[i]);
output[j] = (unsigned char)(inp & 0xff);
output[j + 1] = (unsigned char)((inp >> 8) & 0xff);
output[j + 2] = (unsigned char)((inp >> 16) & 0xff);
output[j + 3] = (unsigned char)((inp >> 24) & 0xff);
}
2024-04-16 03:43:29 +00:00
}
/* Decodes input (unsigned char) into output (unsigned long int). Assumes len is
a multiple of 4.
*/
2024-04-16 18:56:40 +00:00
void MD5::Decode(unsigned int *output, unsigned char *input, unsigned int len) {
2024-04-16 03:43:29 +00:00
unsigned int i, j;
2024-04-16 18:56:40 +00:00
for (i = 0, j = 0; j < len; i++, j += 4) {
unsigned int inp0 = INTEL_INT(input[j]);
unsigned int inp1 = INTEL_INT(input[j + 1]);
unsigned int inp2 = INTEL_INT(input[j + 2]);
unsigned int inp3 = INTEL_INT(input[j + 3]);
output[i] = ((unsigned int)inp0) | (((unsigned int)inp1) << 8) | (((unsigned int)inp2) << 16) |
(((unsigned int)inp3) << 24);
}
2024-04-16 03:43:29 +00:00
}
/* Note: Replace "for loop" with standard memcpy if possible.
*/
2024-04-16 18:56:40 +00:00
void MD5::MD5_memcpy(POINTER output, POINTER input, unsigned int len) {
unsigned int i;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
for (i = 0; i < len; i++)
output[i] = input[i];
2024-04-16 03:43:29 +00:00
}
/* Note: Replace "for loop" with standard memset if possible.
*/
2024-04-16 18:56:40 +00:00
void MD5::MD5_memset(POINTER output, int value, unsigned int len) {
unsigned int i;
for (i = 0; i < len; i++) {
((char *)output)[i] = (char)value;
}
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
MD5 *MD5::Clone() {
MD5 *clone = new MD5();
clone->ctx = this->ctx;
return clone;
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
void MD5::Destroy(MD5 *obj) {
if (obj)
delete obj;
2024-04-16 03:43:29 +00:00
}