ref: 98c39c15996ffa0febc25c48dcfdd44e60a02643
dir: /sys/src/cmd/postscript/misc/pscrypt.c/
/*
 *
 * Adobe's encryption/decryption algorithm for eexec and show. Runs in
 * eexec mode unless told otherwise. Use,
 *
 *		pscrypt file.cypher > file.clear
 *
 * to decrypt eexec input. Assumes file.cypher is hex with the key as the
 * first four bytes, and writes file.clear as binary (omitting the key).
 * Use
 *
 *		pscrypt -e12ab34ef file.clear >file.cypher
 *
 * to encrypt file.clear (for eexec) using 12ab34ef as the key. Input is
 * binary and output is hex. The key must be given as a hex number. Use
 * -sshow to encrypt or decrypt a CharString or Subr,
 *
 *		pscrypt -sshow file.cypher > file.clear
 *
 * Use -b or -x to read binary or hex input, and -B or -X to output binary
 * or hex.
 *
 */
#include <stdio.h>
#include <ctype.h>
#define ENCRYPT		0
#define DECRYPT		1
#define NOTSET		-1
#define BINARY		0
#define HEX		1
#define LINELENGTH	40
#define CHARSTRING	4330
#define EEXEC		55665
#define MAGIC1		52845
#define MAGIC2		22719
int	argc;
char	**argv;
int	mode = DECRYPT;
int	input = NOTSET;
int	output = NOTSET;
int	outoffset = NOTSET;
int	inoffset = NOTSET;
int	cryptkey = 0;			/* encryption key set with -e */
int	linelength = LINELENGTH;	/* only for hex output */
int	lastchar = 0;
unsigned long	seed = EEXEC;
unsigned long	key;
FILE	*fp_in = stdin;
/*****************************************************************************/
main(agc, agv)
    int		agc;
    char	*agv[];
{
/*
 *
 * Implementation of the encryption/decryption used by eexec and show.
 *
 */
    argc = agc;
    argv = agv;
    options();
    initialize();
    arguments();
    exit(0);
}   /* End of main */
/*****************************************************************************/
options()
{
    int		ch;
    char	*names = "bde:l:os:xBSX";
    extern char	*optarg;
    extern int	optind;
/*
 *
 * Command line options.
 *
 */
    while ( (ch = getopt(argc, argv, names)) != EOF )
	switch ( ch ) {
	    case 'b':			/* binary input */
		    input = BINARY;
		    break;
	    case 'd':			/* decrypt */
		    mode = DECRYPT;
		    break;
	    case 'e':			/* encrypt */
		    mode = ENCRYPT;
		    if ( *optarg == '0' && *optarg == 'x' )
			optarg += 2;
		    sscanf(optarg, "%8x", &cryptkey);
		    break;
	    case 'l':			/* line length hex output */
		    linelength = atoi(optarg);
		    break;
	    case 'o':			/* output all bytes - debugging */
		    outoffset = 0;
		    break;
	    case 's':			/* seed */
		    if ( *optarg == 'e' )
			seed = EEXEC;
		    else if ( *optarg == 's' )
			seed = CHARSTRING;
		    else if ( *optarg == '0' && *(optarg+1) == 'x' )
			sscanf(optarg+2, "%x", &seed);
		    else if ( *optarg == '0' )
			sscanf(optarg, "%o", &seed);
		    else sscanf(optarg, "%d", &seed);
		    break;
	    case 'x':			/* hex input */
		    input = HEX;
		    break;
	    case 'B':			/* binary output */
		    output = BINARY;
		    break;
	    case 'X':			/* hex output */
		    output = HEX;
		    break;
	    case '?':			/* don't understand the option */
		    fprintf(stderr, "bad option -%c\n", ch);
		    exit(1);
		    break;
	    default:			/* don't know what to do for ch */
		    fprintf(stderr, "missing case for option -%c\n", ch);
		    exit(1);
		    break;
	}   /* End switch */
    argc -= optind;			/* get ready for non-option args */
    argv += optind;
}   /* End of options */
/*****************************************************************************/
initialize()
{
/*
 *
 * Initialization that has to be done after the options.
 *
 */
    key = seed;
    if ( mode == DECRYPT ) {
	input = (input == NOTSET) ? HEX : input;
	output = (output == NOTSET) ? BINARY : output;
	inoffset = (inoffset == NOTSET) ? 0 : inoffset;
	outoffset = (outoffset == NOTSET) ? -4 : outoffset;
    } else {
	input = (input == NOTSET) ? BINARY : input;
	output = (output == NOTSET) ? HEX : output;
	inoffset = (inoffset == NOTSET) ? 4 : inoffset;
	outoffset = (outoffset == NOTSET) ? 0 : outoffset;
    }	/* End else */
    if ( linelength <= 0 )
	linelength = LINELENGTH;
}   /* End of initialize */
/*****************************************************************************/
arguments()
{
/*
 *
 * Everything left is an input file. No arguments or '-' means stdin.
 *
 */
    if ( argc < 1 )
	crypt();
    else
	while ( argc > 0 ) {
	    if ( strcmp(*argv, "-") == 0 )
		fp_in = stdin;
	    else if ( (fp_in = fopen(*argv, "r")) == NULL ) {
		fprintf(stderr, "can't open %s\n", *argv);
		exit(1);
	    }	/* End if */
	    crypt();
	    if ( fp_in != stdin )
		fclose(fp_in);
	    argc--;
	    argv++;
	}   /* End while */
}   /* End of arguments */
/*****************************************************************************/
crypt()
{
    unsigned int	cypher;
    unsigned int	clear;
/*
 *
 * Runs the encryption/decryption algorithm.
 *
 */
    while ( lastchar != EOF ) {
	cypher = nextbyte();
	clear = ((key >> 8) ^ cypher) & 0xFF;
	key = (key + (mode == DECRYPT ? cypher : clear)) * MAGIC1 + MAGIC2;
	if ( ++outoffset > 0 && lastchar != EOF ) {
	    if ( output == HEX ) {
		printf("%.2X", clear);
		if ( linelength > 0 && (outoffset % linelength) == 0 )
		    putchar('\n');
	    } else putchar(clear);
	}   /* End if */
    }	/* End while */
}   /* End of crypt */
/*****************************************************************************/
nextbyte()
{
    int		val = EOF;
/*
 *
 * Returns the next byte. Uses cryptkey (i.e. what followed -e) while inoffset is
 * positive, otherwise reads (hex or binary) from fp_in.
 *
 */
    if ( inoffset-- > 0 )
	val = (cryptkey >> (inoffset*8)) & 0xFF;
    else if ( input == HEX ) {
	if ( (val = nexthexchar()) != EOF )
	    val = (val << 4) | nexthexchar();
    } else if ( input == BINARY )
	val = Getc(fp_in);
    return(val);
}   /* End of nextbyte */
/*****************************************************************************/
nexthexchar()
{
    int		ch;
/*
 *
 * Reads the next hex character.
 *
 */
    while ( (ch = Getc(fp_in)) != EOF && ! isxdigit(ch) ) ;
    if ( isdigit(ch) )
	ch -= '0';
    else if ( isupper(ch) )
	ch -= 'A' - 10;
    else if ( islower(ch) )
	ch -= 'a' - 10;
    return(ch);
}   /* End of nexthexchar */
/*****************************************************************************/
Getc(fp)
    FILE	*fp;
{
/*
 *
 * Reads the next byte from *fp, sets lastchar, and returns the character.
 *
 */
    return(lastchar = getc(fp));
}   /* End of Getc */
/*****************************************************************************/