and_cesbo icon

md5_crypt

and_cesbo | PRO | 04/12/24 06:20:38 AM UTC | 0 ⭐ | 14242 👁️ | Never ⏰ | []
C |

2.78 KB

|

Cybersecurity

|

0 👍

/

0 👎

#include <openssl/md5.h>
 
static void md5_to64(char *s, uint64_t v, int n)
{
    static const char md5_itoa64[] = /* 0 ... 63 => ascii - 64 */
        "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    while(--n >= 0)
    {
        *s++ = md5_itoa64[v & 0x3f];
        v >>= 6;
    }
}
 
 
// From FreeBSD
void md5_crypt(const char *pw, const char *salt, char passwd[36])
{
    const char *ep;
    const char *sp = salt;
 
    // If it starts with the magic string, then skip that
    static const char *md5_magic = "$1$";
    const size_t md5_magic_len = 3;
    if(!strncmp(sp, md5_magic, md5_magic_len))
        sp += md5_magic_len;
 
    for(ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++)
        continue;
 
    // get the length of the true salt
    const int sl = (int)(ep - sp);
 
    MD5_CTX ctx;
    MD5_Init(&ctx);
 
    // The password first, since that is what is most unknown
    const size_t pw_len = strlen(pw);
    MD5_Update(&ctx, pw, pw_len);
    // Then our magic string
    MD5_Update(&ctx, md5_magic, md5_magic_len);
    // Then the raw salt
    MD5_Update(&ctx, sp, sl);
    // Then just as many characters of the MD5(pw,salt,pw)
    MD5_CTX ctx1;
    MD5_Init(&ctx1);
    MD5_Update(&ctx1, pw, pw_len);
    MD5_Update(&ctx1, sp, sl);
    MD5_Update(&ctx1, pw, pw_len);
    uint8_t final[17];
    MD5_Final(final, &ctx1);
    OPENSSL_cleanse(&ctx1, sizeof(ctx1));
    for(int i = (int)pw_len; i > 0; i -= 16)
        MD5_Update(&ctx, (const uint8_t *)final, (i > 16) ? 16 : i);
 
    memset(final, 0, sizeof(final));
    for(int i = (int)pw_len; i; i >>= 1)
    {
        const uint8_t *d = (i & 1) ? final : (uint8_t *)pw;
        MD5_Update(&ctx, d, 1);
    }
 
    // Now make the output string
    strcpy(passwd, md5_magic);
    strncat(passwd, sp, sl);
    strcat(passwd, "$");
 
    MD5_Final(final, &ctx);
    OPENSSL_cleanse(&ctx, sizeof(ctx));
 
    for(int i = 0; i < 1000; i++)
    {
        MD5_Init(&ctx1);
 
        if(i & 1)
            MD5_Update(&ctx1, pw, pw_len);
        else
            MD5_Update(&ctx1, final, 16);
 
        if(i % 3)
            MD5_Update(&ctx1, sp, sl);
 
        if(i % 7)
            MD5_Update(&ctx1, pw, pw_len);
 
        if(i & 1)
            MD5_Update(&ctx1, final, 16);
        else
            MD5_Update(&ctx1, pw, pw_len);
 
        MD5_Final(final, &ctx1);
        OPENSSL_cleanse(&ctx1, sizeof(ctx1));
    }
 
    uint64_t l;
    char *p = passwd + strlen(passwd);
    final[16] = final[5];
    for(int i = 0; i < 5; i++)
    {
        l = (final[i] << 16) | (final[i + 6] << 8) | final[i + 12];
        md5_to64(p, l, 4); p += 4;
    }
    l = final[11];
    md5_to64(p, l, 2); p += 2;
    *p = '\0';
 
    memset(final, 0, sizeof(final));
} /* md5_crypt */

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