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); +} | 
