[comp.mail.elm] Using crypt

lmb@vicom.COM (Larry Blair) (01/17/89)

I've been talking with the guys who wrote "mush" about adding elm compatible
encryption to their mailer.  They are concerned about the fact the elm uses
crypt() in its encryption, since it isn't available outside of the U.S.

Looking at encode.c, I see that it is used the encrypt the user entered key
for use with the old Enigma rotor scheme.  I don't understand why that is
necessary.  What benefit is gained from encrypting the key?  I'm not a
cryptographer, but it seems to me that encrypting the key does not add
significantly to the security of the message.
-- 
Larry Blair   ames!vsi1!lmb   lmb@vicom.com

lmb@vicom.COM (Larry Blair ) (01/19/89)

In article <1366@vsi1.COM>, I wrote:
> Looking at encode.c, I see that it is used the encrypt the user entered key
> for use with the old Enigma rotor scheme.  I don't understand why that is
> necessary.  What benefit is gained from encrypting the key?  I'm not a
> cryptographer, but it seems to me that encrypting the key does not add
> significantly to the security of the message.

I received several pieces of mail that pointed out the crypting the key
produces a more random key.  My feeling is "so what?"

o The Enigma algorithm is a "crackable" one.  Randomizing the key only
  makes it harder.

o To my thinking, encrypting the mail is mainly to prevent nosy people
  with system priviledges from prying.  Anyone who truly wants to crack
  your message won't be deterred by crypting the key.  If you want a "safe"
  message, use crypt(1) on the whole thing.

o Using the crypt() call makes elm non-portable to non-US sites. [This,
  of course, is absurd when you consider that a DES crypt program was
  posted to the net.]

I've always been appalled at the insecurity of the current email system.
I _really_ like encrypted mail, so I am now on a quest to try to get
the various mail systems to unite in their handling of encryption.
-- 
Larry Blair   ames!vsi1!lmb   lmb@vicom.com

jbayer@ispi.UUCP (Jonathan Bayer) (01/21/89)

In article <1381@vsi1.COM> lmb@vicom.COM (Larry Blair ) writes:
>
>o Using the crypt() call makes elm non-portable to non-US sites. [This,
>  of course, is absurd when you consider that a DES crypt program was
>  posted to the net.]

If that is so (I apparently missed it) why not just include it in Elm
and eliminate any system dependencies.


JB

-- 
Jonathan Bayer			       Beware: The light at the end of the
Intelligent Software Products, Inc.	       tunnel may be an oncoming dragon
19 Virginia Ave.				...uunet!ispi!jbayer
Rockville Centre, NY   11570	(516) 766-2867	jbayer@ispi

rob@pbhyf.PacBell.COM (Rob Bernardo) (01/23/89)

In article <1381@vsi1.COM> lmb@vicom.COM (Larry Blair ) writes:
+o To my thinking, encrypting the mail is mainly to prevent nosy people
+  with system priviledges from prying.  Anyone who truly wants to crack
+  your message won't be deterred by crypting the key.  If you want a "safe"
+  message, use crypt(1) on the whole thing.

Beware: crypt can produce non-ascii characters, which email doesn't tolerate.
-- 
Rob Bernardo, Pacific Bell UNIX/C Reusable Code Library
Email:     ...![backbone]!pacbell!pbhyf!rob   OR  rob@pbhyf.PacBell.COM
Office:    (415) 823-2417  Room 4E750A, San Ramon Valley Administrative Center
Residence: (415) 827-4301  R Bar JB, Concord, California

lmb@vicom.COM (Larry Blair) (01/24/89)

In article <420@ispi.UUCP> jbayer@ispi.UUCP (Jonathan Bayer) writes:
=In article <1381@vsi1.COM> lmb@vicom.COM (Larry Blair ) writes:
=>
=>o Using the crypt() call makes elm non-portable to non-US sites. [This,
=>  of course, is absurd when you consider that a DES crypt program was
=>  posted to the net.]
=
=If that is so (I apparently missed it) why not just include it in Elm
=and eliminate any system dependencies.

I tried to track it down, but I can't seem to find where it was.  It may
have been some place like alt.sources.  In any event, at this time it is
illegal to export a DES encryption program.  Btw, for anyone who wants to
write one, the Nov. '88 "Scientific American" contains a complete description
of the algorithm, along with the necessary permutation tables.

I still maintain that the use of crypt() is unecessary.  Let's, at least,
make it optional.
-- 
Larry Blair   ames!vsi1!lmb   lmb@vicom.com

prc@maxim.ERBE.SE (Robert Claeson) (02/05/89)

In article <1398@vsi1.COM>, lmb@vicom.COM (Larry Blair) writes:

> ... In any event, at this time it is
> illegal to export a DES encryption program.  Btw, for anyone who wants to
> write one, the Nov. '88 "Scientific American" contains a complete description
> of the algorithm, along with the necessary permutation tables.

Europeans can use the DES or enigma program(s) available on the EUUG tapes.

> I still maintain that the use of crypt() is unecessary.  Let's, at least,
> make it optional.

