2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
21 static const char _crypt_a64
[] =
22 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
25 _crypt_to64(char *s
, unsigned long v
, int n
)
29 *s
++ = _crypt_a64
[v
& 0x3f];
39 px_crypt_md5(const char *pw
, const char *salt
, char *passwd
, unsigned dstlen
)
41 static char *magic
= "$1$"; /* This string is magic for this algorithm.
42 * Having it this way, we can get get better
45 static const char *sp
,
47 unsigned char final
[MD5_SIZE
];
56 if (!passwd
|| dstlen
< 120)
59 /* Refine the Salt first */
62 /* If it starts with the magic string, then skip that */
63 if (!strncmp(sp
, magic
, strlen(magic
)))
66 /* It stops at the first '$', max 8 chars */
67 for (ep
= sp
; *ep
&& *ep
!= '$' && ep
< (sp
+ 8); ep
++)
70 /* get the length of the true salt */
74 err
= px_find_digest("md5", &ctx
);
77 err
= px_find_digest("md5", &ctx1
);
79 /* The password first, since that is what is most unknown */
80 px_md_update(ctx
, (uint8
*) pw
, strlen(pw
));
82 /* Then our magic string */
83 px_md_update(ctx
, (uint8
*) magic
, strlen(magic
));
85 /* Then the raw salt */
86 px_md_update(ctx
, (uint8
*) sp
, sl
);
88 /* Then just as many characters of the MD5(pw,salt,pw) */
89 px_md_update(ctx1
, (uint8
*) pw
, strlen(pw
));
90 px_md_update(ctx1
, (uint8
*) sp
, sl
);
91 px_md_update(ctx1
, (uint8
*) pw
, strlen(pw
));
92 px_md_finish(ctx1
, final
);
93 for (pl
= strlen(pw
); pl
> 0; pl
-= MD5_SIZE
)
94 px_md_update(ctx
, final
, pl
> MD5_SIZE
? MD5_SIZE
: pl
);
96 /* Don't leave anything around in vm they could use. */
97 memset(final
, 0, sizeof final
);
99 /* Then something really weird... */
100 for (i
= strlen(pw
); i
; i
>>= 1)
102 px_md_update(ctx
, final
, 1);
104 px_md_update(ctx
, (uint8
*) pw
, 1);
106 /* Now make the output string */
107 strcpy(passwd
, magic
);
108 strncat(passwd
, sp
, sl
);
111 px_md_finish(ctx
, final
);
114 * and now, just to make sure things don't run too fast On a 60 Mhz
115 * Pentium this takes 34 msec, so you would need 30 seconds to build a
116 * 1000 entry dictionary...
118 for (i
= 0; i
< 1000; i
++)
122 px_md_update(ctx1
, (uint8
*) pw
, strlen(pw
));
124 px_md_update(ctx1
, final
, MD5_SIZE
);
127 px_md_update(ctx1
, (uint8
*) sp
, sl
);
130 px_md_update(ctx1
, (uint8
*) pw
, strlen(pw
));
133 px_md_update(ctx1
, final
, MD5_SIZE
);
135 px_md_update(ctx1
, (uint8
*) pw
, strlen(pw
));
136 px_md_finish(ctx1
, final
);
139 p
= passwd
+ strlen(passwd
);
141 l
= (final
[0] << 16) | (final
[6] << 8) | final
[12];
142 _crypt_to64(p
, l
, 4);
144 l
= (final
[1] << 16) | (final
[7] << 8) | final
[13];
145 _crypt_to64(p
, l
, 4);
147 l
= (final
[2] << 16) | (final
[8] << 8) | final
[14];
148 _crypt_to64(p
, l
, 4);
150 l
= (final
[3] << 16) | (final
[9] << 8) | final
[15];
151 _crypt_to64(p
, l
, 4);
153 l
= (final
[4] << 16) | (final
[10] << 8) | final
[5];
154 _crypt_to64(p
, l
, 4);
157 _crypt_to64(p
, l
, 2);
161 /* Don't leave anything around in vm they could use. */
162 memset(final
, 0, sizeof final
);