💾 Archived View for gmi.noulin.net › gitRepositories › hashfunctions › file › md5.c.gmi captured on 2024-08-19 at 05:09:57. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

hashfunctions

Log

Files

Refs

LICENSE

md5.c (7869B)

     1 #include "libsheepyObject.h"
     2 
     3 typ struct {
     4   u32 lo, hi;
     5   u32 a, b, c, d;
     6   unsigned char buffer[64];
     7   u32 block[16];
     8 } MD5_CTX;
     9 
    10 /*
    11  * The basic MD5 functions.
    12  *
    13  * F and G are optimized compared to their RFC 1321 definitions for
    14  * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
    15  * implementation.
    16  */
    17 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
    18 #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
    19 #define H(x, y, z) ((x) ^ (y) ^ (z))
    20 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
    21 
    22 /*
    23  * The MD5 transformation for all four rounds.
    24  */
    25 #define STEP(f, a, b, c, d, x, t, s)                       \
    26   (a) += f((b), (c), (d)) + (x) + (t);                     \
    27   (a) = (((a) << (s)) | (((a)&0xffffffff) >> (32 - (s)))); \
    28   (a) += (b);
    29 
    30 /*
    31  * SET reads 4 input bytes in little-endian byte order and stores them
    32  * in a properly aligned word in host byte order.
    33  *
    34  * The check for little-endian architectures that tolerate unaligned
    35  * memory accesses is just an optimization.  Nothing will break if it
    36  * doesn't work.
    37  */
    38 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
    39 #define SET(n) (*(u32 *)&ptr[(n)*4])
    40 #define GET(n) SET(n)
    41 #else
    42 #define SET(n)                                             \
    43   (ctx->block[(n)] = (u32)ptr[(n)*4] |             \
    44                      ((u32)ptr[(n)*4 + 1] << 8) |  \
    45                      ((u32)ptr[(n)*4 + 2] << 16) | \
    46                      ((u32)ptr[(n)*4 + 3] << 24))
    47 #define GET(n) (ctx->block[(n)])
    48 #endif
    49 
    50 /*
    51  * This processes one or more 64-byte data blocks, but does NOT update
    52  * the bit counters.  There are no alignment requirements.
    53  */
    54 static void *body(MD5_CTX *ctx, void *data, unsigned long size) {
    55   unsigned char *ptr;
    56   u32 a, b, c, d;
    57   u32 saved_a, saved_b, saved_c, saved_d;
    58 
    59   ptr = data;
    60 
    61   a = ctx->a;
    62   b = ctx->b;
    63   c = ctx->c;
    64   d = ctx->d;
    65 
    66   do {
    67     saved_a = a;
    68     saved_b = b;
    69     saved_c = c;
    70     saved_d = d;
    71 
    72     /* Round 1 */
    73     STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
    74     STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
    75     STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
    76     STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
    77     STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
    78     STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
    79     STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
    80     STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
    81     STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
    82     STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
    83     STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
    84     STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
    85     STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
    86     STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
    87     STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
    88     STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
    89 
    90     /* Round 2 */
    91     STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
    92     STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
    93     STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
    94     STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
    95     STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
    96     STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
    97     STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
    98     STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
    99     STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
   100     STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
   101     STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
   102     STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
   103     STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
   104     STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
   105     STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
   106     STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
   107 
   108     /* Round 3 */
   109     STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
   110     STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
   111     STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
   112     STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
   113     STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
   114     STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
   115     STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
   116     STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
   117     STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
   118     STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
   119     STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
   120     STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
   121     STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
   122     STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
   123     STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
   124     STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
   125 
   126     /* Round 4 */
   127     STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
   128     STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
   129     STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
   130     STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
   131     STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
   132     STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
   133     STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
   134     STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
   135     STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
   136     STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
   137     STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
   138     STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
   139     STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
   140     STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
   141     STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
   142     STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
   143 
   144     a += saved_a;
   145     b += saved_b;
   146     c += saved_c;
   147     d += saved_d;
   148 
   149     ptr += 64;
   150   } while (size -= 64);
   151 
   152   ctx->a = a;
   153   ctx->b = b;
   154   ctx->c = c;
   155   ctx->d = d;
   156 
   157   return ptr;
   158 }
   159 
   160 void MD5_Init(MD5_CTX *ctx) {
   161   ctx->a = 0x67452301;
   162   ctx->b = 0xefcdab89;
   163   ctx->c = 0x98badcfe;
   164   ctx->d = 0x10325476;
   165 
   166   ctx->lo = 0;
   167   ctx->hi = 0;
   168 }
   169 
   170 void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size) {
   171   u32 saved_lo;
   172   unsigned long used, free;
   173 
   174   saved_lo = ctx->lo;
   175   if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) {
   176     ctx->hi++;
   177   }
   178   ctx->hi += size >> 29;
   179 
   180   used = saved_lo & 0x3f;
   181 
   182   if (used) {
   183     free = 64 - used;
   184 
   185     if (size < free) {
   186       memcpy(&ctx->buffer[used], data, size);
   187       return;
   188     }
   189 
   190     memcpy(&ctx->buffer[used], data, free);
   191     data = (unsigned char *)data + free;
   192     size -= free;
   193     body(ctx, ctx->buffer, 64);
   194   }
   195 
   196   if (size >= 64) {
   197     data = body(ctx, data, size & ~(unsigned long)0x3f);
   198     size &= 0x3f;
   199   }
   200 
   201   memcpy(ctx->buffer, data, size);
   202 }
   203 
   204 void MD5_Final(unsigned char *result, MD5_CTX *ctx) {
   205   unsigned long used, free;
   206 
   207   used = ctx->lo & 0x3f;
   208 
   209   ctx->buffer[used++] = 0x80;
   210 
   211   free = 64 - used;
   212 
   213   if (free < 8) {
   214     memset(&ctx->buffer[used], 0, free);
   215     body(ctx, ctx->buffer, 64);
   216     used = 0;
   217     free = 64;
   218   }
   219 
   220   memset(&ctx->buffer[used], 0, free - 8);
   221 
   222   ctx->lo <<= 3;
   223   ctx->buffer[56] = ctx->lo;
   224   ctx->buffer[57] = ctx->lo >> 8;
   225   ctx->buffer[58] = ctx->lo >> 16;
   226   ctx->buffer[59] = ctx->lo >> 24;
   227   ctx->buffer[60] = ctx->hi;
   228   ctx->buffer[61] = ctx->hi >> 8;
   229   ctx->buffer[62] = ctx->hi >> 16;
   230   ctx->buffer[63] = ctx->hi >> 24;
   231 
   232   body(ctx, ctx->buffer, 64);
   233 
   234   result[0] = ctx->a;
   235   result[1] = ctx->a >> 8;
   236   result[2] = ctx->a >> 16;
   237   result[3] = ctx->a >> 24;
   238   result[4] = ctx->b;
   239   result[5] = ctx->b >> 8;
   240   result[6] = ctx->b >> 16;
   241   result[7] = ctx->b >> 24;
   242   result[8] = ctx->c;
   243   result[9] = ctx->c >> 8;
   244   result[10] = ctx->c >> 16;
   245   result[11] = ctx->c >> 24;
   246   result[12] = ctx->d;
   247   result[13] = ctx->d >> 8;
   248   result[14] = ctx->d >> 16;
   249   result[15] = ctx->d >> 24;
   250 
   251   memset(ctx, 0, sizeof(*ctx));
   252 }
   253 
   254 /*
   255  * Just a simple method for getting the signature
   256  * result must be == 16
   257  */
   258 void md5_signature(unsigned char *key, unsigned long length,
   259                    unsigned char *result) {
   260   MD5_CTX my_md5;
   261 
   262   MD5_Init(&my_md5);
   263   (void)MD5_Update(&my_md5, key, length);
   264   MD5_Final(result, &my_md5);
   265 }
   266 
   267 u32 hash_md5(const unsigned char *key, size_t key_length) {
   268   unsigned char results[16];
   269 
   270   md5_signature((unsigned char *)key, (unsigned long)key_length, results);
   271 
   272   uint32_t val = ((uint32_t)(results[3] & 0xFF) << 24) |
   273                  ((uint32_t)(results[2] & 0xFF) << 16) |
   274                  ((uint32_t)(results[1] & 0xFF) << 8) | (results[0] & 0xFF);
   275 
   276   return val;
   277 }