hashfunctions

generic hash functions and PRFs: Jenkins, FNV, siphash
git clone https://noulin.net/git/hashfunctions.git
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 }