Let's abandon crypt() altogether. It's not included in any UNIX systems
outside the U.S.A. (unless one buys a source license).
-- 
Robert Claeson, ERBE DATA AB, P.O. Box 77, S-175 22 Jarfalla, Sweden
"No problems." -- Alf
Tel: +46 758-202 50  EUnet:    rclaeson@ERBE.SE  uucp:   uunet!erbe.se!rclaeson
Fax: +46 758-197 20  Internet: rclaeson@ERBE.SE  BITNET: rclaeson@ERBE.SE

clarke@acheron.UUCP (Ed Clarke) (02/05/89)

From article <484@maxim.ERBE.SE>, by prc@maxim.ERBE.SE (Robert Claeson):
> In article <1398@vsi1.COM>, lmb@vicom.COM (Larry Blair) writes:
> Let's abandon crypt() altogether. It's not included in any UNIX systems
> outside the U.S.A. (unless one buys a source license).

I would really like to have 'rot13' put in place of the crypt()
routine.  crypt is ok, but suffers from the export restriction.
rot13 is simple, trivial to implement and anyone can decode it.

So why use it you ask?  Because I'm the postmaster here I sometimes
have to go in and diagnose mailing failures.  It bothers me to see
someone elses private mail.  rot13 would make ME feel better even
though it's not true encryption.

For secure mail, crypt the data outside of elm.  Use the program of
your choice and uuencode if it produces non printable data.
-- 
Ed Clarke
uunet!bywater!acheron!clarke

craigb@ipso.rss.ips.oz (Craig Bevins) (02/08/89)

In article <1398@vsi1.COM> lmb@vicom.COM (Larry Blair) writes:
>In article <420@ispi.UUCP> jbayer@ispi.UUCP (Jonathan Bayer) writes:
>=In article <1381@vsi1.COM> lmb@vicom.COM (Larry Blair ) writes:
>=>
>=>o Using the crypt() call makes elm non-portable to non-US sites. [This,
>=>  of course, is absurd when you consider that a DES crypt program was
>=>  posted to the net.]
>=
>=If that is so (I apparently missed it) why not just include it in Elm
>=and eliminate any system dependencies.
>
>I tried to track it down, but I can't seem to find where it was.  It may
>have been some place like alt.sources.  In any event, at this time it is
>illegal to export a DES encryption program.

I have only come in on the tail end of this discussion, so excuse me
if I have the wrong end of the stick ...

Firstly, let's get the issue of portability out of the way: the use of
crypt(3C/3X) definitely does NOT make software non-portable to non-US
sites.  What do you think the rest of us use for password encryption?
All that's missing from exported systems are crypt(1) (how absurd) and
the decrypt option of encrypt(3C/3X).

So it's illegal for you guys to export DES software, huh?  As far as
I know there's nothing to stop me exporting it from Oz, so here it is,
fresh from volume 7 of my mod.sources archive.  I didn't really want
that US visa, anyway :-).

I haven't even compiled this stuff, let alone attempted to use it, so
caveat emptor.

It seems that the enigma software (a.k.a. crypt(1)) has also been posted
as part of the Crypt Breaker's Workbench package in comp.sources.unix,
volume 10.  If there's sufficient demand, and I don't get any threatening
mail from on-high, I can re-post that little bugger too.

Enjoy.

##########################################################################
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by craigb@ipso.ips.oz.au on Wed Feb  8 03:19:54 EST 1989
# Contents:  Makefile README des.c des.1
 
echo x - Makefile
sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
des:	des.c
	cc -O -o des des.c

# these targets are for my BSD system; your mileage will vary.
install:	des
	cp des /usr/local/bin/des
	cp des.1 /usr/local/man/man1/des.1
@//E*O*F Makefile//
chmod u=rw,g=r,o= Makefile
 
echo x - README
sed 's/^@//' > "README" <<'@//E*O*F README//'
This program came from a cryptography related BBS near Washington, DC.
I have been unable to verify whether it works.  It does compile and run
on 4.2BSD (Sun Unix).  However, the other DES implementation I have
available (Sun's) uses a different format for keys.  I wish both would
allow you to type the 56-bit key as 14 digits of hex -- but neither one
does, they do different transformations of 8 bytes of ASCII.

If anyone has the DES validation samples [from the standard or its 
accompanying publications], please post them.

Note that I do not recommend the use of DES if you want to keep your
data secure.  All that can be said for it is that fewer people know
how to break it than crypt(1).
@//E*O*F README//
chmod u=rw,g=r,o= README
 
echo x - des.c
sed 's/^@//' > "des.c" <<'@//E*O*F des.c//'

/*
 * From: sources-request@mirror.UUCP
 * Newsgroups: mod.sources
 * Subject: v07i027:  Purported DES program in C
 * Message-ID: <240@mirror.UUCP>
 * Date: 15 Sep 86 04:17:06 GMT
 *
 * Submitted by: cca!caip!lll-crg!hoptoad!gnu (John Gilmore)
 * Mod.sources: Volume 7, Issue 27
 * Archive-name: des
 *
 * [  I wrote the Makefile and manpage.  Before compiling this program, you
 *    will want to take a look at the non-standard fopen calls.  I believe
 *    the "rb" and "wb" parameters are instructions to open the file in
 *    'binary' (8bit, no newline mapping) mode for some MS-DOS compilers.
 *    --r$  ]
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 * des: duplicate the NBS Data Encryption Standard in software.
 * usage: des <file>
 * prompts for the password
 * If the filename ends in ".n" it will be decrypted with the key;
 * otherwise it will be encrypted.
 *
 * Permutation algorithm:
 *	The permutation is defined by its effect on each of the 16 nibbles
 *	of the 64-bit input.  For each nibble we give an 8-byte bit array
 *	that has the bits in the input nibble distributed correctly.  The
 *	complete permutation involves ORing the 16 sets of 8 bytes designated
 *	by the 16 input nibbles.  Uses 16*16*8 = 2K bytes of storage for
 *	each 64-bit permutation.  32-bit permutations (P) and expansion (E)
 *	are done similarly, but using bytes instead of nibbles.
 *	Should be able to use long ints, adding the masks, at a
 *	later pass.  Tradeoff: can speed 64-bit perms up at cost of slowing 
 *	down expansion or contraction operations by using 8K tables here and
 *	decreasing the size of the other tables.
 * The compressions are pre-computed in 12-bit chunks, combining 2 of the
 *	6->4 bit compressions.
 * The key schedule is also precomputed.
 * Compile with VALIDATE defined to run the NBS validation suite.
 *
 * Jim Gillogly, May 1977
 * Modified 8/84 by Jim Gillogly and Lauren Weinstein to compile with
 *   post-1977 C compilers and systems
 *
 * This program is now officially in the public domain, and is available for
 * any non-profit use as long as the authorship line is retained.
 */

/*#define VALIDATE	*/	/* define to check the NBS validation suite */
/*#define DEBUG 	*/
/*#define LATTICE	*/	/* define for Lattice C on IBM PC */

#include <stdio.h>

#ifndef LATTICE
#include <sgtty.h>
#include <signal.h>
#ifdef	BSD
#include <sys/types.h>  /* for local timer */
#include <sys/timeb.h>  /* ditto */
#else
#include <time.h>
#endif

struct sgttyb ttybuf;			/* for gtty/stty 		*/
int bye();				/* for caught interrupts 	*/

#endif

char iperm[16][16][8],fperm[16][16][8]; /* inital and final permutations*/
char s[4][4096];			/* S1 thru S8 precomputed	*/
char p32[4][256][4];			/* for permuting 32-bit f output*/
char kn[16][6];				/* key selections		*/

endes(inblock,outblock)			/* encrypt 64-bit inblock	*/
char *inblock, *outblock;
{	char iters[17][8];		/* workspace for each iteration */
	char swap[8];			/* place to interchange L and R */
	register int i;
	register char *s, *t;

	permute(inblock,iperm,iters[0]);/* apply initial permutation	*/
	for (i=0; i<16; i++)		/* 16 churning operations	*/
		iter(i,iters[i],iters[i+1]);
					/* don't re-copy to save space  */
	s = swap; t = &iters[16][4];	/* interchange left		*/
	*s++ = *t++; *s++ = *t++; *s++ = *t++; *s++ = *t++;
	t = &iters[16][0];		/* and right			*/
	*s++ = *t++; *s++ = *t++; *s++ = *t++; *s++ = *t++;
	permute(swap,fperm,outblock);   /* apply final permutation	*/
}

dedes(inblock,outblock)			/* decrypt 64-bit inblock	*/
char *inblock,*outblock;
{	char iters[17][8];		/* workspace for each iteration */
	char swap[8];			/* place to interchange L and R */
	register int i;
	register char *s, *t;

	permute(inblock,iperm,iters[0]);/* apply initial permutation	*/
	for (i=0; i<16; i++)		/* 16 churning operations	*/
		iter(15-i,iters[i],iters[i+1]);
					/* reverse order from encrypting*/
	s = swap; t = &iters[16][4];	/* interchange left		*/
	*s++ = *t++; *s++ = *t++; *s++ = *t++; *s++ = *t++;
	t = &iters[16][0];		/* and right			*/
	*s++ = *t++; *s++ = *t++; *s++ = *t++; *s++ = *t++;
	permute(swap,fperm,outblock);   /* apply final permutation	*/
}

permute(inblock,perm,outblock)		/* permute inblock with perm	*/
char *inblock, *outblock;		/* result into outblock,64 bits */
char perm[16][16][8];			/* 2K bytes defining perm.	*/
{	register int i,j;
	register char *ib, *ob;		/* ptr to input or output block */
	register char *p, *q;

	for (i=0, ob = outblock; i<8; i++)
		*ob++ = 0;		/* clear output block		*/
	ib = inblock;
	for (j = 0; j < 16; j += 2, ib++) /* for each input nibble	*/
	{	ob = outblock;
		p = perm[j][(*ib >> 4) & 017];
		q = perm[j + 1][*ib & 017];
		for (i = 0; i < 8; i++)   /* and each output byte	*/
			*ob++ |= *p++ | *q++;   /* OR the masks together*/
	}
}

char ip[]				/* initial permutation P	*/
= {	58, 50, 42, 34, 26, 18, 10,  2,
	60, 52, 44, 36, 28, 20, 12,  4,
	62, 54, 46, 38, 30, 22, 14,  6,
	64, 56, 48, 40, 32, 24, 16,  8,
	57, 49, 41, 33, 25, 17,  9,  1,
	59, 51, 43, 35, 27, 19, 11,  3,
	61, 53, 45, 37, 29, 21, 13,  5,
	63, 55, 47, 39, 31, 23, 15,  7	};

char fp[]				/* final permutation F	  */
= {	40,  8, 48, 16, 56, 24, 64, 32,
	39,  7, 47, 15, 55, 23, 63, 31,
	38,  6, 46, 14, 54, 22, 62, 30,
	37,  5, 45, 13, 53, 21, 61, 29,
	36,  4, 44, 12, 52, 20, 60, 28,
	35,  3, 43, 11, 51, 19, 59, 27,
	34,  2, 42, 10, 50, 18, 58, 26,
	33,  1, 41,  9, 49, 17, 57, 25	};

/* expansion operation matrix   */	/* rwo: unused	*/
/* char ei[] = {	32,  1,  2,  3,  4,  5,
	 4,  5,  6,  7,  8,  9,
	 8,  9, 10, 11, 12, 13,
	12, 13, 14, 15, 16, 17,
	16, 17, 18, 19, 20, 21,
	20, 21, 22, 23, 24, 25,
	24, 25, 26, 27, 28, 29,
	28, 29, 30, 31, 32,  1  };	*/

char pc1[]				/* permuted choice table (key)  */
= {	57, 49, 41, 33, 25, 17,  9,
	 1, 58, 50, 42, 34, 26, 18,
	10,  2, 59, 51, 43, 35, 27,
	19, 11,  3, 60, 52, 44, 36,

	63, 55, 47, 39, 31, 23, 15,
	 7, 62, 54, 46, 38, 30, 22,
	14,  6, 61, 53, 45, 37, 29,
	21, 13,  5, 28, 20, 12,  4	};

char totrot[]			   /* number left rotations of pc1 */
= {	1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28	};

char pc1m[56];			  /* place to modify pc1 into	*/
char pcr[56];			   /* place to rotate pc1 into	*/

char pc2[]				/* permuted choice key (table)  */
= {	14, 17, 11, 24,  1,  5,
	 3, 28, 15,  6, 21, 10,
	23, 19, 12,  4, 26,  8,
	16,  7, 27, 20, 13,  2,
	41, 52, 31, 37, 47, 55,
	30, 40, 51, 45, 33, 48,
	44, 49, 39, 56, 34, 53,
	46, 42, 50, 36, 29, 32	};

char si[8][64]			  /* 48->32 bit compression tables*/
= {					/* S[1]			 */
	14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
	 0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
	 4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
	15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
					/* S[2]			 */
	15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
	 3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
	 0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
	13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
					/* S[3]			 */
	10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
	13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
	13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
	 1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
					/* S[4]			 */
	 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
	13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
	10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
	 3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
					/* S[5]			 */
	 2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
	14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
	 4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
	11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
					/* S[6]			 */
	12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
	10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
	 9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
	 4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
					/* S[7]			 */
	 4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
	13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
	 1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
	 6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
					/* S[8]			 */
	13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
	 1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
	 7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
	 2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11	};

char p32i[]				/* 32-bit permutation function  */
= {	16,  7, 20, 21,
	29, 12, 28, 17,
	 1, 15, 23, 26,
	 5, 18, 31, 10,
	 2,  8, 24, 14,
	32, 27,  3,  9,
	19, 13, 30,  6,
	22, 11,  4, 25	};

desinit(key)				/* initialize all des arrays	*/
char *key;
{
#ifdef DEBUG
/*deb*/ printf("Initial perm init.\n");
#endif
	perminit(iperm,ip);		/* initial permutation		*/
#ifdef DEBUG
/*deb*/ printf("Final perm init.\n");
#endif
	perminit(fperm,fp);		/* final permutation		*/
#ifdef DEBUG
/*deb*/ printf("Key sched init.\n");
#endif
	kinit(key);			/* key schedule			*/
#ifdef DEBUG
/*deb*/ printf("Compression init.\n");
#endif
	sinit();			/* compression functions	*/

#ifdef DEBUG
/*deb*/ printf("32-bit perm init.\n");
#endif
	p32init();			/* 32-bit permutation in f	*/
#ifdef DEBUG
/*deb*/ printf("End init.\n");
#endif
}

int bytebit[]			   /* bit 0 is left-most in byte	*/
	= {	0200,0100,040,020,010,04,02,01 };

int nibblebit[] = { 010,04,02,01 };

sinit()				 /* initialize s1-s8 arrays		*/
{	register int i,j;

	for (i=0; i<4; i++)		/* each 12-bit position		*/
		for (j=0; j<4096; j++)  /* each possible 12-bit value   */
			s[i][j]=(getcomp(i*2,j>>6)<<4) |
				(017&getcomp(i*2+1,j&077));
					/* store 2 compressions per char*/
}

getcomp(k,v)				/* 1 compression value for sinit*/
int k,v;
{	register int i,j;		/* correspond to i and j in FIPS*/

	i=((v&040)>>4)|(v&1);		/* first and last bits make row */
	j=(v&037)>>1;			/* middle 4 bits are column	*/
	return (int) si[k][(i<<4)+j];   /* result is ith row, jth col   */
}

kinit(key)				/* initialize key schedule array*/
char *key;				/* 64 bits (will use only 56)   */
{	register int i,j,l;
	int m;

	for (j=0; j<56; j++)		/* convert pc1 to bits of key   */
	{	l=pc1[j]-1;		/* integer bit location		*/
		m = l & 07;		/* find bit			*/
		pc1m[j]=(key[l>>3] &	/* find which key byte l is in  */
			bytebit[m])	/* and which bit of that byte   */
			? 1 : 0;	/* and store 1-bit result	*/
	}
	for (i=0; i<16; i++)		/* for each key sched section   */
		for (j=0; j<6; j++)	/* and each byte of the kn	*/
			kn[i][j]=0;	/* clear it for accumulation	*/
	for (i=0; i<16; i++)		/* key chunk for each iteration */
	{	for (j=0; j<56; j++)	/* rotate pc1 the right amount  */
		pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28];
			/* rotate left and right halves independently   */
		for (j=0; j<48; j++)	/* select bits individually	*/
		if (pcr[pc2[j]-1])	/* check bit that goes to kn[j] */
			{	l= j & 07;
				kn[i][j>>3] |= bytebit[l];
			}		/* mask it in if it's there	*/
	}
}

p32init()				/* initialize 32-bit permutation*/
{	register int l, j, k;
	int i,m;

	for (i=0; i<4; i++)		/* each input byte position	*/
		for (j=0; j<256; j++)	/* all possible input bytes	*/
		for (k=0; k<4; k++)	/* each byte of the mask	*/
			p32[i][j][k]=0;	/* clear permutation array	*/
	for (i=0; i<4; i++)		/* each input byte position	*/
		for (j=0; j<256; j++)	/* each possible input byte	*/
		for (k=0; k<32; k++)	/* each output bit position	*/
		{   l=p32i[k]-1;	/* invert this bit (0-31)	*/
			if ((l>>3)!=i)	/* does it come from input posn?*/
			continue;	/* if not, bit k is 0		*/
			if (!(j&bytebit[l&07]))
			continue;	/* any such bit in input?	*/
			m = k & 07;	 /* which bit is it?		*/
			p32[i][j][k>>3] |= bytebit[m];
		}
}

perminit(perm,p)			/* initialize a perm array	*/
char perm[16][16][8];			/* 64-bit, either init or final */
char p[64];
{	register int l, j, k;
	int i,m;

	for (i=0; i<16; i++)		/* each input nibble position   */
		for (j=0; j<16; j++)	/* all possible input nibbles   */
		for (k=0; k<8; k++)	/* each byte of the mask	*/
			perm[i][j][k]=0;/* clear permutation array	*/
	for (i=0; i<16; i++)		/* each input nibble position   */
		for (j = 0; j < 16; j++)/* each possible input nibble   */
		for (k = 0; k < 64; k++)/* each output bit position	*/
		{   l = p[k] - 1;	/* where does this bit come from*/
			if ((l >> 2) != i)  /* does it come from input posn?*/
			continue;	/* if not, bit k is 0		*/
			if (!(j & nibblebit[l & 3]))
			continue;	/* any such bit in input?	*/
			m = k & 07;	/* which bit is this in the byte*/
			perm[i][j][k>>3] |= bytebit[m];
		}
}

