[comp.sources.unix] v17i092: Encrypt using Hill cipher

rsalz@uunet.uu.net (Rich Salz) (02/09/89)

Submitted-by: John Cowan <magpie.MASA.COM!cowan>
Posting-number: Volume 17, Issue 92
Archive-name: hill

Hill provides file encryption using the Hill cipher.  In encryption mode,
plaintext is read from the standard input and ciphertext is written to the
standard output in accordance with a user-specified key.  Additional
options allow compressing the plaintext and/or expressing the ciphertext
in ASCII.  In decryption mode, the operations of encryption mode are
reversed (provided the right key is supplied).

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	hill
#	hill.1
#	hill0.c
#	kappa.c
#	makefile
#	table.i
export PATH; PATH=/bin:$PATH
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
^Xhill - encryption program using Hill cipher
^X
^XHill provides file encryption using the Hill cipher.
^XIn encryption mode, plaintext is read from the standard input
^Xand ciphertext is written to the standard output
^Xin accordance with a user-specified key.
^XAdditional options allow compressing the plaintext
^Xand/or expressing the ciphertext in ASCII.
^XIn decryption mode, the operations of encryption mode
^Xare reversed (provided the right key is supplied).
SHAR_EOF
fi # end of overwriting check
if test -f 'hill'
then
	echo shar: will not over-write existing file "'hill'"
else
sed 's/^X//' << \SHAR_EOF > 'hill'
^X# Hill interface routine
^Xcd /tmp
^XTEMP=hill$$
^XSED="sed s#junk#${TEMP}#"
^Xtrap 'rm -f ${TEMP}*' 0 1 2 3
^X# parse arguments
^Xset -- `getopt cCpsued $*`
^Xif [ $? != 0 ]
^Xthen
^X	echo "usage: $0 { -e | -d } [ { -c | -C | -p } ] [ -u ] [ key ]"
^X	exit 1
^Xfi
^X# set internal flags
^Xfor i in $*
^Xdo
^X	case $i in
^X	-c | -C | -p)	REDUCTION=$i;	shift;;
^X	-e | -d)		MODE=$i;	shift;;
^X	-u)			UU=$i;		shift;;
^X	--)			shift;		break;;
^X	esac
^Xdone
^Xif [ x$MODE = x ]
^Xthen
^X	echo "$0: must specify -e to encode or -d to decode"
^X	exit 1
^Xfi
^Xif [ x$1 = x ]
^Xthen
^X	HILL="hill0 $MODE"
^Xelse
^X	HILL="hill0 $MODE \"$1\""
^Xfi
^X# do the work
^Xif [ $MODE = -e ]
^Xthen
^X	case ${REDUCTION}${UU} in
^X	-c-u)	compact | $HILL >$TEMP
^X		uuencode $TEMP $TEMP.uu junk
^X		cat $TEMP.uu;;
^X	-c)	compact | $HILL;;
^X	-C-u)	compress | $HILL >$TEMP
^X		uuencode $TEMP $TEMP.uu junk
^X		cat $TEMP.uu;;
^X	-C)	compress | $HILL;;
^X	-p-u)	cat >$TEMP
^X		pack $TEMP >/dev/null
^X		$HILL <$TEMP.z >$TEMP
^X		uuencode $TEMP $TEMP.uu junk
^X		cat $TEMP.uu;;
^X	-p)	cat >$TEMP
^X		pack $TEMP >/dev/null
^X		$HILL <$TEMP.z;;
^X	-u)	$HILL >$TEMP
^X		uuencode $TEMP $TEMP.uu junk
^X		cat $TEMP.uu;;
^X	*)	$HILL;;
^X	esac
^Xelse
^X	case ${REDUCTION}${UU} in
^X	-c-u)	$SED | uudecode
^X		$HILL <$TEMP | uncompact;;
^X	-c)	$HILL | uncompact;;
^X	-C-u)	$SED | uudecode;
^X		$HILL <$TEMP | uncompress;;
^X	-C)	$HILL | uncompress;;
^X	-p-u)	$SED | uudecode
^X		$HILL <$TEMP >$TEMP.z
^X		rm -f $TEMP
^X		unpack $TEMP.z >/dev/null
^X		cat $TEMP;;
^X	-p)	$HILL >$TEMP.z
^X		unpack $TEMP.z >/dev/null
^X		cat $TEMP;;
^X	-u)	$SED | uudecode
^X		$HILL <$TEMP;;
^X	*)	$HILL;;
^X	esac
^Xfi
SHAR_EOF
fi # end of overwriting check
if test -f 'hill.1'
then
	echo shar: will not over-write existing file "'hill.1'"
