diff options
Diffstat (limited to 'md5/redhat-crypt-md5.c')
| -rw-r--r-- | md5/redhat-crypt-md5.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/md5/redhat-crypt-md5.c b/md5/redhat-crypt-md5.c new file mode 100644 index 0000000..a8a37fd --- /dev/null +++ b/md5/redhat-crypt-md5.c @@ -0,0 +1,125 @@ +/* +** Copyright 1998 - 1999 Double Precision, Inc. +** See COPYING for distribution information. +*/ + +#define MD5_INTERNAL +#include "md5.h" +#include <string.h> + + +static char base64[]= + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +char *md5_crypt_redhat(const char *pw, const char *salt) +{ +struct MD5_CONTEXT outer_context, inner_context; +MD5_DIGEST digest; +unsigned pwl=strlen(pw); +unsigned l; +unsigned i, j; +char *p; +static char buffer[100]; + + if (*salt == '$' && salt[1] == '1' && salt[2] == '$') + salt += 3; + + for (l=0; l<8 && salt[l] && salt[l] != '$'; l++) + ; + + md5_context_init(&inner_context); + md5_context_hashstream(&inner_context, pw, pwl); + md5_context_hashstream(&inner_context, salt, l); + md5_context_hashstream(&inner_context, pw, pwl); + md5_context_endstream(&inner_context, pwl*2+l); + md5_context_digest(&inner_context, digest); + + md5_context_init(&outer_context); + md5_context_hashstream(&outer_context, pw, pwl); + md5_context_hashstream(&outer_context, "$1$", 3); + md5_context_hashstream(&outer_context, salt, l); + + for (i=pwl; i; ) + { + j=i; + if (j > 16) j=16; + md5_context_hashstream(&outer_context, digest, j); + i -= j; + } + + j=pwl*2+l+3; + + for (i=pwl; i; i >>= 1) + { + md5_context_hashstream(&outer_context, (i & 1) ? "": pw, 1); + ++j; + } + + + md5_context_endstream(&outer_context, j); + md5_context_digest(&outer_context, digest); + + for (i=0; i<1000; i++) + { + j=0; + + md5_context_init(&outer_context); + if (i & 1) + { + md5_context_hashstream(&outer_context, pw, pwl); + j += pwl; + } + else + { + md5_context_hashstream(&outer_context, digest, 16); + j += 16; + } + + if (i % 3) + { + md5_context_hashstream(&outer_context, salt, l); + j += l; + } + + if (i % 7) + { + md5_context_hashstream(&outer_context, pw, pwl); + j += pwl; + } + + if (i & 1) + { + md5_context_hashstream(&outer_context, digest, 16); + j += 16; + } + else + { + md5_context_hashstream(&outer_context, pw, pwl); + j += pwl; + } + + md5_context_endstream(&outer_context, j); + md5_context_digest(&outer_context, digest); + } + + strcpy(buffer, "$1$"); + strncat(buffer, salt, l); + strcat(buffer, "$"); + + p=buffer+strlen(buffer); + for (i=0; i<5; i++) + { + unsigned char *d=digest; + + j= (d[i] << 16) | (d[i+6] << 8) | d[i == 4 ? 5:12+i]; + *p++= base64[j & 63] ; j=j >> 6; + *p++= base64[j & 63] ; j=j >> 6; + *p++= base64[j & 63] ; j=j >> 6; + *p++= base64[j & 63]; + } + j=digest[11]; + *p++ = base64[j & 63]; j=j >> 6; + *p++ = base64[j & 63]; + *p=0; + return (buffer); +} |