iter(num,inblock,outblock)		/* 1 churning operation		*/
int num;				/* i.e. the num-th one		*/
char *inblock, *outblock;		/* 64 bits each			*/
{	char fret[4];			/* return from f(R[i-1],key)	*/
	register char *ib, *ob, *fb;
/*	register int i;	*/	/* rwo: unused	*/

	ob = outblock; ib = &inblock[4];
	f(ib, num, fret);		/* the primary transformation   */
	*ob++ = *ib++;			/* L[i] = R[i-1]		*/
	*ob++ = *ib++;
	*ob++ = *ib++;
	*ob++ = *ib++;
	ib = inblock; fb = fret;	/* R[i]=L[i] XOR f(R[i-1],key)  */
	*ob++ = *ib++ ^ *fb++;
	*ob++ = *ib++ ^ *fb++;
	*ob++ = *ib++ ^ *fb++;
	*ob++ = *ib++ ^ *fb++;
}

f(right,num,fret)			/* critical cryptographic trans */
char *right, *fret;			/* 32 bits each			*/
int num;				/* index number of this iter	*/
{	register char *kb, *rb, *bb;	/* ptr to key selection &c	*/
	char bigright[6];		/* right expanded to 48 bits	*/
	char result[6];			/* expand(R) XOR keyselect[num] */
	char preout[4];			/* result of 32-bit permutation */

	kb = kn[num];			/* fast version of iteration	*/
	bb = bigright;
	rb = result;
	expand(right,bb);		/* expand to 48 bits		*/
	*rb++ = *bb++ ^ *kb++;		/* expanded R XOR chunk of key  */
	*rb++ = *bb++ ^ *kb++;
	*rb++ = *bb++ ^ *kb++;
	*rb++ = *bb++ ^ *kb++;
	*rb++ = *bb++ ^ *kb++;
	*rb++ = *bb++ ^ *kb++;
	contract(result,preout);	/* use S fns to get 32 bits	*/
	perm32(preout,fret);		/* and do final 32-bit perm	*/
}

