Blob


1 /*
2 *
3 * Adobe's encryption/decryption algorithm for eexec and show. Runs in
4 * eexec mode unless told otherwise. Use,
5 *
6 * pscrypt file.cypher > file.clear
7 *
8 * to decrypt eexec input. Assumes file.cypher is hex with the key as the
9 * first four bytes, and writes file.clear as binary (omitting the key).
10 * Use
11 *
12 * pscrypt -e12ab34ef file.clear >file.cypher
13 *
14 * to encrypt file.clear (for eexec) using 12ab34ef as the key. Input is
15 * binary and output is hex. The key must be given as a hex number. Use
16 * -sshow to encrypt or decrypt a CharString or Subr,
17 *
18 * pscrypt -sshow file.cypher > file.clear
19 *
20 * Use -b or -x to read binary or hex input, and -B or -X to output binary
21 * or hex.
22 *
23 */
25 #include <stdio.h>
26 #include <ctype.h>
28 #define ENCRYPT 0
29 #define DECRYPT 1
31 #define NOTSET -1
32 #define BINARY 0
33 #define HEX 1
34 #define LINELENGTH 40
36 #define CHARSTRING 4330
37 #define EEXEC 55665
38 #define MAGIC1 52845
39 #define MAGIC2 22719
41 int argc;
42 char **argv;
44 int mode = DECRYPT;
45 int input = NOTSET;
46 int output = NOTSET;
47 int outoffset = NOTSET;
48 int inoffset = NOTSET;
50 int cryptkey = 0; /* encryption key set with -e */
51 int linelength = LINELENGTH; /* only for hex output */
52 int lastchar = 0;
54 unsigned long seed = EEXEC;
55 unsigned long key;
57 FILE *fp_in;
59 /*****************************************************************************/
61 main(agc, agv)
63 int agc;
64 char *agv[];
66 {
68 /*
69 *
70 * Implementation of the encryption/decryption used by eexec and show.
71 *
72 */
74 argc = agc;
75 argv = agv;
77 fp_in = stdin;
79 options();
80 initialize();
81 arguments();
83 exit(0);
85 } /* End of main */
87 /*****************************************************************************/
89 options()
91 {
93 int ch;
94 char *names = "bde:l:os:xBSX";
96 extern char *optarg;
97 extern int optind;
99 /*
101 * Command line options.
103 */
105 while ( (ch = getopt(argc, argv, names)) != EOF )
106 switch ( ch ) {
107 case 'b': /* binary input */
108 input = BINARY;
109 break;
111 case 'd': /* decrypt */
112 mode = DECRYPT;
113 break;
115 case 'e': /* encrypt */
116 mode = ENCRYPT;
117 if ( *optarg == '0' && *optarg == 'x' )
118 optarg += 2;
119 sscanf(optarg, "%8x", &cryptkey);
120 break;
122 case 'l': /* line length hex output */
123 linelength = atoi(optarg);
124 break;
126 case 'o': /* output all bytes - debugging */
127 outoffset = 0;
128 break;
130 case 's': /* seed */
131 if ( *optarg == 'e' )
132 seed = EEXEC;
133 else if ( *optarg == 's' )
134 seed = CHARSTRING;
135 else if ( *optarg == '0' && *(optarg+1) == 'x' )
136 sscanf(optarg+2, "%x", &seed);
137 else if ( *optarg == '0' )
138 sscanf(optarg, "%o", &seed);
139 else sscanf(optarg, "%d", &seed);
140 break;
142 case 'x': /* hex input */
143 input = HEX;
144 break;
146 case 'B': /* binary output */
147 output = BINARY;
148 break;
150 case 'X': /* hex output */
151 output = HEX;
152 break;
154 case '?': /* don't understand the option */
155 fprintf(stderr, "bad option -%c\n", ch);
156 exit(1);
157 break;
159 default: /* don't know what to do for ch */
160 fprintf(stderr, "missing case for option -%c\n", ch);
161 exit(1);
162 break;
163 } /* End switch */
165 argc -= optind; /* get ready for non-option args */
166 argv += optind;
168 } /* End of options */
170 /*****************************************************************************/
172 initialize()
176 /*
178 * Initialization that has to be done after the options.
180 */
182 key = seed;
184 if ( mode == DECRYPT ) {
185 input = (input == NOTSET) ? HEX : input;
186 output = (output == NOTSET) ? BINARY : output;
187 inoffset = (inoffset == NOTSET) ? 0 : inoffset;
188 outoffset = (outoffset == NOTSET) ? -4 : outoffset;
189 } else {
190 input = (input == NOTSET) ? BINARY : input;
191 output = (output == NOTSET) ? HEX : output;
192 inoffset = (inoffset == NOTSET) ? 4 : inoffset;
193 outoffset = (outoffset == NOTSET) ? 0 : outoffset;
194 } /* End else */
196 if ( linelength <= 0 )
197 linelength = LINELENGTH;
199 } /* End of initialize */
201 /*****************************************************************************/
203 arguments()
207 /*
209 * Everything left is an input file. No arguments or '-' means stdin.
211 */
213 if ( argc < 1 )
214 crypt();
215 else
216 while ( argc > 0 ) {
217 if ( strcmp(*argv, "-") == 0 )
218 fp_in = stdin;
219 else if ( (fp_in = fopen(*argv, "r")) == NULL ) {
220 fprintf(stderr, "can't open %s\n", *argv);
221 exit(1);
222 } /* End if */
223 crypt();
224 if ( fp_in != stdin )
225 fclose(fp_in);
226 argc--;
227 argv++;
228 } /* End while */
230 } /* End of arguments */
232 /*****************************************************************************/
234 crypt()
238 unsigned int cypher;
239 unsigned int clear;
241 /*
243 * Runs the encryption/decryption algorithm.
245 */
247 while ( lastchar != EOF ) {
248 cypher = nextbyte();
249 clear = ((key >> 8) ^ cypher) & 0xFF;
250 key = (key + (mode == DECRYPT ? cypher : clear)) * MAGIC1 + MAGIC2;
251 if ( ++outoffset > 0 && lastchar != EOF ) {
252 if ( output == HEX ) {
253 printf("%.2X", clear);
254 if ( linelength > 0 && (outoffset % linelength) == 0 )
255 putchar('\n');
256 } else putchar(clear);
257 } /* End if */
258 } /* End while */
260 } /* End of crypt */
262 /*****************************************************************************/
264 nextbyte()
268 int val = EOF;
270 /*
272 * Returns the next byte. Uses cryptkey (i.e. what followed -e) while inoffset is
273 * positive, otherwise reads (hex or binary) from fp_in.
275 */
277 if ( inoffset-- > 0 )
278 val = (cryptkey >> (inoffset*8)) & 0xFF;
279 else if ( input == HEX ) {
280 if ( (val = nexthexchar()) != EOF )
281 val = (val << 4) | nexthexchar();
282 } else if ( input == BINARY )
283 val = Getc(fp_in);
285 return(val);
287 } /* End of nextbyte */
289 /*****************************************************************************/
291 nexthexchar()
295 int ch;
297 /*
299 * Reads the next hex character.
301 */
303 while ( (ch = Getc(fp_in)) != EOF && ! isxdigit(ch) ) ;
305 if ( isdigit(ch) )
306 ch -= '0';
307 else if ( isupper(ch) )
308 ch -= 'A' - 10;
309 else if ( islower(ch) )
310 ch -= 'a' - 10;
312 return(ch);
314 } /* End of nexthexchar */
316 /*****************************************************************************/
318 Getc(fp)
320 FILE *fp;
324 /*
326 * Reads the next byte from *fp, sets lastchar, and returns the character.
328 */
330 return(lastchar = getc(fp));
332 } /* End of Getc */
334 /*****************************************************************************/