Advertisement
and_cesbo

md5_crypt

Apr 12th, 2024
612
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.78 KB | Cybersecurity | 0 0
  1. #include <openssl/md5.h>
  2.  
  3. static void md5_to64(char *s, uint64_t v, int n)
  4. {
  5.     static const char md5_itoa64[] = /* 0 ... 63 => ascii - 64 */
  6.         "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  7.     while(--n >= 0)
  8.     {
  9.         *s++ = md5_itoa64[v & 0x3f];
  10.         v >>= 6;
  11.     }
  12. }
  13.  
  14.  
  15. // From FreeBSD
  16. void md5_crypt(const char *pw, const char *salt, char passwd[36])
  17. {
  18.     const char *ep;
  19.     const char *sp = salt;
  20.  
  21.     // If it starts with the magic string, then skip that
  22.     static const char *md5_magic = "$1$";
  23.     const size_t md5_magic_len = 3;
  24.     if(!strncmp(sp, md5_magic, md5_magic_len))
  25.         sp += md5_magic_len;
  26.  
  27.     for(ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++)
  28.         continue;
  29.  
  30.     // get the length of the true salt
  31.     const int sl = (int)(ep - sp);
  32.  
  33.     MD5_CTX ctx;
  34.     MD5_Init(&ctx);
  35.  
  36.     // The password first, since that is what is most unknown
  37.     const size_t pw_len = strlen(pw);
  38.     MD5_Update(&ctx, pw, pw_len);
  39.     // Then our magic string
  40.     MD5_Update(&ctx, md5_magic, md5_magic_len);
  41.     // Then the raw salt
  42.     MD5_Update(&ctx, sp, sl);
  43.     // Then just as many characters of the MD5(pw,salt,pw)
  44.     MD5_CTX ctx1;
  45.     MD5_Init(&ctx1);
  46.     MD5_Update(&ctx1, pw, pw_len);
  47.     MD5_Update(&ctx1, sp, sl);
  48.     MD5_Update(&ctx1, pw, pw_len);
  49.     uint8_t final[17];
  50.     MD5_Final(final, &ctx1);
  51.     OPENSSL_cleanse(&ctx1, sizeof(ctx1));
  52.     for(int i = (int)pw_len; i > 0; i -= 16)
  53.         MD5_Update(&ctx, (const uint8_t *)final, (i > 16) ? 16 : i);
  54.  
  55.     memset(final, 0, sizeof(final));
  56.     for(int i = (int)pw_len; i; i >>= 1)
  57.     {
  58.         const uint8_t *d = (i & 1) ? final : (uint8_t *)pw;
  59.         MD5_Update(&ctx, d, 1);
  60.     }
  61.  
  62.     // Now make the output string
  63.     strcpy(passwd, md5_magic);
  64.     strncat(passwd, sp, sl);
  65.     strcat(passwd, "$");
  66.  
  67.     MD5_Final(final, &ctx);
  68.     OPENSSL_cleanse(&ctx, sizeof(ctx));
  69.  
  70.     for(int i = 0; i < 1000; i++)
  71.     {
  72.         MD5_Init(&ctx1);
  73.  
  74.         if(i & 1)
  75.             MD5_Update(&ctx1, pw, pw_len);
  76.         else
  77.             MD5_Update(&ctx1, final, 16);
  78.  
  79.         if(i % 3)
  80.             MD5_Update(&ctx1, sp, sl);
  81.  
  82.         if(i % 7)
  83.             MD5_Update(&ctx1, pw, pw_len);
  84.  
  85.         if(i & 1)
  86.             MD5_Update(&ctx1, final, 16);
  87.         else
  88.             MD5_Update(&ctx1, pw, pw_len);
  89.  
  90.         MD5_Final(final, &ctx1);
  91.         OPENSSL_cleanse(&ctx1, sizeof(ctx1));
  92.     }
  93.  
  94.     uint64_t l;
  95.     char *p = passwd + strlen(passwd);
  96.     final[16] = final[5];
  97.     for(int i = 0; i < 5; i++)
  98.     {
  99.         l = (final[i] << 16) | (final[i + 6] << 8) | final[i + 12];
  100.         md5_to64(p, l, 4); p += 4;
  101.     }
  102.     l = final[11];
  103.     md5_to64(p, l, 2); p += 2;
  104.     *p = '\0';
  105.  
  106.     memset(final, 0, sizeof(final));
  107. } /* md5_crypt */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement