diff -urpN john-1.7.8-jumbo-5a/src/pkzip.h john-1.7.8-jumbo-5b/src/pkzip.h
--- john-1.7.8-jumbo-5a/src/pkzip.h	2011-08-19 14:54:15.453125000 +0000
+++ john-1.7.8-jumbo-5b/src/pkzip.h	2011-08-19 18:23:38.875000000 +0000
@@ -49,29 +49,27 @@ static const u32 pkz_crc_32_tab[] =
 #define UBUF_SIZE (32*1024)
 #define MAX_PKZ_FILES 8
 typedef struct zip_salt_t {
-	unsigned cnt;			// number of hashes
+	unsigned cnt;				// number of hashes
+	unsigned chk_bytes;			// number of bytes valid in checksum (1 or 2)
+	unsigned flags;				// bit mask, that tells us what data is provided in the hash line, and also can tell us what steps to take or not take.
 	u8 h[MAX_PKZ_FILES][12];	// hash data (up to 8)
-	u8 c[MAX_PKZ_FILES][2];	// the 1 or 2 byte checksums (that match the 1 to 8 hashes)
+	u8 c[MAX_PKZ_FILES][2];		// the 1 or 2 byte checksums (that match the 1 to 8 hashes)
+	unsigned asciilen;			// the length of the asciidat field. This does not tell us how long it decomresses to, but tells us its compressed length.
+	unsigned asciiCompType;		// a 0 or 8  (stored or imploded, the only types we handle.).
 	u8 *asciidat;
 	u8 *ascii_decr;
-	unsigned asciilen;
 	u8 *ascii_ucmp;
 	unsigned ascii_ucmp_len;
-
-	u8 *encrDat;			// Encrypted data from the zip file. May be partial, or may be 'full'.  If an ASCII file, then partial will work.
-//	u8 *decrDat;			// 
-//	u8 *uncomprDat;			// 
-
-	u32 crc32;				// if a 'full' file of encr data, then this is the CRC
-	unsigned compLen;		// length of compressed data (whether part or full)
-	unsigned deCompLen;		// length of decompressed data (if full).
-	unsigned flags;			// 
+	u8 *encrDat;				// Encrypted data from the zip file. May be partial, or may be 'full'.  If an ASCII file, then partial will work.
+	u32 crc32;					// if a 'full' file of encr data, then this is the CRC
+	unsigned compLen;			// length of compressed data (whether part or full)
+	unsigned deCompLen;			// length of decompressed data (if full).
+	unsigned compType;			// the type of compression  0 or 8
 	unsigned offset;
 	char *filename;
 	char *ifilename;
 	u8 *full_encr_dat;
 	u8 *full_decr_dat;
-	unsigned chk_bytes;		// number of bytes valid in checksum (1 or 2)
 } PKZ_SALT;
 
 typedef union MY_WORD {
diff -urpN john-1.7.8-jumbo-5a/src/pkzip_fmt_plug.c john-1.7.8-jumbo-5b/src/pkzip_fmt_plug.c
--- john-1.7.8-jumbo-5a/src/pkzip_fmt_plug.c	2011-08-19 14:54:15.468750000 +0000
+++ john-1.7.8-jumbo-5b/src/pkzip_fmt_plug.c	2011-08-19 20:56:25.125000000 +0000
@@ -37,12 +37,16 @@
 #define SALT_SIZE				(sizeof(PKZ_SALT*))
 
 #define MIN_KEYS_PER_CRYPT		1
-#define MAX_KEYS_PER_CRYPT		64
+#define MAX_KEYS_PER_CRYPT		512
 
 //#define ZIP_DEBUG
 
+// It is likely that this should be put into the arch.h files for the differnt systems,
+// IF we find a system which operates faster doing the non-table work.
+#define PKZIP_USE_MULT_TABLE
+
 // format:  
-//   $pkzip$
+//   $pkzip1$					version 1 of pkzip hashes.
 //   Number of test records*
 //   bytes_of_checksum_valid*	Either 1 or 2 byte validation.  PKZIP > 2 will only use 1.
 //                              Older stuff (and many unixes), validate against both bytes.
@@ -62,10 +66,12 @@
 //                                              More files means a 'correct' checksum is
 //                                              likely to be the right one.
 //    ASCII hash len*   if flags&2
+//    asciiCompType*    if flags&2
 //    ASCII hash data*  if flags&2
 //    CRC32*            if flags&4
 //    Compr_len*        if flags&4
 //    deCompr_len*      if flags&4
+//    compType*         if flags&4       The compression type of the 'whole' blob. 0 or 8
 //    Offset*           Only if flags&8  this is the offset from start of file to the 
 //                                       compressed/encrypted deflated 'blob' of data.
 //    FileName*         if flags&8       the name of the .zip file.  NOTE, that file WILL be
@@ -77,15 +83,26 @@
 //                                       .zip, then the data can be put here inline.
 
 static struct fmt_tests tests[] = {
-	{"$pkzip$1*2*1*c97839b8fe9e0373ba3c7b29ac6f**********", "love"},
-	{"$pkzip$1*1*1*4f83334e87f67a42fce2a53ef967**********", "john"},
-	{"$pkzip$1*1*1*fcf7385e0c4466cd621743a7f967**********", "john"},
-	{"$pkzip$4*2*1*dce4fb16f19b70cf9c368a5c139b*e27bc3e3adb1cc0f227758f38b8d*20f4ad0590ec2b44ff8510266aec*f63277b2a5ea02bcaed067ee71a6**********", "john"},
-	{"$pkzip$1*2*1*20f4ad0590ec2b44ff8510266aec**********", "john"},
-	{"$pkzip$1*2*16*20f4ad0590ec2b44ff8510266aec*38*20f4ad0590ec2b44ff85102650314ec911cc2227bdb0e5ced23ea8517ce4bdc5ec77136e450641fcfe317fd36e069de280f6623e34085186*f967d462*54*49****20F4AD0590EC2B44FF85102650314EC911CC2227BDB0E5CED23EA8517CE4BDC5EC77136E450641FCFE317FD36E069DE280F6623E34085186F3A4FEE45EB6D4C6AABF9B7A5A142D456CF542C1EB35BCAAE120330D*", "john"},
-	{"$pkzip$1*2*2*20f4ad0590ec2b44ff8510266aec*38*20f4ad0590ec2b44ff85102650314ec911cc2227bdb0e5ced23ea8517ce4bdc5ec77136e450641fcfe317fd36e069de280f6623e34085186********", "john"},
-	{"$pkzip$5*1*14*556f978a58fa4d1bbd18c6ad7cf3*15d082fd66f783745e02a9a4e138*515d1afdf3036ceddd74f6c2e6a0*117e84fce498fc1aa4ba251efed7*55f7bd45d53f0345aac7a408ac\
-0f***fed7246b*4c6*e00****117e84fce498fc1aa4ba251e5eae6d70747ce420626b1306568499b7600bc9758b0cb03b3eec5343b745b24a41f26b95794af638ff195878692a7bb012d6457bc36b6b48a4f01e99b5c7febaeee\
+	{"$pkzip1$1*2*1*c97839b8fe9e0373ba3c7b29ac6f************", "love"},
+	{"$pkzip1$1*1*1*4f83334e87f67a42fce2a53ef967************", "john"},
+	{"$pkzip1$1*1*1*fcf7385e0c4466cd621743a7f967************", "john"},
+	// 4 hashes in the next one.
+	{"$pkzip1$4*2*1*dce4fb16f19b70cf9c368a5c139b*e27bc3e3adb1cc0f227758f38b8d*20f4ad0590ec2b44ff8510266aec*f63277b2a5ea02bcaed067ee71a6************", "john"},
+	// 8 hashes (max) made with info-zip (2 byte checksums, NOTE they are all the same, since the files were created close to each other)
+	{"$pkzip1$8*2*1*a4a8ac4a5dc8e54105390fb0742d*828c2ccc5be1dbd632aefa1c742d*7a89efd471da46d59570a465742d*47a2799835a2adffd7dbb4ef742d*f71e5644a2efb450173602d6742d*\
+b09fa98d83f0bb3a06a8bed0742d*1a042b99ad076f9a41e250f8742d*26222d5d8d26f6506c8c9fec742d************", "P^$sW0R9"},
+	// 8 hashes (max) made by pkzip, so only 1 byte 'valid'
+	{"$pkzip1$8*1*1*c18675da635e8c05bd4a1b76e162*4be88995ea780d02014c37cdf651*40a798f2dd1482860aea6e70e539*b146f66e800914fcfdd9f17e635c*05570fc392bf9e40080425c9901f*\
+234302627ca721b2acf8d97bcde1*057b6feb54ad24fa8e028e821233*89fc3126769848e44102d741a8c1************", "P^$sW0R9"},
+	{"$pkzip1$1*2*1*20f4ad0590ec2b44ff8510266aec************", "john"},
+	// 1 hash, an ASCII check (step 2), and a 'full' inline test blob (test 3)
+	{"$pkzip1$1*2*16*20f4ad0590ec2b44ff8510266aec*38*8*20f4ad0590ec2b44ff85102650314ec911cc2227bdb0e5ced23ea8517ce4bdc5ec77136e450641fcfe317fd36e069de280f6623e34085186*f967d462*\
+54*49*8****20F4AD0590EC2B44FF85102650314EC911CC2227BDB0E5CED23EA8517CE4BDC5EC77136E450641FCFE317FD36E069DE280F6623E34085186F3A4FEE45EB6D4C6AABF9B7A5A142D456CF542C1EB35BCAAE120330D*", "john"},
+    // 1 hash, and an ASCII check (step 2)
+	{"$pkzip1$1*2*2*20f4ad0590ec2b44ff8510266aec*38*8*20f4ad0590ec2b44ff85102650314ec911cc2227bdb0e5ced23ea8517ce4bdc5ec77136e450641fcfe317fd36e069de280f6623e34085186*********", "john"},
+	// 1 hash, and a 'full' inline test blob (test 3)
+	{"$pkzip1$5*1*14*556f978a58fa4d1bbd18c6ad7cf3*15d082fd66f783745e02a9a4e138*515d1afdf3036ceddd74f6c2e6a0*117e84fce498fc1aa4ba251efed7*55f7bd45d53f0345aac7a408ac0f*\
+***fed7246b*4c6*e00*8****117e84fce498fc1aa4ba251e5eae6d70747ce420626b1306568499b7600bc9758b0cb03b3eec5343b745b24a41f26b95794af638ff195878692a7bb012d6457bc36b6b48a4f01e99b5c7febaeee\
 a045abd0286f8fe676bbf28c6232555b71f242794cb3bf9df89eab681e8436c7fdc561c951d2ffbf6e3ac5302cbad5706c5f59f8f1806e76b465f1f4280e829db18c0ddc3b181b6fa992076b6f1641539b5f45142004db41d5ed\
 158338f663822612bd8ad18676dc7d40148bb006e4d4033f9dfe80526862286afb908d2f46b895cdc11e15fd2712932ba491a82aeadc231612c6cbc304858d80a46378f72dcda91ea70adfeda96c0fbdd17a954dd4f88fb6c44b\
 d362e0302fe209ac1b9a06a1b7f35dc6208b58d5315058322c85117184e279f4aaec3870a8f05dc2aff0e8bc8613adbc30a95f77f9594132027f44217164c193ab2568a7c175bc41bb6ba96e847746e40d179cc41da890049d35\
@@ -104,13 +121,15 @@ d0cf4f6b2c23618eb41064842441345b3792abd1
 
 static char saved_key[MAX_KEYS_PER_CRYPT][PLAINTEXT_LENGTH + 1];
 static int saved_key_len[MAX_KEYS_PER_CRYPT];
-//static const PKZ_SALT *salt;
 static PKZ_SALT *salt;
 static int cur_chk_bytes=2;
-static u8 mult_tab[16384];
 static u8 chk[MAX_PKZ_FILES][2];
 static u8 ucpr_buf[UBUF_SIZE];
 
+#ifdef PKZIP_USE_MULT_TABLE
+static u8 mult_tab[16384];
+#endif
+
 extern struct fmt_main fmt_pkzip;
 
 static int binary_hash1_0(void *binary);
@@ -162,76 +181,119 @@ static int valid(char *ciphertext, struc
 	int len, cnt;
 	u32 flags;
 	FILE *in;
+	char *sFailStr;
 
-	if (strncmp(ciphertext, "$pkzip$", 7))
+	if (strncmp(ciphertext, "$pkzip1$", 7))
 		return 0;
 
 	cp = (u8*)str_alloc_copy(ciphertext);
 
-	p = &cp[7];
+	p = &cp[8];
 	p = GetFld(p, &cp);
-	if (!p || *p==0 || *cp < '1' || *cp > ('0'+MAX_PKZ_FILES)) return 0;
+	if (!p || *p==0) {
+		sFailStr = "Out of data, reading count of hashes field"; goto Bail; }
 	sscanf((c8*)cp, "%x", &cnt);
+	if (cnt < 1 || cnt > MAX_PKZ_FILES) {
+		sFailStr = "Count of hashes field out of range"; goto Bail; }
 	p = GetFld(p, &cp);
-	if (!p || *p==0 || *cp < '1' || *cp > '2') return 0;
+	if (!p || *p==0 || *cp < '1' || *cp > '2') {
+		sFailStr = "Number of valid hash bytes empty or out of range"; goto Bail; }
 	p = GetFld(p, &cp);
-	if (!p || *p==0 || !is_hex_str(cp)) return 0;
+	if (!p || *p==0 || cp[0] == 0 || !is_hex_str(cp)) {
+		sFailStr = "Flags field empty, or not a hex string"; goto Bail; }
 	sscanf((c8*)cp, "%x", &flags);
 
 	while (cnt--) {
 		p = GetFld(p, &cp);
-		if ( (cnt && (!p || *p==0)) || strlen((c8*)cp) != 28 || !is_hex_str(cp)) return 0;
+		if ( !p || *p==0 || strlen((c8*)cp) != 28 || !is_hex_str(cp)) {
+			sFailStr = "Invalid hash found (missing or not 28 bytes of hex)"; goto Bail; }
 	}
 
 	// Handle flags&2
 	p = GetFld(p, &cp);
-	if ( !p || *p==0 || ((flags&2) && !strlen((c8*)cp)) || !is_hex_str(cp)) return 0;
+	if ( !p || *p==0 || ((flags&2) && (!strlen((c8*)cp) || !is_hex_str(cp)))) {
+			sFailStr = "Length of ascii blob missing (with flags&2 was set)"; goto Bail; }
 	sscanf((c8*)cp, "%x", &len);  // ASCII-mode blob length
 	p = GetFld(p, &cp);
-	if ( !p || *p==0 || ((flags&2) && strlen((c8*)cp) != (len<<1)) || !is_hex_str(cp)) return 0;
+	if ( !p || *p==0 || ((flags&2) && !(*cp=='0'||*cp=='8'))) {
+			sFailStr = "Invalid compression type for ASCII blob (with flags&2 set)"; goto Bail; }
+	p = GetFld(p, &cp);
+	if ( !p || *p==0 || ((flags&2) && (strlen((c8*)cp) != (len<<1) || !is_hex_str(cp)))) {
+			sFailStr = "Ascii blob missing, wrong legth or not hex (with flags&2 was set)"; goto Bail; }
 
 	// Handle flags&4
 	p = GetFld(p, &cp);
-	if ( !p || *p==0 || ((flags&4) && !strlen((c8*)cp)) || !is_hex_str(cp)) return 0;
+	if ( !p || *p==0 || ((flags&4) && (!strlen((c8*)cp) || !is_hex_str(cp)))) {
+			sFailStr = "Crc data missing or not hex, (with flags&4 was set)"; goto Bail; }
 	p = GetFld(p, &cp);
-	if ( !p || *p==0 || ((flags&4) && !strlen((c8*)cp)) || !is_hex_str(cp)) return 0;
+	if ( !p || *p==0 || ((flags&4) && (!strlen((c8*)cp) || !is_hex_str(cp)))) {
+			sFailStr = "Compressed Length data missing or not hex, (with flags&4 was set)"; goto Bail; }
 	sscanf((c8*)cp, "%x", &len);  // compressed len
 	p = GetFld(p, &cp);
-	if ( !p || *p==0 || ((flags&4) && !strlen((c8*)cp)) || !is_hex_str(cp)) return 0;
+	if ( !p || *p==0 || ((flags&4) && (!strlen((c8*)cp) || !is_hex_str(cp)))) {
+			sFailStr = "deCompressed Length data missing or not hex, (with flags&4 was set)"; goto Bail; }
+	p = GetFld(p, &cp);
+	if ( !p || *p==0 || ((flags&4) && !(*cp=='0'||*cp=='8'))) {
+			sFailStr = "Invalid compression type for main FULL blob (with flags&4 set)"; goto Bail; }
 
 	// Handle flags&8
 	p = GetFld(p, &cp);
-	if ( !p || *p==0 || ((flags&8) && !strlen((c8*)cp)) || !is_hex_str(cp)) return 0;
+	if ( !p || *p==0 || ((flags&8) && (!strlen((c8*)cp) || !is_hex_str(cp)))) {
+			sFailStr = "File Offset data missing or not hex, (with flags&8 was set)"; goto Bail; }
 	p = GetFld(p, &cp);
-	if ( !p || *p==0 || ((flags&8) && !strlen((c8*)cp))) return 0;
+	if ( !p || *p==0 || ((flags&8) && !strlen((c8*)cp))) {
+			sFailStr = "Zip-FileName data missing or not hex, (with flags&8 was set)"; goto Bail; }
 	if (flags&8) {
 		in = fopen((c8*)cp, "r");
 		if (!in) {
-			fprintf(stderr, "Error loading a pkzip hash line. The file %s could NOT be found\n", cp);
+			// this error is listed, even if not in pkzip debugging mode.
+			fprintf(stderr, "Error loading a pkzip hash line. The ZIP file '%s' could NOT be found\n", cp);
 			return 0;
 		}
 		fclose(in);
 	}
 	p = GetFld(p, &cp);
-	if ( !p || *p==0 || ((flags&8) && !strlen((c8*)cp))) return 0;
+	if ( !p || *p==0 || ((flags&8) && !strlen((c8*)cp))) {
+			sFailStr = "Internal FileName data missing or not hex, (with flags&8 was set)"; goto Bail; }
 
 	// Handle flags&16
 	p = GetFld(p, &cp);
-	if ( !p || *p || ((flags&16) && strlen((c8*)cp) != (len<<1)) || !is_hex_str(cp)) return 0;
+	if ( !p || *p || ((flags&16) && (strlen((c8*)cp) != (len<<1) || !is_hex_str(cp)))) {
+			sFailStr = "Compressed/Encrypted ZIP data is missing or not right size, or not hex, (with flags&16 was set)"; goto Bail; }
 
-	if ( (flags & (8|16)) && !(flags&4)) // if we have the 'full' file (or file name), and not the CRC and complen, then bail.
-		return 0;
+	// if we have the 'full' file (or file name), and not the CRC and complen, then bail.
+	if ( (flags & (8|16)) && !(flags&4)) {
+			sFailStr = "Flags are set wrong.  If either flags&8 or flags&16, then flags&4 must be set."; goto Bail; }
 
 	return 1;
+
+Bail:;
+#ifdef ZIP_DEBUG
+	fprintf (stderr, "pkzip validation failed [%s]  Hash is %s\n", sFailStr, ciphertext);
+#endif
+	return 0;
 }
 
 
 static void init(struct fmt_main *pFmt)
 {
 	// Precompute the multiply mangling, within 2 parts of the hash.
+	// There is a pattern, 64k entries long.  However the exact same
+	// value is produced 4 times in a row, every time.  Thus, we can 
+	// build a 16k wide array, and then access the array using this
+	//   ((val&0xFFFF) >> 2)  This is faster on all current HW,
+	// since the 16kb array access (and the and/shift) is faster than
+	// performing the whole mult, 2 shifts, 2 adds and an and 
+	// (if the compiler can optimize it to that)
+	//
+	// There is a # define at the top of this file that turns this OFF.
+	// if that define is not set, then these mult's will be done in the
+	// crypt_all and decrypt functions
+#ifdef PKZIP_USE_MULT_TABLE
 	unsigned short n;
 	for (n = 0; n < 16384; n++)
 		mult_tab[n] = ((n*4+3) * (n*4+2) >> 8) & 0xff;
+#endif
 }
 
 static void SetChkBytes() {
@@ -271,6 +333,9 @@ static void load_bin_data(u8 *inp, u8 **
 
 static void * get_salt(char *ciphertext)
 {
+	// NOTE, there is NO error checking at all in this function.  It is assumed that ALL proper
+	// error checking was performed in valid, and that the string will convert into the valid
+	// data to load properly. Valid is VERY anal about this, and does all the work.
 	static unsigned char salt_p[8];
 	PKZ_SALT *salt;
 	int i, j;
@@ -283,7 +348,7 @@ static void * get_salt(char *ciphertext)
 	cp = cpalloc;
 	strcpy((c8*)cp, ciphertext);
 
-	p = &cp[7];
+	p = &cp[8];
 	p = GetFld(p, &cp);
 	sscanf((c8*)cp, "%x", &(salt->cnt));
 	p = GetFld(p, &cp);
@@ -301,7 +366,10 @@ static void * get_salt(char *ciphertext)
 	// Handle flags&2
 	p = GetFld(p, &cp);
 	if (salt->flags&2)
-		sscanf((c8*)cp, "%x", &(salt->asciilen));  // ASCII-mode blob length
+		sscanf((c8*)cp, "%x", &(salt->asciilen));
+	p = GetFld(p, &cp);
+	if (salt->flags&2)
+		sscanf((c8*)cp, "%x", &(salt->asciiCompType));
 	p = GetFld(p, &cp);
 	if (salt->flags&2)
 		load_bin_data(cp, &(salt->asciidat));
@@ -309,18 +377,21 @@ static void * get_salt(char *ciphertext)
 	// Handle flags&4
 	p = GetFld(p, &cp);
 	if (salt->flags&4)
-		sscanf((c8*)cp, "%x", &(salt->crc32));  // compressed len
+		sscanf((c8*)cp, "%x", &(salt->crc32));
+	p = GetFld(p, &cp);
+	if (salt->flags&4)
+		sscanf((c8*)cp, "%x", &(salt->compLen));
 	p = GetFld(p, &cp);
 	if (salt->flags&4)
-		sscanf((c8*)cp, "%x", &(salt->compLen));  // compressed len
+		sscanf((c8*)cp, "%x", &(salt->deCompLen));
 	p = GetFld(p, &cp);
 	if (salt->flags&4)
-		sscanf((c8*)cp, "%x", &(salt->deCompLen));  // compressed len
+		sscanf((c8*)cp, "%x", &(salt->compType));
 
 	// Handle flags&8
 	p = GetFld(p, &cp);
 	if (salt->flags&8)
-		sscanf((c8*)cp, "%x", &(salt->offset));  // Offset to data blob in file.
+		sscanf((c8*)cp, "%x", &(salt->offset));
 	p = GetFld(p, &cp);
 	if (salt->flags&8)
 		salt->filename = str_alloc_copy((c8*)cp);
@@ -341,6 +412,7 @@ static void * get_salt(char *ciphertext)
 
 static void *get_binary(char *ciphertext)
 {
+	// No error checking performed.  All of the error checking was done in valid().
 	static unsigned char Buf[BINARY_SIZE];
 	int cnt;
 	unsigned char *op=Buf, *p, *cp, *cpalloc = (unsigned char*)mem_alloc(strlen(ciphertext)+1);
@@ -348,9 +420,9 @@ static void *get_binary(char *ciphertext
 	cp = cpalloc;
 	strcpy((c8*)cp, ciphertext);
 
-	p = &cp[7];
+	p = &cp[8];
 	p = GetFld(p, &cp);
-	sscanf((c8*)cp, "%d", &cnt);
+	sscanf((c8*)cp, "%x", &cnt);
 	p = GetFld(p, &cp);
 	p = GetFld(p, &cp);
 	while (cnt--) {
@@ -395,89 +467,82 @@ static char *get_key(int index)
 	return saved_key[index];
 }
 
+/* 
+ * Crypt_all simply performs the checksum .zip validatation of the data. It performs
+ * this for ALL hashes provided. If any of them fail to match, then crypt all puts the
+ * complement of the 'proper' checksum of the first hash into the output. These 2 bytes
+ * are checked against the binary for this salt/password combination.  Thus, if any
+ * checksum fails, it will never match binary.  However, if ALL of the checksums match
+ * we then put the checksum bytes from the first hash, into our output data. Then, when
+ * the binary check (cmp_all, cmp_one) is performed, it WILL match.  NOTE, this does 
+ * not mean we have found the password.  Just that all hashes quick check checksums
+ * for this password 'work'.
+ */
 static void crypt_all(int _count)
 {
 	int idx;
-	char *pw_end, *pw;
 	for (idx = 0; idx < _count; ++idx) {
-		int count = salt->cnt;
-		int count2 = 0, len;
-		int salt_idx = -1;
-		MY_WORD key0, key1, key2;
-		u8 *p;
-
-		pw = saved_key[idx];
-		len = saved_key_len[idx];
-		pw_end = pw + len;
-
-		p = (u8 *)pw_end - len;
-
-		key0.u = 0x12345678UL;
-		key1.u = 0x23456789UL;
-		key2.u = 0x34567890UL;
+		int cur_hash_count = salt->cnt;
+		int cur_hash_idx = -1;
+		MY_WORD pwkey0, pwkey1, pwkey2;
+		u8 *p = (u8 *)saved_key[idx];
+
+		// load the 'pwkey' one time.
+		pwkey0.u = 0x12345678UL; pwkey1.u = 0x23456789UL; pwkey2.u = 0x34567890UL;
 		do {
-			key0.u = pkzip_crc32 (key0.u, *p++);
-			key1.u = (key1.u + key0.c[0]) * 134775813 + 1;
-			key2.u = pkzip_crc32 (key2.u, key1.c[3]);
+			pwkey0.u = pkzip_crc32 (pwkey0.u, *p++);
+			pwkey1.u = (pwkey1.u + pwkey0.c[0]) * 134775813 + 1;
+			pwkey2.u = pkzip_crc32 (pwkey2.u, pwkey1.c[3]);
 		} while (*p);
+
+		// use the pwkey for each hash.  We mangle on the 12 bytes of IV to what 
+		// was computed in the pwkey load.
 		do
 		{
-			u8 target, pre_target;
+			u8 checkSum1, checkSum2;
+			MY_WORD key0, key1, key2;
+			const u8 *b = salt->h[++cur_hash_idx], *be = &b[11];
+			const u8 *e = salt->c[cur_hash_idx];
 
-			//#if !USE_MULT_TAB
-			//u16 t;
-			//#endif
-			MY_WORD kez0, kez1, kez2;
-			const u8 *b = salt->h[++salt_idx], *be = &b[11];
-			const u8 *e = salt->c[salt_idx];
-
-			kez0.u = key0.u, kez1.u = key1.u, kez2.u = key2.u;
+			key0.u = pwkey0.u, key1.u = pwkey1.u, key2.u = pwkey2.u;
 			do
 			{
-				//#if USE_MULT_TAB
-
-				pre_target = *b++ ^ mult_tab [(kez2.u&0xFFFF) >> 2];		// 6550k/s GCC speed.   6995k/s (VC speed)
-				//pre_target = *b++ ^ mult_tab [(u16)(kez2.u) >> 2];		// 6360k/s              7029k/s
-				//pre_target = *b++ ^ mult_tab [(kez2.u>>2)&0x3FFF];		// 6440k/s              7052k/s
-
-				//#else
-				//     t = kez2.u | 2;
-				//     pre_target = *b++ ^ (u8)(((u16) (t * (t^1)) >> 8));
-				//#endif
-				kez0.u = pkzip_crc32 (kez0.u, pre_target);
-				kez1.u = (kez1.u + kez0.c[0]) * 134775813 + 1;
-				kez2.u = pkzip_crc32 (kez2.u, kez1.c[3]);
+#ifdef PKZIP_USE_MULT_TABLE
+				checkSum2 = *b++ ^ mult_tab [(u16)(key2.u) >> 2];	// 6850K/GCC  7230K/VC  Midrange Core 32 bit, Win32
+#else
+				u16 t = key2.u | 2;
+				checkSum2 = *b++ ^ (u8)(((u16) (t * (t^1)) >> 8));	// 5926K/GCC  6429K/VC  Midrange Core 32 bit, Win32
+#endif
+				key0.u = pkzip_crc32 (key0.u, checkSum2);
+				key1.u = (key1.u + key0.c[0]) * 134775813 + 1;
+				key2.u = pkzip_crc32 (key2.u, key1.c[3]);
 			}
 			while (b < be);
 
-			//#if USE_MULT_TAB
-
-			target = *b++ ^ mult_tab [(kez2.u&0xFFFF) >> 2];
-			//target = *b++ ^ mult_tab [(u16)(kez2.u) >> 2];
-			//target = *b++ ^ mult_tab [(kez2.u>>2)&0x3FFF];
-
-
-			//#else
-			//     t = kez2.u | 2;
-			//     target = *b++ ^ (u8)(((u16) (t * (t^1)) >> 8));
-			//#endif
-
-			if (target != e[0])
-				goto out;
-
-			if (pre_target == e[1])
-				count2++;
-			else if (salt->chk_bytes == 2)
-				goto out;
+			// if the hash is a 2 byte checksum type, then check that value
+			// NOW. No reason to continue if this byte does not check out.
+			if (salt->chk_bytes == 2 && checkSum2 != e[1])
+				goto Failed_Bailout;
+
+#ifdef PKZIP_USE_MULT_TABLE
+			checkSum1 = *b++ ^ mult_tab [(u16)(key2.u) >> 2];
+#else
+			{
+			u16 t = key2.u | 2;
+			checkSum1 = *b++ ^ (u8)(((u16) (t * (t^1)) >> 8));
+			}
+#endif
+			if (checkSum1 != e[0])
+				goto Failed_Bailout;
 		}
-		while(--count);
+		while(--cur_hash_count);
 
-		// We got a HIT!!!!
+		// We got a HIT!!!! All hash checksums matched.
 		chk[idx][0] = salt->c[0][0];
 		chk[idx][1] = salt->c[0][1];
 		continue;
 		
-		out: ;
+Failed_Bailout: ;
 		chk[idx][0] = ~(salt->c[0][0]);
 		chk[idx][1] = ~(salt->c[0][1]);
 	}
@@ -506,17 +571,12 @@ static int cmp_all(void *binary, int cou
 }
 
 static void decrypt (int idx, u8 *inp, u8 *out, int inplen) {
-	char *pw_end, *pw;
 	MY_WORD key0, key1, key2;
-	u8 *p, C;
+	u8 *p=((u8*)&(saved_key[idx])), C;
 	const u8 *b = inp, *be = &b[12];
 
-	pw = saved_key[idx];
-	pw_end = pw + saved_key_len[idx];
-
-	p = (u8 *)pw_end - saved_key_len[idx];
-
 	key0.u = 0x12345678UL; 	key1.u = 0x23456789UL; 	key2.u = 0x34567890UL;
+	// Load the password into the keys.
 	do {
 		key0.u = pkzip_crc32 (key0.u, *p++);
 		key1.u = (key1.u + key0.c[0]) * 134775813 + 1;
@@ -525,15 +585,27 @@ static void decrypt (int idx, u8 *inp, u
 
 	// Load the IV into the keys.
 	do {
-		C = *b++ ^ mult_tab [(key2.u & 0xFFFF) >> 2];
+#ifdef PKZIP_USE_MULT_TABLE
+		C = *b++ ^ mult_tab [(u16)(key2.u) >> 2];
+#else
+		u16 t = key2.u | 2;
+		C = *b++ ^ (u8)(((u16) (t * (t^1)) >> 8));
+#endif
 		key0.u = pkzip_crc32 (key0.u, C);
 		key1.u = (key1.u + key0.c[0]) * 134775813 + 1;
 		key2.u = pkzip_crc32 (key2.u, key1.c[3]);
 	} while (b < be);
 
+	// now decrypt the rest of the data.
 	be = &(inp[inplen]);
 	do {
-		C = *b++ ^ mult_tab [(key2.u & 0xFFFF) >> 2];
+#ifdef PKZIP_USE_MULT_TABLE
+		C = *b++ ^ mult_tab [(u16)(key2.u) >> 2];
+#else
+		u16 t = key2.u | 2;
+		C = *b++ ^ (u8)(((u16) (t * (t^1)) >> 8));
+#endif
+		// write out this decrypted byte.
 		*out++ = C;
 		key0.u = pkzip_crc32 (key0.u, C);
 		key1.u = (key1.u + key0.c[0]) * 134775813 + 1;
@@ -541,14 +613,25 @@ static void decrypt (int idx, u8 *inp, u
 	} while (b < be);
 }
 
-static int decomp_validate(u8 *inp, int inplen, int outlen, u32 crcExpect) {
-	// Ok, here we have to do a FULL decrypt, make sure the data is the proper length, and make sure the
+/* This is the 'third' step in cracking the key
+ * We do a FULL decrypt, then full inflate.
+ */
+// Ok, here we have to do a FULL decrypt, make sure the data is the proper length, and make sure the
 	// CRC32 matches.  If all of that, then we have a 100% hit on the password.  Otherwise, a false positive.
+static int decomp_validate(u8 *inp, int inplen, int outlen, u32 crcExpect) {
 	z_stream strm;
 	int ret, i;
 	u32 crc = 0xFFFFFFFF;
 	int last_out, bytes_this_time;
 
+	if (salt->compType == 0) {
+		// file is stored, so simply CRC the data)
+		if (inplen != outlen)
+		for (i = 0; i < inplen; ++i)
+			crc = pkzip_crc32(crc,inp[i]);
+		return ~crc == crcExpect;
+	}
+
 	strm.zalloc = Z_NULL;
 	strm.zfree = Z_NULL;
 	strm.opaque = Z_NULL;
@@ -609,6 +692,19 @@ static int decomp_validate_ascii(u8 *inp
 	z_stream strm;
 	int ret, i;
 
+	if (salt->asciiCompType == 0) {
+		// file is stored, so simply check the 
+		for (i = 0; i <inplen-4; ++i) {
+			char c = inp[i];
+			if (((unsigned char)c) > 0x7F)
+				return 0;
+			if (c > ' ' || c == '\n' || c == '\r' || c == '\t' || c == 0x1a)
+				continue;
+			return 0;
+		}
+		return 1;
+	}
+
 	strm.zalloc = Z_NULL;
 	strm.zfree = Z_NULL;
 	strm.opaque = Z_NULL;
@@ -631,14 +727,18 @@ static int decomp_validate_ascii(u8 *inp
 	if (ret != Z_OK || strm.total_out < 16)
 		return 0;
 
-	for (i = 0; i < strm.total_out-6; ++i) {
+	for (i = 0; i < strm.total_out-4; ++i) {
 		char c = salt->ascii_ucmp[i];
-		if (c > 0x7F)
+		if (((unsigned char)c) > 0x7F)
 			return 0;
 		if (c > ' ' || c == '\n' || c == '\r' || c == '\t' || c == 0x1a)
 			continue;
 		return 0;
 	}
+#ifdef ZIP_DEBUG
+	salt->ascii_ucmp[strm.total_out-4] = 0;
+	printf ("ASCII find:  decoded to: len=%ld [%s]\n", strm.total_out, salt->ascii_ucmp);
+#endif
 	return 1;
 }
 
diff -urpN john-1.7.8-jumbo-5a/src/zip2john.c john-1.7.8-jumbo-5b/src/zip2john.c
--- john-1.7.8-jumbo-5a/src/zip2john.c	2011-08-19 14:54:15.500000000 +0000
+++ john-1.7.8-jumbo-5b/src/zip2john.c	2011-08-19 18:54:46.515625000 +0000
@@ -6,7 +6,7 @@
  * are permitted.
  *
  * Updated in Aug 2011 by Jim Fougeron.  Added PKZIP 'old' encryption.  The signature
- * on the pkzip will be $pkzip$ and does not look like the AES version written by Dhiru
+ * on the pkzip will be $pkzip1$ and does not look like the AES version written by Dhiru
  * Also fixed some porting issues, such as variables needing declared at top of blocks.
  * Added a -a= switch for 'old' format.  That allows a user to give a hint that a specific
  * file 'is' known to be ASCII.  This allows john to have a significant performance 
@@ -37,7 +37,7 @@
  * filename:$zip$*type*hex(CRC)*encryption_strength*hex(salt)*hex(password_verfication_value):hex(authentication_code)
  *
  * For pkzip type:  (JimF, with longer explaination of fields)
- * filename:$pkzip$C*B*F*H*[H*[H*...]]*AL*AD*crc*cmplen*decomplen*offset*filename*intfilename*filedata*
+ * filename:$pkzip1$C*B*F*H*[H*[H*...]]*AL*AT*AD*crc*cmplen*decomplen*compType*offset*filename*intfilename*filedata*
  *
  * All numeric and 'binary data' fields are stored in hex.  
  *
@@ -50,11 +50,13 @@
  * AL is the 'length' of the ASCII compressed file blob.  This assumes that there is a 'known to be' total ASCII text file
  *    encrypted in the zip.  Only a tiny part of the start of the file is decrypted and decompressed. Then if that decompressed
  *    data is 'all' ASCII items, then that is a better validation than a checksum match.
+ * AT is the 'type' of compression. Only 0 or 8 are handled (store or inflate)
  * AD This is the compressed ASCII data.  It is the first 12 bytes (the IV), of the imploded data of the ASCII file, and some
  *    more.  80-90 bytes is more than adequate.  This number may be reduced, if it speeds things up in the end.
  * CRC32       This is the crc of the 'whole' file we have to test
  * Compr_len   This is the length of compressed data (the test-3 full test data).
  * deComp_len  The length of the decompressed data (full file test data).
+ * compType    is the 'type' of compression. Only 0 or 8 are handled (store or inflate)
  * Offset      This is the offset of this data within the .zip file. If the file is too large, then it can not be placed into
  *             the john input line.  If that is the case, the .zip file must be present (name listed next), and when john
  *             runs, it will load the zip data.
@@ -255,12 +257,12 @@ static void process_old_zip(const char *
 	int unix_made=0, check_in_crc = 1, two_byte_check = 0;
 	unsigned Flag_bits = 1;
 	// todo.
-	unsigned AL=0;
+	unsigned AL=0, AT=0;
 	char *AD = "";
-	char sAL[20] = {0};
+	char sAL[8] = {0}, sAT[8] = {0};
 
-	uint32_t best_size=0xFFFFFFFF, best_off, best_crc, best_cmp_size;
-	char best_filename[1024]={0}, best_str_off[20]={0}, best_fname[1024]={0};
+	uint32_t best_size=0xFFFFFFFF, best_off=0, best_crc=0, best_cmp_size=0;
+	char best_filename[1024]={0}, best_str_off[20]={0}, best_fname[1024]={0}, best_type[8]={0};
 
 	strcpy(best_fname, fname);
 
@@ -330,6 +332,7 @@ static void process_old_zip(const char *
 					best_crc=crc;
 					best_cmp_size=compressed_size;
 					strcpy(best_filename, (char*)filename);
+					sprintf(best_type, "%x", compression_method);
 				}
 
 				if (!checksum_only && ascii_mode && !strcmp((char*)filename, ascii_fname)) {
@@ -338,11 +341,13 @@ static void process_old_zip(const char *
 					AL = 112;
 					if (compressed_size < 102)
 						AL = compressed_size;
+					AT = compression_method;
 					fread(Buf, 1, AL, fp);
 					fseek(fp, whence, SEEK_SET);
 					AD = mem_alloc_tiny( (AL<<1)+1, MEM_ALIGN_NONE);
 					convert_to_hex(AD, Buf, AL);
 					sprintf(sAL, "%x", AL);
+					sprintf(sAT, "%x", AT);
 					Flag_bits |= 2;
 					Flag_bits &= (~1); // remove the 'checksum' only flag bit.
 				}
@@ -403,13 +408,14 @@ print_and_cleanup:;
 			Flag_bits &= (~4);
 			AD = "";
 			*sAL = 0;
+			*sAT = 0;
 		}
 	}
-	printf ("%s:$pkzip$%x*%x*%x*%s*", fname, count_of_hashes, two_byte_check+1, Flag_bits, building_hash);
+	printf ("%s:$pkzip1$%x*%x*%x*%s*", fname, count_of_hashes, two_byte_check+1, Flag_bits, building_hash);
 	if (checksum_only)
-		printf("*********\n");
+		printf("***********\n");
 	else
-		printf("%s*%s*%x*%x*%x*%s*%s*%s*%s*\n", sAL, AD, best_crc, best_cmp_size, best_size, best_str_off, best_fname, best_filename, FileData );
+		printf("%s*%s*%s*%x*%x*%x*%s*%s*%s*%s*%s*\n", sAL, sAT, AD, best_crc, best_cmp_size, best_size, best_type, best_str_off, best_fname, best_filename, FileData );
 	fclose(fp);
 }
 