else
sed 's/^X//' << \SHAR_EOF > 'hill.1'
^X.TH HILL 1
^X.SH NAME
^Xhill \- encryption program using Hill cipher
^X.SH SYNOPSIS
^X.B hill
^X[ -e | -d ]
^X[ -c | -C | -p ]
^X[ -u ]
^X[ key ]
^X.SH DESCRIPTION
^X.I Hill
^Xprovides file encryption using the Hill cipher.
^XIn encryption mode,
^Xplaintext is read from the standard input
^Xand ciphertext is written to the standard output
^Xin accordance with a user-specified
^X.B key.
^XAdditional options allow compressing the plaintext
^Xand/or expressing the ciphertext in ASCII.
^XIn decryption mode, the operations of encryption mode
^Xare reversed (provided the right
^X.B key
^Xis supplied).
^X.SH OPTIONS
^X.TP
^X.B \-e
^XEncryption mode.
^X.TP
^X.B \-d
^XDecryption mode.
^X.TP
^X.B \-c
^XUse
^X.I compact
^Xor
^X.I uncompact
^Xfor compression or decompression
^X(these programs must be on the search path
^Xto use this option).
^X.TP
^X.B \-C
^XUse
^X.I compress
^Xor
^X.I uncompress
^Xfor compression or decompression
^X(these programs must be on the search path
^Xto use this option).
^X.TP
^X.B \-p
^XUse
^X.I pack
^Xor
^X.I unpack
^Xfor compression or decompression
^X(these programs must be on the search path
^Xto use this option).
^X.TP
^X.B \-u
^XUse
^X.I uuencode
^Xafter encryption
^Xor
^X.I uudecode
^Xbefore decryption
^X(these programs must be on the search path
^Xto use this option).
^X.SH "SECURITY CONSIDERATIONS"
^X.I Hill
^Xprovides strong security against straight cryptanalysis
^Xand acceptable security against probable-plaintext analysis.
^XUse of the -c and -C options
^Xactually improves security;
^Xone of these options should be used
^Xexcept where time is critical.
^XUse of the -p option
^Xdecreases security;
^Xit should be used only where space is critical
^Xand neither -C nor -c is available.
^X.PP
^XKeys must be at least 9 bytes long
^X(the maximum length is 256 bytes)
^Xand should be both long and hard to guess.
^XAll security resides in the keys.
^X.SH "TIME CONSIDERATIONS"
^X.I Hill
^Xencrypts at the rate of about 2 kilobytes per second
^X(using a 16-byte key)
^Xon an 8MHz IBM PC/AT running SCO Xenix.
^XTime increases linearly in the length of the file
^Xand in the square root of the key length.
^X.SH "SPACE CONSIDERATIONS"
^XEncrypted files increase in length by about 1%.
^X.SH FILES
^X/usr/bin/hill			script for pre/postprocessing
^X.br
^X/usr/bin/hill0			actual encryption program
^X.br
^XThese two files can be installed anywhere on the search path.
^X.SH "MS-DOS VERSION"
^XThe MS-DOS version of
^X.I hill
^Xhas the same capabilities,
^Xexcept that only the
^X.B \-e
^Xand 
^X.B \-d
^Xoptions are supported.
^X.SH "SEE ALSO"
^X.IR pack (1),
^X.IR compact (1),
^X.IR compress (1) 
SHAR_EOF
fi # end of overwriting check
if test -f 'hill0.c'
then
	echo shar: will not over-write existing file "'hill0.c'"
