💾 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
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
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 }