enigma.c revision 40767
1/*
2 *	"enigma.c" is in file cbw.tar from
3 *	anonymous FTP host watmsg.waterloo.edu: pub/crypt/cbw.tar.Z
4 *
5 *	A one-rotor machine designed along the lines of Enigma
6 *	but considerably trivialized.
7 *
8 *	A public-domain replacement for the UNIX "crypt" command.
9 *
10 *	Upgraded to function properly on 64-bit machines.
11 */
12
13#define ECHO 010
14#include <stdio.h>
15#define ROTORSZ 256
16#define MASK 0377
17char	t1[ROTORSZ];
18char	t2[ROTORSZ];
19char	t3[ROTORSZ];
20char	deck[ROTORSZ];
21char	*getpass();
22char	buf[13];
23
24void	shuffle();
25void	puth();
26
27void
28setup(pw)
29char *pw;
30{
31	int ic, i, k, temp, pf[2], pid;
32	unsigned random;
33	long seed;
34
35	strncpy(buf, pw, 8);
36	while (*pw)
37		*pw++ = '\0';
38	buf[8] = buf[0];
39	buf[9] = buf[1];
40	pipe(pf);
41	if ((pid=fork())==0) {
42		close(0);
43		close(1);
44		dup(pf[0]);
45		dup(pf[1]);
46		execlp("makekey", "-", 0);
47		execl("/usr/libexec/makekey", "-", 0);	/* BSDI */
48		execl("/usr/lib/makekey", "-", 0);
49		execl("/usr/bin/makekey", "-", 0);	/* IBM */
50		execl("/lib/makekey", "-", 0);
51		perror("makekey");
52		fprintf(stderr, "enigma: cannot execute 'makekey', aborting\n");
53		exit(1);
54	}
55	write(pf[1], buf, 10);
56	close(pf[1]);
57	i=wait((int *)NULL);
58	if (i<0) perror("enigma: wait");
59	if (i!=pid) {
60		fprintf(stderr, "enigma: expected pid %d, got pid %d\n", pid, i);
61		exit(1);
62	}
63	if ((i=read(pf[0], buf, 13)) != 13) {
64		fprintf(stderr, "enigma: cannot generate key, read %d\n",i);
65		exit(1);
66	}
67	seed = 123;
68	for (i=0; i<13; i++)
69		seed = seed*buf[i] + i;
70	for(i=0;i<ROTORSZ;i++) {
71		t1[i] = i;
72		deck[i] = i;
73	}
74	for(i=0;i<ROTORSZ;i++) {
75		seed = 5*seed + buf[i%13];
76		if( sizeof(long) > 4 )  {
77			/* Force seed to stay in 32-bit signed math */
78			if( seed & 0x80000000 )
79				seed = seed | (-1L & ~0xFFFFFFFFL);
80			else
81				seed &= 0x7FFFFFFF;
82		}
83		random = seed % 65521;
84		k = ROTORSZ-1 - i;
85		ic = (random&MASK)%(k+1);
86		random >>= 8;
87		temp = t1[k];
88		t1[k] = t1[ic];
89		t1[ic] = temp;
90		if(t3[k]!=0) continue;
91		ic = (random&MASK) % k;
92		while(t3[ic]!=0) ic = (ic+1) % k;
93		t3[k] = ic;
94		t3[ic] = k;
95	}
96	for(i=0;i<ROTORSZ;i++)
97		t2[t1[i]&MASK] = i;
98}
99
100main(argc, argv)
101char *argv[];
102{
103	register int i, n1, n2, nr1, nr2;
104	int secureflg = 0;
105
106	if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 's') {
107		argc--;
108		argv++;
109		secureflg = 1;
110	}
111	if (argc != 2){
112		setup(getpass("Enter key:"));
113	}
114	else
115		setup(argv[1]);
116	n1 = 0;
117	n2 = 0;
118	nr2 = 0;
119
120	while((i=getchar()) >=0) {
121		if (secureflg) {
122			nr1 = deck[n1]&MASK;
123			nr2 = deck[nr1]&MASK;
124		} else {
125			nr1 = n1;
126		}
127		i = t2[(t3[(t1[(i+nr1)&MASK]+nr2)&MASK]-nr2)&MASK]-nr1;
128		putchar(i);
129		n1++;
130		if(n1==ROTORSZ) {
131			n1 = 0;
132			n2++;
133			if(n2==ROTORSZ) n2 = 0;
134			if (secureflg) {
135				shuffle(deck);
136			} else {
137				nr2 = n2;
138			}
139		}
140	}
141}
142
143void
144shuffle(deck)
145	char deck[];
146{
147	int i, ic, k, temp;
148	unsigned random;
149	static long seed = 123;
150
151	for(i=0;i<ROTORSZ;i++) {
152		seed = 5*seed + buf[i%13];
153		random = seed % 65521;
154		k = ROTORSZ-1 - i;
155		ic = (random&MASK)%(k+1);
156		temp = deck[k];
157		deck[k] = deck[ic];
158		deck[ic] = temp;
159	}
160}
161
162void
163puth( title, cp, len )
164char	*title;
165char	*cp;
166int	len;
167{
168	fprintf( stderr, "%s = ", title);
169	while( len-- > 0 )  {
170		fprintf(stderr, "%2.2x ", (*cp++) & 0xFF );
171	}
172	fprintf(stderr,"\n");
173}
174