else
sed 's/^X//' << \SHAR_EOF > 'hill0.c'
^X# include <stdio.h>
^X# include "table.i"
^X# ifdef DOS
^X# include <fcntl.h>
^X# include <io.h>
^X# endif
^X
^X# ifdef DOS
^X# define TTY "con"
^X# else
^X# define TTY "/dev/tty"
^X# endif
^X
^X# define Over(x) for (x = 0; x < order; x++)
^X# define Times(a,b) ((long)(a) * (long)(b) % 257)
^X
^Xint mode;
^X
^Xchar key[256];
^Xint matkey[16][16];
^Xint invec[16];
^Xint outvec[16];
^Xint order;
^X
^X
^Xsetup(argc, argv)
^Xint argc; char **argv;
^X	{
^X	FILE *tty;
^X
^X	if (strcmp(argv[1], "-e") == 0)
^X		mode = 'e';
^X	else if (strcmp(argv[1], "-d") == 0)
^X		mode = 'd';
^X	else {
^X		fprintf(stderr, "usage: hill -e [key]\n   or: hill -d [key]\n");
^X		exit(1);
^X		}
^X	if (argc > 2)
^X		strcpy(key, argv[2]);
^X	else {
^X		tty = fopen(TTY, "r+");
^X		setbuf(tty, NULL);
^X		fprintf(tty, "Key? ");
^X		fgets(key, sizeof(key), tty);
^X		key[strlen(key) - 1] = 0;
^X		fclose(tty);
^X		}
^X	}
^X
^Xmakemat()
^X	{
^X	int i, j, k;
^X	int n = 0;
^X	FILE *tty;
^X
^X	setorder();
^X	Over(i) Over(j)
^X		matkey[i][j] = key[n++];
^X	for (i = 0; i < strlen(key); i++)
^X		key[i] = 0;
^X	square();
^X	while ((k = invert()) != EOF)
^X		matkey[k][k] = (matkey[k][k] + 1) % 257;
^X	}
^X
^Xsetorder()
^X	{
^X	int n = strlen(key);
^X
^X	for (order = 0; order < 17; order++)
^X		if (order*order > n) break;
^X	order--;
^X	if (order < 3) {
^X		fprintf(stderr, "key size < 9\n");
^X		exit(1);
^X		}
^X	}
^X
^Xsquare()
^X	{
^X	int result[16][16];
^X	int i, j, k;
^X
^X	Over(i) Over(j)
^X		result[i][j] = 0;
^X	Over(i) Over(j) Over(k)
^X		result[i][j] += Times(matkey[i][k], matkey[k][j]);
^X	Over(i) Over(j)
^X		matkey[i][j] = result[i][j] % 257;
^X	}
^X
^Xint invert()
^X	{
^X	int matrix[16][16];
^X	int inverse[16][16];
^X	int i, j, k;
^X	int t;
^X	int pivot;
^X
^X	Over(i) Over(j) {
^X		matrix[i][j] = matkey[i][j];
^X		inverse[i][j] = 0;
^X		}
^X	Over(k)
^X		inverse[k][k] = 1;
^X
^X	Over(k) {
^X		if (matrix[k][k] == 0) {
^X			for (i = k + 1; i < order; i++)
^X				if (matrix[i][k]) {
^X					Over(j) {
^X						t = matrix[i][j];
^X						matrix[i][j] = matrix[k][j];
^X						matrix[k][j] = t;
^X						t = inverse[i][j];
^X						inverse[i][j] = inverse[k][j];
^X						inverse[k][j] = t;
^X						}
^X					break;
^X					}
^X			if (i == order) return(k);
^X			}
^X
^X		pivot = inverses[matrix[k][k]];
^X		Over(j) {
^X			matrix[k][j] = Times(matrix[k][j], pivot);
^X			inverse[k][j] = Times(inverse[k][j], pivot);
^X			}
^X		Over(i) if (i != k) {
^X			pivot = matrix[i][k];
^X			Over(j) {
^X				matrix[i][j] -= Times(pivot, matrix[k][j]);
^X				if (matrix[i][j] < 0) matrix[i][j] += 257;
^X				inverse[i][j] -= Times(pivot, inverse[k][j]);
^X				if (inverse[i][j] < 0) inverse[i][j] += 257;
^X				}
^X			}
^X		}
^X
^X	if (mode == 'd') Over(i) Over(j)
^X		matkey[i][j] = inverse[i][j];
^X	return(EOF);
^X	}
^X
^X
^Xint getvec()
^X	{
^X	int i;
^X	int padf = 0;
^X
^X	Over(i)
^X		if ((invec[i] = getchar()) == EOF) {
^X			if (i == 0) return(0);
^X			else if (padf) invec[i] = rand() % 257;
^X			else { invec[i] = 256; padf++; }
^X			}
^X		else if (invec[i] == 255 && mode == 'd')
^X			invec[i] += getchar();
^X	return(i);
^X	}
^X
^Xputvec()
^X	{
^X	int j;
^X
^X	Over(j)
^X		switch(outvec[j]) {
^X		case 256:
^X			if (mode == 'd') return;
^X			else putchar(255), putchar(1);
^X			break;
^X		case 255:
^X			putchar(255);
^X			if (mode == 'e') putchar(0);
^X			break;
^X		default:
^X			putchar(outvec[j]);
^X			}
^X	}
^X
^Xmatmul()
^X	{
^X	int i, j, k;
^X
^X	Over(i) {
^X		outvec[i] = 0;
^X		Over(j)
^X			outvec[i] += Times(invec[j], matkey[i][j]);
^X		outvec[i] %= 257;
^X		}
^X	}
^X
^Xmain(argc, argv)
^Xint argc; char **argv;
^X	{
^X	long tloc;
^X
^X# ifdef DOS
^X;setmode(fileno(stdin), O_BINARY);
^X	setmode(fileno(stdout), O_BINARY);
^X# endif
^X	time(&tloc);
^X	srand((int) tloc);
^X	setup(argc, argv);
^X	makemat();
^X	while(getvec()) {
^X;	matmul();
^X;	putvec();
^X;;}
^X	}
SHAR_EOF
fi # end of overwriting check
if test -f 'kappa.c'
then
	echo shar: will not over-write existing file "'kappa.c'"
