Imported upstream version 0.59.3
[hcoop/debian/courier-authlib.git] / md5 / redhat-crypt-md5.c
1 /*
2 ** Copyright 1998 - 1999 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5
6 #define MD5_INTERNAL
7 #include "md5.h"
8 #include <string.h>
9
10 static const char rcsid[]="$Id: redhat-crypt-md5.c,v 1.3 1999/12/06 13:22:43 mrsam Exp $";
11
12 static char base64[]=
13 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
14
15 char *md5_crypt_redhat(const char *pw, const char *salt)
16 {
17 struct MD5_CONTEXT outer_context, inner_context;
18 MD5_DIGEST digest;
19 unsigned pwl=strlen(pw);
20 unsigned l;
21 unsigned i, j;
22 char *p;
23 static char buffer[100];
24
25 if (*salt == '$' && salt[1] == '1' && salt[2] == '$')
26 salt += 3;
27
28 for (l=0; l<8 && salt[l] && salt[l] != '$'; l++)
29 ;
30
31 md5_context_init(&inner_context);
32 md5_context_hashstream(&inner_context, pw, pwl);
33 md5_context_hashstream(&inner_context, salt, l);
34 md5_context_hashstream(&inner_context, pw, pwl);
35 md5_context_endstream(&inner_context, pwl*2+l);
36 md5_context_digest(&inner_context, digest);
37
38 md5_context_init(&outer_context);
39 md5_context_hashstream(&outer_context, pw, pwl);
40 md5_context_hashstream(&outer_context, "$1$", 3);
41 md5_context_hashstream(&outer_context, salt, l);
42
43 for (i=pwl; i; )
44 {
45 j=i;
46 if (j > 16) j=16;
47 md5_context_hashstream(&outer_context, digest, j);
48 i -= j;
49 }
50
51 j=pwl*2+l+3;
52
53 for (i=pwl; i; i >>= 1)
54 {
55 md5_context_hashstream(&outer_context, (i & 1) ? "": pw, 1);
56 ++j;
57 }
58
59
60 md5_context_endstream(&outer_context, j);
61 md5_context_digest(&outer_context, digest);
62
63 for (i=0; i<1000; i++)
64 {
65 j=0;
66
67 md5_context_init(&outer_context);
68 if (i & 1)
69 {
70 md5_context_hashstream(&outer_context, pw, pwl);
71 j += pwl;
72 }
73 else
74 {
75 md5_context_hashstream(&outer_context, digest, 16);
76 j += 16;
77 }
78
79 if (i % 3)
80 {
81 md5_context_hashstream(&outer_context, salt, l);
82 j += l;
83 }
84
85 if (i % 7)
86 {
87 md5_context_hashstream(&outer_context, pw, pwl);
88 j += pwl;
89 }
90
91 if (i & 1)
92 {
93 md5_context_hashstream(&outer_context, digest, 16);
94 j += 16;
95 }
96 else
97 {
98 md5_context_hashstream(&outer_context, pw, pwl);
99 j += pwl;
100 }
101
102 md5_context_endstream(&outer_context, j);
103 md5_context_digest(&outer_context, digest);
104 }
105
106 strcpy(buffer, "$1$");
107 strncat(buffer, salt, l);
108 strcat(buffer, "$");
109
110 p=buffer+strlen(buffer);
111 for (i=0; i<5; i++)
112 {
113 unsigned char *d=digest;
114
115 j= (d[i] << 16) | (d[i+6] << 8) | d[i == 4 ? 5:12+i];
116 *p++= base64[j & 63] ; j=j >> 6;
117 *p++= base64[j & 63] ; j=j >> 6;
118 *p++= base64[j & 63] ; j=j >> 6;
119 *p++= base64[j & 63];
120 }
121 j=digest[11];
122 *p++ = base64[j & 63]; j=j >> 6;
123 *p++ = base64[j & 63];
124 *p=0;
125 return (buffer);
126 }