2 Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
4 See the accompanying file LICENSE, version 2000-Apr-09 or later
5 (the contents of which are also included in zip.h) for terms of use.
6 If, for some reason, all these files are missing, the Info-ZIP license
7 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
10 crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h]
12 This encryption/decryption source code for Info-Zip software was
13 originally written in Europe. The whole source package can be
14 freely distributed, including from the USA. (Prior to January 2000,
15 re-export from the US was a violation of US law.)
17 NOTE on copyright history:
18 Previous versions of this source package (up to version 2.8) were
19 not copyrighted and put in the public domain. If you cannot comply
20 with the Info-Zip LICENSE, you may want to look for one of those
21 public domain versions.
25 This encryption code is a direct transcription of the algorithm from
26 Roger Schlafly, described by Phil Katz in the file appnote.txt. This
27 file (appnote.txt) is distributed with the PKZIP program (even in the
28 version without encryption capabilities).
31 #define ZCRYPT_INTERNAL
43 /* For the encoding task used in Zip (and ZipCloak), we want to initialize
44 the crypt algorithm with some reasonably unpredictable bytes, see
45 the crypthead() function. The standard rand() library function is
46 used to supply these `random' bytes, which in turn is initialized by
47 a srand() call. The srand() function takes an "unsigned" (at least 16bit)
48 seed value as argument to determine the starting point of the rand()
49 pseudo-random number generator.
50 This seed number is constructed as "Seed = Seed1 .XOR. Seed2" with
51 Seed1 supplied by the current time (= "(unsigned)time()") and Seed2
52 as some (hopefully) nondeterministic bitmask. On many (most) systems,
53 we use some "process specific" number, as the PID or something similar,
54 but when nothing unpredictable is available, a fixed number may be
57 1.) This implementation requires the availability of the following
58 standard UNIX C runtime library functions: time(), rand(), srand().
59 On systems where some of them are missing, the environment that
60 incorporates the crypt routines must supply suitable replacement
62 2.) It is a very bad idea to use a second call to time() to set the
63 "Seed2" number! In this case, both "Seed1" and "Seed2" would be
64 (almost) identical, resulting in a (mostly) "zero" constant seed
65 number passed to srand().
67 The implementation environment defined in the "zip.h" header should
68 supply a reasonable definition for ZCR_SEED2 (an unsigned number; for
69 most implementations of rand() and srand(), only the lower 16 bits are
70 significant!). An example that works on many systems would be
71 "#define ZCR_SEED2 (unsigned)getpid()".
72 The default definition for ZCR_SEED2 supplied below should be regarded
73 as a fallback to allow successful compilation in "beta state"
76 # include <time.h> /* time() function supplies first part of crypt seed */
77 /* "last resort" source for second part of crypt seed pattern */
79 # define ZCR_SEED2 (unsigned)3141592654L /* use PI as default pattern */
81 # ifdef GLOBAL /* used in Amiga system headers, maybe others too */
86 # define GLOBAL(g) G.g
91 /* char *key = (char *)NULL; moved to globals.h */
93 local
int testp
OF((__GPRO__ ZCONST uch
*h
));
94 local
int testkey
OF((__GPRO__ ZCONST uch
*h
, ZCONST
char *key
));
98 #ifndef UNZIP /* moved to globals.h for UnZip */
99 local ulg keys
[3]; /* keys defining the pseudo-random sequence */
104 # define Trace(x) fprintf x
111 # define CRC_32_TAB crc_32_tab
114 #define CRC32(c, b) (CRC_32_TAB[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
116 /***********************************************************************
117 * Return the next byte in the pseudo-random sequence
119 int decrypt_byte(__G
)
122 unsigned temp
; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
123 * unpredictable manner on 16-bit systems; not a problem
124 * with any known compiler so far, though */
126 temp
= ((unsigned)GLOBAL(keys
[2]) & 0xffff) | 2;
127 return (int)(((temp
* (temp
^ 1)) >> 8) & 0xff);
130 /***********************************************************************
131 * Update the encryption keys with the next byte of plain text
133 int update_keys(__G__ c
)
135 int c
; /* byte of plain text */
137 GLOBAL(keys
[0]) = CRC32(GLOBAL(keys
[0]), c
);
138 GLOBAL(keys
[1]) += GLOBAL(keys
[0]) & 0xff;
139 GLOBAL(keys
[1]) = GLOBAL(keys
[1]) * 134775813L + 1;
141 register int keyshift
= (int)(GLOBAL(keys
[1]) >> 24);
142 GLOBAL(keys
[2]) = CRC32(GLOBAL(keys
[2]), keyshift
);
148 /***********************************************************************
149 * Initialize the encryption keys and the random header according to
150 * the given password.
152 void init_keys(__G__ passwd
)
154 ZCONST
char *passwd
; /* password string with which to modify keys */
156 GLOBAL(keys
[0]) = 305419896L;
157 GLOBAL(keys
[1]) = 591751049L;
158 GLOBAL(keys
[2]) = 878082192L;
159 while (*passwd
!= '\0') {
160 update_keys(__G__ (int)*passwd
);
168 /***********************************************************************
169 * Write encryption header to file zfile using the password passwd
170 * and the cyclic redundancy check crc.
172 void crypthead(passwd
, crc
, zfile
)
173 ZCONST
char *passwd
; /* password string */
174 ulg crc
; /* crc of file being encrypted */
175 FILE *zfile
; /* where to write header */
177 int n
; /* index in random header */
178 int t
; /* temporary */
179 int c
; /* random byte */
180 int ztemp
; /* temporary for zencoded value */
181 uch header
[RAND_HEAD_LEN
-2]; /* random header */
182 static unsigned calls
= 0; /* ensure different random header each time */
184 /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
185 * output of rand() to get less predictability, since rand() is
186 * often poorly implemented.
189 srand((unsigned)time(NULL
) ^ ZCR_SEED2
);
192 for (n
= 0; n
< RAND_HEAD_LEN
-2; n
++) {
193 c
= (rand() >> 7) & 0xff;
194 header
[n
] = (uch
)zencode(c
, t
);
196 /* Encrypt random header (last two bytes is high word of crc) */
198 for (n
= 0; n
< RAND_HEAD_LEN
-2; n
++) {
199 ztemp
= zencode(header
[n
], t
);
202 ztemp
= zencode((int)(crc
>> 16) & 0xff, t
);
204 ztemp
= zencode((int)(crc
>> 24) & 0xff, t
);
211 /***********************************************************************
212 * Encrypt the zip entry described by z from file source to file dest
213 * using the password passwd. Return an error code in the ZE_ class.
215 int zipcloak(z
, source
, dest
, passwd
)
216 struct zlist far
*z
; /* zip entry to encrypt */
217 FILE *source
, *dest
; /* source and destination files */
218 ZCONST
char *passwd
; /* password string */
220 int c
; /* input byte */
221 int res
; /* result code */
222 ulg n
; /* holds offset and counts size */
223 ush flag
; /* previous flags */
224 int t
; /* temporary */
225 int ztemp
; /* temporary storage for zencode value */
227 /* Set encrypted bit, clear extended local header bit and write local
228 header to output file */
229 if ((n
= (ulg
)ftell(dest
)) == (ulg
)-1L) return ZE_TEMP
;
232 z
->flg
|= 1, z
->flg
&= ~8;
233 z
->lflg
|= 1, z
->lflg
&= ~8;
234 z
->siz
+= RAND_HEAD_LEN
;
235 if ((res
= putlocal(z
, dest
)) != ZE_OK
) return res
;
237 /* Initialize keys with password and write random header */
238 crypthead(passwd
, z
->crc
, dest
);
240 /* Skip local header in input file */
241 if (fseek(source
, (long)(4 + LOCHEAD
+ (ulg
)z
->nam
+ (ulg
)z
->ext
),
243 return ferror(source
) ? ZE_READ
: ZE_EOF
;
247 for (n
= z
->siz
- RAND_HEAD_LEN
; n
; n
--) {
248 if ((c
= getc(source
)) == EOF
) {
249 return ferror(source
) ? ZE_READ
: ZE_EOF
;
251 ztemp
= zencode(c
, t
);
254 /* Skip extended local header in input file if there is one */
255 if ((flag
& 8) != 0 && fseek(source
, 16L, SEEK_CUR
)) {
256 return ferror(source
) ? ZE_READ
: ZE_EOF
;
258 if (fflush(dest
) == EOF
) return ZE_TEMP
;
262 /***********************************************************************
263 * Decrypt the zip entry described by z from file source to file dest
264 * using the password passwd. Return an error code in the ZE_ class.
266 int zipbare(z
, source
, dest
, passwd
)
267 struct zlist far
*z
; /* zip entry to encrypt */
268 FILE *source
, *dest
; /* source and destination files */
269 ZCONST
char *passwd
; /* password string */
271 int c0
, c1
; /* last two input bytes */
272 ulg offset
; /* used for file offsets */
273 ulg size
; /* size of input data */
274 int r
; /* size of encryption header */
275 int res
; /* return code */
276 ush flag
; /* previous flags */
278 /* Save position and skip local header in input file */
279 if ((offset
= (ulg
)ftell(source
)) == (ulg
)-1L ||
280 fseek(source
, (long)(4 + LOCHEAD
+ (ulg
)z
->nam
+ (ulg
)z
->ext
),
282 return ferror(source
) ? ZE_READ
: ZE_EOF
;
284 /* Initialize keys with password */
287 /* Decrypt encryption header, save last two bytes */
289 for (r
= RAND_HEAD_LEN
; r
; r
--) {
291 if ((c1
= getc(source
)) == EOF
) {
292 return ferror(source
) ? ZE_READ
: ZE_EOF
;
294 Trace((stdout
, " (%02x)", c1
));
296 Trace((stdout
, " %02x", c1
));
298 Trace((stdout
, "\n"));
300 /* If last two bytes of header don't match crc (or file time in the
301 * case of an extended local header), back up and just copy. For
302 * pkzip 2.0, the check has been reduced to one byte only.
305 if ((ush
)(c0
| (c1
<<8)) !=
306 (z
->flg
& 8 ? (ush
) z
->tim
& 0xffff : (ush
)(z
->crc
>> 16))) {
308 c0
++; /* avoid warning on unused variable */
309 if ((ush
)c1
!= (z
->flg
& 8 ? (ush
) z
->tim
>> 8 : (ush
)(z
->crc
>> 24))) {
311 if (fseek(source
, offset
, SEEK_SET
)) {
312 return ferror(source
) ? ZE_READ
: ZE_EOF
;
314 if ((res
= zipcopy(z
, source
, dest
)) != ZE_OK
) return res
;
318 /* Clear encrypted bit and local header bit, and write local header to
320 if ((offset
= (ulg
)ftell(dest
)) == (ulg
)-1L) return ZE_TEMP
;
325 z
->siz
-= RAND_HEAD_LEN
;
326 if ((res
= putlocal(z
, dest
)) != ZE_OK
) return res
;
329 for (size
= z
->siz
; size
; size
--) {
330 if ((c1
= getc(source
)) == EOF
) {
331 return ferror(source
) ? ZE_READ
: ZE_EOF
;
336 /* Skip extended local header in input file if there is one */
337 if ((flag
& 8) != 0 && fseek(source
, 16L, SEEK_CUR
)) {
338 return ferror(source
) ? ZE_READ
: ZE_EOF
;
340 if (fflush(dest
) == EOF
) return ZE_TEMP
;
348 /***********************************************************************
349 * If requested, encrypt the data in buf, and in any case call fwrite()
350 * with the arguments to zfwrite(). Return what fwrite() returns.
352 unsigned zfwrite(buf
, item_size
, nb
, f
)
353 zvoid
*buf
; /* data buffer */
354 extent item_size
; /* size of each item in bytes */
355 extent nb
; /* number of items */
356 FILE *f
; /* file to write to */
358 int t
; /* temporary */
360 if (key
!= (char *)NULL
) { /* key is the global password pointer */
361 ulg size
; /* buffer size */
362 char *p
= (char*)buf
; /* steps through buffer */
364 /* Encrypt data in buffer */
365 for (size
= item_size
*(ulg
)nb
; size
!= 0; p
++, size
--) {
366 *p
= (char)zencode(*p
, t
);
369 /* Write the buffer out */
370 return fwrite(buf
, item_size
, nb
, f
);
377 #if (defined(UNZIP) && !defined(FUNZIP))
379 /***********************************************************************
380 * Get the password and set up keys for current zipfile member.
381 * Return PK_ class error.
383 int decrypt(__G__ passwrd
)
385 ZCONST
char *passwrd
;
389 uch h
[RAND_HEAD_LEN
];
391 Trace((stdout
, "\n[incnt = %d]: ", GLOBAL(incnt
)));
393 /* get header once (turn off "encrypted" flag temporarily so we don't
394 * try to decrypt the same data twice) */
395 GLOBAL(pInfo
->encrypted
) = FALSE
;
396 defer_leftover_input(__G
);
397 for (n
= 0; n
< RAND_HEAD_LEN
; n
++) {
400 Trace((stdout
, " (%02x)", h
[n
]));
403 GLOBAL(pInfo
->encrypted
) = TRUE
;
405 if (GLOBAL(newzip
)) { /* this is first encrypted member in this zipfile */
406 GLOBAL(newzip
) = FALSE
;
407 if (passwrd
!= (char *)NULL
) { /* user gave password on command line */
409 if ((GLOBAL(key
) = (char *)malloc(strlen(passwrd
)+1)) ==
412 strcpy(GLOBAL(key
), passwrd
);
413 GLOBAL(nopwd
) = TRUE
; /* inhibit password prompting! */
415 } else if (GLOBAL(key
)) { /* get rid of previous zipfile's key */
417 GLOBAL(key
) = (char *)NULL
;
421 /* if have key already, test it; else allocate memory for it */
424 return PK_COOL
; /* existing password OK (else prompt for new) */
425 else if (GLOBAL(nopwd
))
426 return PK_WARN
; /* user indicated no more prompting */
427 } else if ((GLOBAL(key
) = (char *)malloc(IZ_PWLEN
+1)) == (char *)NULL
)
433 r
= (*G
.decr_passwd
)((zvoid
*)&G
, &n
, GLOBAL(key
), IZ_PWLEN
+1,
434 GLOBAL(zipfn
), GLOBAL(filename
));
435 if (r
== IZ_PW_ERROR
) { /* internal error in fetch of PW */
440 if (r
!= IZ_PW_ENTERED
) { /* user replied "skip" or "skip all" */
441 *GLOBAL(key
) = '\0'; /* We try the NIL password, ... */
442 n
= 0; /* and cancel fetch for this item. */
446 if (r
== IZ_PW_CANCELALL
) /* User replied "Skip all" */
447 GLOBAL(nopwd
) = TRUE
; /* inhibit any further PW prompt! */
452 } /* end function decrypt() */
456 /***********************************************************************
457 * Test the password. Return -1 if bad, 0 if OK.
459 local
int testp(__G__ h
)
464 char *key_translated
;
466 /* On systems with "obscure" native character coding (e.g., EBCDIC),
467 * the first test translates the password to the "main standard"
468 * character coding. */
471 /* allocate buffer for translated password */
472 if ((key_translated
= malloc(strlen(GLOBAL(key
)) + 1)) == (char *)NULL
)
474 /* first try, test password translated "standard" charset */
475 r
= testkey(__G__ h
, STR_TO_CP1(key_translated
, GLOBAL(key
)));
476 #else /* !STR_TO_CP1 */
477 /* first try, test password as supplied on the extractor's host */
478 r
= testkey(__G__ h
, GLOBAL(key
));
479 #endif /* ?STR_TO_CP1 */
484 /* now prepare for second (and maybe third) test with translated pwd */
485 if ((key_translated
= malloc(strlen(GLOBAL(key
)) + 1)) == (char *)NULL
)
488 /* second try, password translated to alternate ("standard") charset */
489 r
= testkey(__G__ h
, STR_TO_CP2(key_translated
, GLOBAL(key
)));
492 /* third try, password translated to another "standard" charset */
493 r
= testkey(__G__ h
, STR_TO_CP3(key_translated
, GLOBAL(key
)));
496 free(key_translated
);
499 #endif /* STR_TO_CP2 */
502 free(key_translated
);
504 /* last resort, test password as supplied on the extractor's host */
505 r
= testkey(__G__ h
, GLOBAL(key
));
507 #endif /* STR_TO_CP1 */
511 } /* end function testp() */
514 local
int testkey(__G__ h
, key
)
516 ZCONST uch
*h
; /* decrypted header */
517 ZCONST
char *key
; /* decryption password to test */
525 uch hh
[RAND_HEAD_LEN
]; /* decrypted header */
527 /* set keys and save the encrypted header */
528 init_keys(__G__ key
);
529 memcpy(hh
, h
, RAND_HEAD_LEN
);
532 for (n
= 0; n
< RAND_HEAD_LEN
; n
++) {
534 Trace((stdout
, " %02x", hh
[n
]));
538 "\n lrec.crc= %08lx crec.crc= %08lx pInfo->ExtLocHdr= %s\n",
539 GLOBAL(lrec
.crc32
), GLOBAL(pInfo
->crc
),
540 GLOBAL(pInfo
->ExtLocHdr
) ? "true":"false"));
541 Trace((stdout
, " incnt = %d unzip offset into zipfile = %ld\n",
543 GLOBAL(cur_zipfile_bufstart
)+(GLOBAL(inptr
)-GLOBAL(inbuf
))));
545 /* same test as in zipbare(): */
547 #ifdef ZIP10 /* check two bytes */
548 c
= hh
[RAND_HEAD_LEN
-2], b
= hh
[RAND_HEAD_LEN
-1];
550 " (c | (b<<8)) = %04x (crc >> 16) = %04x lrec.time = %04x\n",
551 (ush
)(c
| (b
<<8)), (ush
)(GLOBAL(lrec
.crc32
) >> 16),
552 ((ush
)GLOBAL(lrec
.last_mod_dos_datetime
) & 0xffff))));
553 if ((ush
)(c
| (b
<<8)) != (GLOBAL(pInfo
->ExtLocHdr
) ?
554 ((ush
)GLOBAL(lrec
.last_mod_dos_datetime
) & 0xffff) :
555 (ush
)(GLOBAL(lrec
.crc32
) >> 16)))
558 b
= hh
[RAND_HEAD_LEN
-1];
559 Trace((stdout
, " b = %02x (crc >> 24) = %02x (lrec.time >> 8) = %02x\n",
560 b
, (ush
)(GLOBAL(lrec
.crc32
) >> 24),
561 ((ush
)GLOBAL(lrec
.last_mod_dos_datetime
) >> 8) & 0xff));
562 if (b
!= (GLOBAL(pInfo
->ExtLocHdr
) ?
563 ((ush
)GLOBAL(lrec
.last_mod_dos_datetime
) >> 8) & 0xff :
564 (ush
)(GLOBAL(lrec
.crc32
) >> 24)))
567 /* password OK: decrypt current buffer contents before leaving */
568 for (n
= (long)GLOBAL(incnt
) > GLOBAL(csize
) ?
569 (int)GLOBAL(csize
) : GLOBAL(incnt
),
570 p
= GLOBAL(inptr
); n
--; p
++)
574 } /* end function testkey() */
576 #endif /* UNZIP && !FUNZIP */
580 /* something "externally visible" to shut up compiler/linker warnings */