else
sed 's/^X//' << \SHAR_EOF > 'kappa.c'
^X/* Kappa: utility program
^X	Prints a table of character frequencies drawn from stdin.
^X;The table appears in natural order.
^X;Frequencies are per 1000 characters.
^X*/
^X
^X# include <stdio.h>
^X
^Xlong table[256];
^Xlong total;
^X
^Xmain()
^X	{
^X;int ch;
^X	int i;
^X	int lcmpr();
^X
^X	while ((ch = getchar()) != EOF) {
^X;;table[ch]++;
^X		total++;
^X		}
^X	printf("Total: %ld\n\n", total);
^X	for (i = 0; i < 256; i++) {
^X;;table[i] *= 1000;
^X		table[i] /= total;
^X		}
^X	for (i = 0; i < 256; i++) {
^X;;printf("%3.3ld ", table[i]);
^X		if ((i + 1) % 16 == 0) putchar('\n');
^X		if ((i + 1) % 128 == 0) putchar('\n');
^X		}
^X	}
SHAR_EOF
fi # end of overwriting check
if test -f 'makefile'
then
	echo shar: will not over-write existing file "'makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'makefile'
^Xall: hill0 hill.exe kappa
^Xhill0: hill0.c table.i
^X	cc -o hill0 hill0.c
^Xhill.exe: hill0.c table.i
^X	cc -DDOS -dos -o hill.exe hill0.c
^Xkappa: kappa.c
^Xinstall: hill hill0
^X	mv hill hill0 /usr/lbin
SHAR_EOF
fi # end of overwriting check
if test -f 'table.i'
then
	echo shar: will not over-write existing file "'table.i'"
else
sed 's/^X//' << \SHAR_EOF > 'table.i'
^Xint inverses[257] = { 0, 1, 129, 86, 193, 103, 43, 147, 225, 200, 180, 187, 
^X150, 178, 202, 120, 241, 121, 100, 230, 90, 49, 222, 190, 75, 72, 89, 238, 101, 
^X195, 60, 199, 249, 148, 189, 235, 50, 132, 115, 145, 45, 163, 153, 6, 111, 40, 
^X95, 175, 166, 21, 36, 126, 173, 97, 119, 243, 179, 248, 226, 61, 30, 59, 228, 
^X102, 253, 87, 74, 234, 223, 149, 246, 181, 25, 169, 66, 24, 186, 247, 201, 244, 
^X151, 165, 210, 96, 205, 127, 3, 65, 184, 26, 20, 209, 176, 152, 216, 46, 83, 
^X53, 139, 135, 18, 28, 63, 5, 215, 164, 177, 245, 188, 224, 250, 44, 218, 116, 
^X124, 38, 113, 134, 159, 54, 15, 17, 158, 140, 114, 220, 51, 85, 255, 2, 172, 
^X206, 37, 143, 117, 99, 240, 242, 203, 98, 123, 144, 219, 133, 141, 39, 213, 7, 
^X33, 69, 12, 80, 93, 42, 252, 194, 229, 239, 122, 118, 204, 174, 211, 41, 105, 
^X81, 48, 237, 231, 73, 192, 254, 130, 52, 161, 47, 92, 106, 13, 56, 10, 71, 233, 
^X191, 88, 232, 76, 11, 108, 34, 23, 183, 170, 4, 155, 29, 198, 227, 196, 31, 9, 
^X78, 14, 138, 160, 84, 131, 221, 236, 91, 82, 162, 217, 146, 251, 104, 94, 212, 
^X112, 142, 125, 207, 22, 68, 109, 8, 58, 197, 62, 156, 19, 168, 185, 182, 67, 
^X35, 208, 167, 27, 157, 136, 16, 137, 55, 79, 107, 70, 77, 57, 32, 110, 214, 
^X154, 64, 171, 128, 256};
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0

-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.