Crypt - modified not to use crypt(3)
philip at axis.UUCP
philip at axis.UUCP
Sat Feb 21 09:04:27 AEST 1987
Since posting the original article, it has become apparent that many
UNIX systems (and DOS) lack the makekey program, and sometimes even
the crypt(3) functions.
This is not actually too important - I only used makekey/crypt because
it was there.
The crypt(3) function is complicated - based upon the DES algorithms.
It is used normally on UNIX to generate the encrypted passwords which
are stored in the password file. Since these are publicly available,
a good encryption routine is needed to stop people deriving the password
from its crypted form. In my crypt program, the result of this routine
is used simply to seed a pseudo-random number generator.
The 'string' used to do this is never stored anywhere outside the program,
thus it is not too important if it is possible to derive the input key
from this initialisation string. What this means is that you can replace
crypt(3) with just about anything. You can even use the password that the user
gives directly, although I would suggest using some method of generating
something a little longer to use as the intialisation string - like
replicating the users key (for example). Doing this should not do too much
damage to the security of the system (but then I am no expert in these
matters ...)
The following is a hacked version of the original, without any calls
to makekey or crypt(3) - it should be suitable for UNIX systems with
no encryption available, and even for DOS - if you can write your
own version of getpass(3). This version simply replicates the input key
until it is 13 characters long, and uses that to seed the random number
generator.
If it is important that data encrypted on one machine should be decryptable
on another, this is probably the version to use, since some vendors seem
to have replaced the DES based crypt(3) with their own version, and thus
systems using that will not be compatible.
Philip
=============================================================================
#include <stdio.h>
#define ROTORSIZ 256
#define MASK 0377
#define EMPTY 07777
#define X_SIZE 4099
char *strrchr();
unsigned r1[ROTORSIZ];
unsigned r2[ROTORSIZ];
unsigned r3[ROTORSIZ];
unsigned char x[X_SIZE];
init(password, decrypt)
char *password;
int decrypt;
{
register int index;
register int i;
unsigned random;
long seed = 123L;
char buf[14];
strncpy(buf, password, 13);
while (strlen(buf) < 13) strncat(buf, password, 13 - strlen(buf));
for (i = 0 ; i < ROTORSIZ; i++) r1[i] = r2[i] = r3[i] = EMPTY;
for (i = 0; i < 13; i++) seed = seed * buf[i] + i;
i = 0;
while (i < ROTORSIZ)
{
seed = (long)(5L * seed + (long)i);
random = (unsigned)(seed % 65521L);
index = (int)(random & MASK);
if (r1[index] == EMPTY)
r1[index] = i++;
else
continue;
}
i = 0;
while (i < ROTORSIZ)
{
seed = (long)(5L * seed + (long)i);
random = (unsigned)(seed % 65521L);
index = (int)(random & MASK);
if (r2[index] == EMPTY)
r2[index] = i++;
else
continue;
}
i = 0;
while (i < ROTORSIZ)
{
seed = (long)(5L * seed + (long)i);
random = (unsigned)(seed % 65521L);
index = (int)(random & MASK);
if (r3[index] == EMPTY)
r3[index] = i++;
else
continue;
}
for (i = 0; i < X_SIZE; i++)
{
seed = (long)(5L * seed + (long)i);
random = (unsigned)(seed % 65521L);
x[i] = random & 03;
}
if (decrypt)
{
invert(r1);
invert(r2);
invert(r3);
}
}
invert(r)
unsigned r[ROTORSIZ];
{
unsigned t[ROTORSIZ];
register int i;
for (i = 0; i < ROTORSIZ; i++) t[i] = r[i];
for (i = 0; i < ROTORSIZ; i++) r[t[i]] = i;
}
crypt()
{
register int ch;
register int i = 0;
register unsigned ofs1 = 0;
register unsigned ofs2 = 0;
register unsigned ofs3 = 0;
while ((ch = getchar()) != EOF)
{
putchar(r3[r2[r1[ch+ofs1&MASK]+ofs2&MASK]+ofs3&MASK]);
switch (x[i]){
case 00:
ofs1 = ++ofs1 & MASK;
break;
case 01:
ofs2 = ++ofs2 & MASK;
break;
case 02:
ofs3 = ++ofs3 & MASK;
break;
}
if (ofs1 == 0) ofs2 = ++ofs2 & MASK;
if (ofs2 == 0) ofs3 = ++ofs3 & MASK;
if (++i == X_SIZE) i = 0;
}
}
decrypt()
{
register int ch;
register int i = 0;
register unsigned ofs1 = 0;
register unsigned ofs2 = 0;
register unsigned ofs3 = 0;
while ((ch = getchar()) != EOF)
{
putchar(r1[r2[r3[ch]-ofs3&MASK]-ofs2&MASK]-ofs1&MASK);
switch (x[i]){
case 00:
ofs1 = ++ofs1 & MASK;
break;
case 01:
ofs2 = ++ofs2 & MASK;
break;
case 02:
ofs3 = ++ofs3 & MASK;
break;
}
if (ofs1 == 0) ofs2 = ++ofs2 & MASK;
if (ofs2 == 0) ofs3 = ++ofs3 & MASK;
if (++i == X_SIZE) i = 0;
}
}
main(argc, argv)
int argc;
char *argv[];
{
int flag;
char *p;
p = strrchr(argv[0], '/');
if (p == NULL) p = argv[0];
else ++p;
if (strcmp(p, "crypt") == 0) flag = 0;
else flag = 1;
if (argc != 2)
init(getpass("Enter key: "), flag);
else
init(argv[1], flag);
if (flag) decrypt();
else crypt();
}
More information about the Comp.sources.unix
mailing list