perm32(inblock,outblock)		/* 32-bit permutation at end	*/
char *inblock,*outblock;		/* of the f crypto function	*/
{	register int j;
/*	register int i;	*/	/* rwo: unused	*/
	register char *ib, *ob;
	register char *q;

	ob = outblock;			/* clear output block		*/
	*ob++ = 0; *ob++ = 0; *ob++ = 0; *ob++ = 0;
	ib=inblock;			/* ptr to 1st byte of input	*/
	for (j=0; j<4; j++, ib++)	/* for each input byte		*/
	{	q = p32[j][*ib & 0377];
		ob = outblock;		/* and each output byte		*/
		*ob++ |= *q++;		/* OR the 16 masks together	*/
		*ob++ |= *q++;
		*ob++ |= *q++;
		*ob++ |= *q++;
	}
}

expand(right,bigright)			/* 32 to 48 bits with E oper	*/
char *right,*bigright;			/* right is 32, bigright 48	*/
{
	register char *bb, *r, r0, r1, r2, r3;

	bb = bigright;
	r = right; r0 = *r++; r1 = *r++; r2 = *r++; r3 = *r++;
	*bb++ = ((r3 & 0001) << 7) |	/* 32				*/
		((r0 & 0370) >> 1) |	/* 1 2 3 4 5			*/
		((r0 & 0030) >> 3);	/* 4 5				*/
	*bb++ = ((r0 & 0007) << 5) |	/* 6 7 8			*/
		((r1 & 0200) >> 3) |	/* 9				*/
		((r0 & 0001) << 3) |	/* 8				*/
		((r1 & 0340) >> 5);	/* 9 10 11			*/
	*bb++ = ((r1 & 0030) << 3) |	/* 12 13			*/
		((r1 & 0037) << 1) |	/* 12 13 14 15 16		*/
		((r2 & 0200) >> 7);	/* 17				*/
	*bb++ = ((r1 & 0001) << 7) |	/* 16				*/
		((r2 & 0370) >> 1) |	/* 17 18 19 20 21		*/
		((r2 & 0030) >> 3);	/* 20 21			*/
	*bb++ = ((r2 & 0007) << 5) |	/* 22 23 24			*/
		((r3 & 0200) >> 3) |	/* 25				*/
		((r2 & 0001) << 3) |	/* 24				*/
		((r3 & 0340) >> 5);	/* 25 26 27			*/
	*bb++ = ((r3 & 0030) << 3) |	/* 28 29			*/
		((r3 & 0037) << 1) |	/* 28 29 30 31 32		*/
		((r0 & 0200) >> 7);	/* 1				*/
}

contract(in48,out32)			/* contract f from 48 to 32 bits*/
char *in48,*out32;			/* using 12-bit pieces into bytes */
{	register char *c;
	register char *i;
	register int i0, i1, i2, i3, i4, i5;

	i = in48;
	i0 = *i++; i1 = *i++; i2 = *i++; i3 = *i++; i4 = *i++; i5 = *i++;
	c = out32;			/* do output a byte at a time   */
	*c++ = s[0][07777 & ((i0 << 4) | ((i1 >> 4) & 017  ))];
	*c++ = s[1][07777 & ((i1 << 8) | ( i2	& 0377 ))];
	*c++ = s[2][07777 & ((i3 << 4) | ((i4 >> 4) & 017  ))];
	*c++ = s[3][07777 & ((i4 << 8) | ( i5	& 0377 ))];
}

/* End of DES algorithm (except for calling desinit below)	*/

#ifndef VALIDATE
char *inname, *outname;
FILE *infile, *outfile;

int encrypting;
char buf[512];
char keyx[9], keyy[9];

char *malloc(), *strcpy(), *strcat();

main(argc, argv)
int argc; char *argv[];
{	register char *u;
	char *filename;

	if (argc < 2)			/* filenames given? */
	{  fprintf(stderr, "Usage: des file ...\n");
	   exit(1); 	
	}

	for (++argv; --argc; ++argv)
	{	inname = *argv;
		outname = filename = malloc((unsigned) strlen(inname) + 3);
		strcpy(filename, inname);
		u = &filename[strlen(filename) - 2]; /* check last 2 chars */

		encrypting = (strcmp(".n", u) != 0);
		if (!encrypting) *u = 0; /* strip .n from output filename */
		else strcat(filename, ".n");  /* or add .n to output file */

#		ifdef	LATTICE
		if ((infile = fopen(inname, "rb")) == NULL)
#		else
		if ((infile = fopen(inname, "r")) == NULL)
#		endif
		{	fprintf(stderr,"Can't read %s.\n", inname);
			exit(1);
		}
#		ifdef	LATTICE
		if ((outfile = fopen(outname, "rb")) != NULL)
#		else
		if ((outfile = fopen(outname, "r")) != NULL)
#		endif
		{	fprintf(stderr, "%s would be overwritten.\n",outname);
			exit(1);
		}
#		ifdef	LATTICE
		if ((outfile = fopen(outname, "wb")) == NULL)
#		else
		if ((outfile = fopen(outname, "w")) == NULL)
#		endif
		{	fprintf(stderr,"Can't write %s.\n", outname);
			exit(1);
		}

		key_get("Type password for ");
		for (;;)
		{	strcpy(keyx, keyy);
			key_get("Verify password for ");
			if (strcmp(keyx, keyy) == 0) break;
		}
		desinit(keyx);	  /* set up tables for DES	*/

		if (pfile() == 0) unlink(inname);
		else	fprintf(stderr,
			   "%s: I/O Error -- File unchanged\n", inname);

		fclose(outfile);
		fclose(infile);
	}
	exit(0);
}

