blob: 1715288ba6559453416f39f6bf47af3bac700c35 [file] [log] [blame]
/*
*
* 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;
/*****************************************************************************/
main(agc, agv)
int agc;
char *agv[];
{
/*
*
* Implementation of the encryption/decryption used by eexec and show.
*
*/
argc = agc;
argv = agv;
fp_in = stdin;
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 */
/*****************************************************************************/