/* * * 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 #include #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 */ /*****************************************************************************/