key_get(mes)			/* get file key */
char *mes;
{	register int i, j;
	char linebuf[256];
	int count;

	for (i=0; i<14; i++) keyy[i]=0;

#ifdef LATTICE
#else
	gtty(0, &ttybuf);
	ttybuf.sg_flags &= ~ECHO;  /* turn off echoing */
	signal(SIGINT, bye);	/* catch ints */
	stty(0, &ttybuf);
#endif

	printf("%s%s: ", mes, inname);
	fflush(stdout);

	count = read(0, linebuf, 256);  /* read input line */
	printf("\n");

#ifndef LATTICE
	ttybuf.sg_flags |= ECHO;  	/* restore echo */
	stty(0, &ttybuf);
#endif

	linebuf[count] = 0;  /* null terminate */
	if (linebuf[count-1] == '\n')  /* ignore any terminating newline */
	{  linebuf[count-1] = 0;
	   count--; 	
	}
	if (count > 8) count = 8;	/* only use 8 chars */
	for (i = j = 0; count--;)
	   keyy[i++] = linebuf[j++];
}

pfile()				 /* process the file		*/
{	register int m, nsave;
	register char *b;
	int j;

	while (m = fread(buf, 1, 512, infile))
	{
		if ((nsave = m) < 0)	/* read error			*/
		return(-1);
		for (b=buf; m>0;	/* encrypt/decrypt 1 buffer-full*/
		m -= 8, b += 8)		/* 8-byte blocks		*/
		{   if (encrypting)
		{   if (m<8)		/* don't have a full 64 bits	*/
			{   for (j=0; j<8-m; j++)
				b[m+j]=garbage(); /* fill block with trash  */
			nsave += 8-m;   /* complete the block		*/
			}
			else j=0;	/* number of nulls in last block*/
			endes(b,b);	/* don't need diff input, output*/
		}
		else			/* decrypting			*/
		{   if (m < 8) deout(b, 1); /* last byte in file: count */
			else
			{   dedes(b, b); /* decrypt and output block	*/
			deout(b, 0);
			}
		}
		}
		if (encrypting) if (fwrite(buf, 1, nsave, outfile) != nsave)
			return(-1);
	}
	/* have now encrypted/decrypted the whole file;
	 * need to append the byte count for the last block if encrypting.
	 */
	if (encrypting) fputc(8 - j, outfile);  /* how many good bytes? */
	return(0);
}

int outcount = 0;			/* see when caught up with delay*/

deout(block,flag)			/* 1-block delay on output	*/
char *block,flag;			/* 64-bit block, last block flag*/
{	static char last[8];		/* previous input block		*/
	register int i;
/*	register char *c,*j;	*/	/* rwo: unused	*/

	if (flag)			/* output the last few bytes	*/
	{
		fwrite(last, 1, block[0] & 0377, outfile);
		return;
	}
	if (outcount++)			/* seen any blocks before?	*/
		fwrite(last, 1, 8, outfile);
	for (i = 0; i < 8; i++) last[i] = block[i]; /* copy the block   */
}

garbage()				/* generate garbage for filling */
/* This garbage should be as random as possible.  We're using subsequent calls
 * on the timer, but ideally each byte should be uncorrelated.  Preferable
 * would be to call the timer once and use it to initialize a dumb random
 * number generator.
 */
{
#ifdef LATTICE
	long timer(), ltime;

	ltime = timer();
	return (int) ltime & 0377;
#else
#	ifdef	BSD
	struct timeb tp;

	ftime(&tp);			/* get current time		*/
	return tp.millitm;		/* return time in milliseconds  */
#	else
	long ltime;
	time(&ltime);
	return (int) ltime & 0377;
#	endif
#endif
}

#ifndef LATTICE

/* restore echo to tty and exit */
bye()
{
	ttybuf.sg_flags |= ECHO;  /* restore echoing */
	stty(0, &ttybuf);
	exit(2);
}

#endif

#else	   /* validation */

#define VALFILE "valid.triples"

FILE *fd;

char key[8], plain[8], cipher[8], processed[8];

