summaryrefslogtreecommitdiff
path: root/src/lib/libc/crypt/md5crypt.c
diff options
context:
space:
mode:
authorderaadt <>1996-05-30 02:36:33 +0000
committerderaadt <>1996-05-30 02:36:33 +0000
commit355e931842bac2aed7596a45c184045fe5c2a5eb (patch)
tree281f889bbdfce2af1c23a1454af8200df9ac6121 /src/lib/libc/crypt/md5crypt.c
parentb08ebc2003288b99b5bff2ea3afc425782eb3c08 (diff)
downloadopenbsd-355e931842bac2aed7596a45c184045fe5c2a5eb.tar.gz
openbsd-355e931842bac2aed7596a45c184045fe5c2a5eb.tar.bz2
openbsd-355e931842bac2aed7596a45c184045fe5c2a5eb.zip
add md5crypt()
Diffstat (limited to 'src/lib/libc/crypt/md5crypt.c')
-rw-r--r--src/lib/libc/crypt/md5crypt.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/lib/libc/crypt/md5crypt.c b/src/lib/libc/crypt/md5crypt.c
new file mode 100644
index 0000000000..7872c36859
--- /dev/null
+++ b/src/lib/libc/crypt/md5crypt.c
@@ -0,0 +1,151 @@
1/* $OpenBSD: md5crypt.c,v 1.1 1996/05/30 02:36:33 deraadt Exp $ */
2
3/*
4 * ----------------------------------------------------------------------------
5 * "THE BEER-WARE LICENSE" (Revision 42):
6 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
7 * can do whatever you want with this stuff. If we meet some day, and you think
8 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
9 * ----------------------------------------------------------------------------
10 *
11 */
12
13#if defined(LIBC_SCCS) && !defined(lint)
14static char rcsid[] = "$OpenBSD: md5crypt.c,v 1.1 1996/05/30 02:36:33 deraadt Exp $";
15#endif /* LIBC_SCCS and not lint */
16
17#include <unistd.h>
18#include <stdio.h>
19#include "md5.h"
20
21static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
22 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
23
24static void
25to64(s, v, n)
26 char *s;
27 unsigned long v;
28 int n;
29{
30 while (--n >= 0) {
31 *s++ = itoa64[v&0x3f];
32 v >>= 6;
33 }
34}
35
36/*
37 * UNIX password
38 *
39 * Use MD5 for what it is best at...
40 */
41
42char *
43md5crypt(pw, salt)
44 register const char *pw;
45 register const char *salt;
46{
47 static char *magic = "$1$"; /*
48 * This string is magic for
49 * this algorithm. Having
50 * it this way, we can get
51 * get better later on
52 */
53 static char passwd[120], *p;
54 static const char *sp,*ep;
55 unsigned char final[16];
56 int sl,pl,i,j;
57 MD5_CTX ctx,ctx1;
58 unsigned long l;
59
60 /* Refine the Salt first */
61 sp = salt;
62
63 /* If it starts with the magic string, then skip that */
64 if(!strncmp(sp,magic,strlen(magic)))
65 sp += strlen(magic);
66
67 /* It stops at the first '$', max 8 chars */
68 for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
69 continue;
70
71 /* get the length of the true salt */
72 sl = ep - sp;
73
74 MD5Init(&ctx);
75
76 /* The password first, since that is what is most unknown */
77 MD5Update(&ctx,pw,strlen(pw));
78
79 /* Then our magic string */
80 MD5Update(&ctx,magic,strlen(magic));
81
82 /* Then the raw salt */
83 MD5Update(&ctx,sp,sl);
84
85 /* Then just as many characters of the MD5(pw,salt,pw) */
86 MD5Init(&ctx1);
87 MD5Update(&ctx1,pw,strlen(pw));
88 MD5Update(&ctx1,sp,sl);
89 MD5Update(&ctx1,pw,strlen(pw));
90 MD5Final(final,&ctx1);
91 for(pl = strlen(pw); pl > 0; pl -= 16)
92 MD5Update(&ctx,final,pl>16 ? 16 : pl);
93
94 /* Don't leave anything around in vm they could use. */
95 memset(final,0,sizeof final);
96
97 /* Then something really weird... */
98 for (j=0,i = strlen(pw); i ; i >>= 1)
99 if(i&1)
100 MD5Update(&ctx, final+j, 1);
101 else
102 MD5Update(&ctx, pw+j, 1);
103
104 /* Now make the output string */
105 strcpy(passwd,magic);
106 strncat(passwd,sp,sl);
107 strcat(passwd,"$");
108
109 MD5Final(final,&ctx);
110
111 /*
112 * and now, just to make sure things don't run too fast
113 * On a 60 Mhz Pentium this takes 34 msec, so you would
114 * need 30 seconds to build a 1000 entry dictionary...
115 */
116 for(i=0;i<1000;i++) {
117 MD5Init(&ctx1);
118 if(i & 1)
119 MD5Update(&ctx1,pw,strlen(pw));
120 else
121 MD5Update(&ctx1,final,16);
122
123 if(i % 3)
124 MD5Update(&ctx1,sp,sl);
125
126 if(i % 7)
127 MD5Update(&ctx1,pw,strlen(pw));
128
129 if(i & 1)
130 MD5Update(&ctx1,final,16);
131 else
132 MD5Update(&ctx1,pw,strlen(pw));
133 MD5Final(final,&ctx1);
134 }
135
136 p = passwd + strlen(passwd);
137
138 l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
139 l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
140 l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
141 l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
142 l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
143 l = final[11] ; to64(p,l,2); p += 2;
144 *p = '\0';
145
146 /* Don't leave anything around in vm they could use. */
147 memset(final,0,sizeof final);
148
149 return passwd;
150}
151