main()  /* read key/plain/cipher triples until exhausted */
{	int count, i;

	if ((fd = fopen(VALFILE, "r")) == NULL)
	{	fprintf(stderr, "Can't read %s.\n", VALFILE);
		exit(1);
	}
	count = 0;
	desinit(key);		/* initialize most of the arrays */
	while (readvals())
	{	kinit(key);	/* initialize key stuff		*/
		printf("Key: "); writehex(key);
		printf("  Plain: "); writehex(plain);
		printf("  Cipher: "); writehex(cipher);
		printf("\n");
		endes(plain, processed); /* encipher the plaintext */
		printf("Encry:  "); writehex(processed);
		printf("\n");
		for (i = 0; i < 8; i++)
			if (processed[i] != cipher[i])
				printf("Encryption failed.\n");
		dedes(cipher, processed); /* decipher the ciphertext */
		printf("Decry:  "); writehex(processed);
		printf("\n");
		for (i = 0; i < 8; i++)
			if (processed[i] != plain[i])
				printf("Decryption failed.\n");
		count++;
	}
	printf("Processed %d tests.\n", count);
}

readvals()	/* get the next legit triple */
{	int r;

	r = readhex(key);
	readhex(plain);
	readhex(cipher);
	return r;
}

writehex(str)   /* write the 64-bit hex string */
char *str;
{	int i;

	for (i = 0; i < 8; i++)
		printf("%02x", str[i] & 0377);
}

hex(n)  /* convert hex nibble into integer */
int n;
{
	if (n >= 'A' && n <= 'F') return n - 'A' + 10;
	return n - '0';
}

readhex(str)	/* read 64 bits of hex code */
char *str;
{	int i, c;

	for (i = 0; i < 8; i++)
	{	c = hex(getc(fd)) << 4;
		str[i] = c | hex(getc(fd));
	}
	while ((c = getc(fd)) == ' ' || c == '\t' || c == '\n');
	ungetc(c, fd);  /* skip to next field */
	return c != EOF;
}

#endif

/************ end scrydes ************/

@//E*O*F des.c//
chmod u=rw,g=r,o= des.c
 
echo x - des.1
sed 's/^@//' > "des.1" <<'@//E*O*F des.1//'
@.TH DES 1  LOCAL
@.SH NAME
des \- perform DES encryption on a file
@.SH SYNOPSIS
@.B des
filename
@.SH DESCRIPTION
This program takes a single argument, a file to encrypt or decrypt.
When started, it asks for a password.
If the file is named like ``foo.n'' the file is decrypted with the given key,
and output is put into the file ``foo.''
Otherwise, if the file is named like ``foo,'' the file is encrypted and
the output is put into ``foo.n''.
In both cases, the original input file is removed.
@.SH "SEE ALSO"
crypt(1)
@.SH BUGS
May not be true DES.
@//E*O*F des.1//
chmod u=rw,g=r,o= des.1
 
echo Inspecting for damage in transit...
temp=/tmp/shar$$; dtemp=/tmp/.shar$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
      7     27    159 Makefile
     13    127    699 README
    758   4236  23007 des.c
     18    102    547 des.1
    796   4492  24412 total
!!!
wc  Makefile README des.c des.1 | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if [ -s $dtemp ]
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0
-- 

Craig Bevins.
IPS Radio and Space Services.  Australian Govt Dept of Admin Services.
Internet: craigb@ipso.ips.oz.au    UUCP: uunet!ipso.ips.oz.au!craigb
Phone: +61 2 269 8635    FAX: +61 2 269 8612    Telex: AA 20663 IPSO
Snail: P.O. Box 702, Darlinghurst.  NSW.  2010.  Australia.

kquinlan@haley.edg.cv.co.uk (Kevin Quinlan) (02/15/89)

In article <490@acheron.UUCP> clarke@acheron.UUCP (Ed Clarke) writes:

>I would really like to have 'rot13' put in place of the crypt() ...
>rot13 is simple, trivial to implement and anyone can decode it.

True - and hence it is not very useful as an encryption method.

>For secure mail, crypt the data outside of elm.  Use the program of
>your choice and uuencode if it produces non printable data.

This is much more of a pain. With the present method, I can
encrypt *part* of a message and read such messages without
leaving elm - even temporarily.

It seems to me that leaving the present method in elm does no harm,
if you don't want to use it or you can't use it - then there are
alternatives outside of elm, but if you can - currently it is
very convenient - and surely that's what it is all about and why
we are all looking at this news group and not one on ucbmail or
binmail etc..

But there may be an alternative - some time ago someone
mentioned the RFC 822 header "Encrypted".  Has anyone ever seen
this used? - and couldn't elm be allowed to use one of several
encryption schemes and the details put in an "Encrypted" header?


 +---------------------------------------------------------------+
 | Kevin Quinlan, Prime Computer R & D, Amersham, HP7 0PX, UK    |
 | kquinlan@cvedg.prime.com                                      |
 | kquinlan@uk.co.cv.edg                  +44 494 714771 x 269   |
 +---------------------------------------------------------------+

ejp@ausmelb.oz (Esmond Pitt) (02/20/89)

ELM developers wherever they are must bear in mind the needs of users
with existing mailboxes containing encrypted mail, and the continuing
need to be able to read same with new versions of ELM.

We also need a means of printing encrypted mail, or of saving to a
file, in the clear. There is presently no method of putting it anywhere
unencoded except to the screen, so we have to pipe the output of elm &
edit out control characters. Very messy indeed.

-- 
Esmond Pitt, Austec (Asia/Pacific) Ltd
...!uunet.UU.NET!munnari!ausmelb!ejp,ejp@ausmelb.oz