diff -urpN john-1.7.8-jumbo-6rc1/src/pkzip_fmt_plug.c john-1.7.8-jumbo-6b/src/pkzip_fmt_plug.c
--- john-1.7.8-jumbo-6rc1/src/pkzip_fmt_plug.c	2011-08-29 19:47:50.109375000 +0000
+++ john-1.7.8-jumbo-6b/src/pkzip_fmt_plug.c	2011-08-30 01:37:16.906250000 +0000
@@ -37,14 +37,14 @@
 
 #define PLAINTEXT_LENGTH		31
 
-#define BINARY_SIZE				(MAX_PKZ_FILES*2)
+#define BINARY_SIZE				1
 #define SALT_SIZE				(sizeof(PKZ_SALT*))
 
 #define MIN_KEYS_PER_CRYPT		1
-/* max keys allows 2048 words per thread on a 8 thread OMP build */
+/* max keys allows 256 words per thread on a 16 thread OMP build */
 /* for non-OMP builds, we only want 64 keys */
 #ifdef _OPENMP
-#define MAX_KEYS_PER_CRYPT		(2048*8)
+#define MAX_KEYS_PER_CRYPT		(16*256)
 #else
 #define MAX_KEYS_PER_CRYPT		64
 #endif
@@ -142,41 +142,19 @@ d0cf4f6b2c23618eb41064842441345b3792abd1
 static char saved_key[MAX_KEYS_PER_CRYPT][PLAINTEXT_LENGTH + 1];
 static u32  K12[MAX_KEYS_PER_CRYPT*3];
 static PKZ_SALT *salt;
-static int cur_chk_bytes=2;
-static u16 chk[MAX_PKZ_FILES];
-static u32  ASCII[0x20];
+static u8 chk[MAX_KEYS_PER_CRYPT];
+static int dirty=1;
 #ifdef PKZIP_USE_MULT_TABLE
 static u8 mult_tab[16384];
 #endif
 
-/* in an OMP build, this will be a number larger than 1  (set in init() function */
-static int omp_inc=1;
-
 /* This field is used in cmp_exact loop.  It is a buffer where we decompress     */
 /* a block at a time, while also performing CRC checking                         */
 static u8 ucpr_buf[UBUF_SIZE];
 
-
 extern struct fmt_main fmt_pkzip;
-
-/* We switch back and forth between binary and gethash functions, depending upon  */
-/* if the checksum is 1 byte valid, or 2 byte valid.                              */
-static int binary_hash1_0(void *binary);
-static int binary_hash1_1(void *binary);
-static int get_hash1_0(int index);
-static int get_hash1_1(int index);
-static int binary_hash2_0(void *binary);
-static int binary_hash2_1(void *binary);
-static int binary_hash2_2(void *binary);
-static int binary_hash2_3(void *binary);
-static int get_hash2_0(int index);
-static int get_hash2_1(int index);
-static int get_hash2_2(int index);
-static int get_hash2_3(int index);
-
 static const char *ValidateZipContents(FILE *in, long offset, int len, u32 crc, const char *sIntName);
 
-
 /* Similar to strtok, but written specifically for the format. */
 static u8 *GetFld(u8 *p, u8 **pRet) {
 	if (!p || *p==0) {
@@ -401,7 +379,7 @@ static const char *ValidateZipContents(F
 
 static void init(struct fmt_main *pFmt)
 {
-	unsigned short n;
+	unsigned short n=0;
 	/*
 	 * Precompute the multiply mangling, within several parts of the hash. There is a pattern,
 	 * 64k entries long.  However the exact same value is produced 4 times in a row, every
@@ -417,47 +395,19 @@ static void init(struct fmt_main *pFmt)
 	for (n = 0; n < 16384; n++)
 		mult_tab[n] = ((n*4+3) * (n*4+2) >> 8) & 0xff;
 #endif
-	ASCII['\n'] = 1;
-	ASCII['\t'] = 1;
-	ASCII['\r'] = 1;
-	ASCII[0x1a] = 1;
 
 #ifdef _OPENMP
+	// This can be tuned but it's tedious.
 	n = omp_get_max_threads();
-	omp_inc = MAX_KEYS_PER_CRYPT / n;
-//	if (omp_inc > 2048)
-//		omp_inc = 2048;
-	fmt_pkzip.params.max_keys_per_crypt = omp_inc*n;
-//	printf ("OMP_INC for pkzip is %d\n", omp_inc);
+	if (n*256 < MAX_KEYS_PER_CRYPT)
+		fmt_pkzip.params.max_keys_per_crypt = n*256;
 #endif
-}
-
-static void SetChkBytes() {
-	cur_chk_bytes = salt->chk_bytes;
-	switch(cur_chk_bytes) {
-		case 1:
-			fmt_pkzip.methods.binary_hash[0] = binary_hash1_0;
-			fmt_pkzip.methods.binary_hash[1] = binary_hash1_1;
-			fmt_pkzip.methods.get_hash[0] = get_hash1_0;
-			fmt_pkzip.methods.get_hash[1] = get_hash1_1;
-			break;
-		case 2:
-			fmt_pkzip.methods.binary_hash[0] = binary_hash2_0;
-			fmt_pkzip.methods.binary_hash[1] = binary_hash2_1;
-			fmt_pkzip.methods.binary_hash[2] = binary_hash2_2;
-			fmt_pkzip.methods.binary_hash[2] = binary_hash2_3;
-			fmt_pkzip.methods.get_hash[0] = get_hash2_0;
-			fmt_pkzip.methods.get_hash[1] = get_hash2_1;
-			fmt_pkzip.methods.get_hash[2] = get_hash2_2;
-			fmt_pkzip.methods.get_hash[2] = get_hash2_3;
-			break;
-	}
+	// if not openmp and not use mult_tab, make sure we quiet the unused warning.
+	(void)n;
 }
 
 static void set_salt(void *_salt) {
 	salt = *((PKZ_SALT**)_salt);
-	if(cur_chk_bytes != salt->chk_bytes)
-		SetChkBytes();
 }
 
 static void load_bin_data(u8 *inp, u8 **out) {
@@ -551,86 +501,19 @@ static void *get_salt(char *ciphertext)
 	return salt_p;
 }
 
-static void *get_binary(char *ciphertext)
-{
-	/* NOTE, almost NO error checking at all in this function.  Proper error checking 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);
-
-	cp = cpalloc;
-	strcpy((c8*)cp, ciphertext);
-
-	p = &cp[8];
-	p = GetFld(p, &cp);
-	sscanf((c8*)cp, "%x", &cnt);
-	p = GetFld(p, &cp);
-	p = GetFld(p, &cp);
-	while (cnt--) {
-		p = GetFld(p, &cp);
-#if ARCH_LITTLE_ENDIAN
-		*op++ = (atoi16[ARCH_INDEX(cp[26])]<<4) + atoi16[ARCH_INDEX(cp[27])];
-		*op++ = (atoi16[ARCH_INDEX(cp[24])]<<4) + atoi16[ARCH_INDEX(cp[25])];
-#else
-		*op++ = (atoi16[ARCH_INDEX(cp[24])]<<4) + atoi16[ARCH_INDEX(cp[25])];
-		*op++ = (atoi16[ARCH_INDEX(cp[26])]<<4) + atoi16[ARCH_INDEX(cp[27])];
-#endif
-	}
-	MEM_FREE(cpalloc);
-	return Buf;
-}
-
-static int binary_hash1_0(void *binary) { /*printf ("bin10 =%x\n", ((unsigned short*)binary)[0]);*/ return ((unsigned short*)binary)[0] & 0xf; }
-static int binary_hash1_1(void *binary) { /*printf ("bin11 =%x\n", ((unsigned short*)binary)[0]);*/ return ((unsigned short*)binary)[0] & 0xff; }
-
-static int get_hash1_0(int index) { /*printf ("\nhash10=%x\n", chk[index]);*/ return chk[index] & 0xf; }
-static int get_hash1_1(int index) { /*printf ("\nhash11=%x\n", chk[index]);*/ return chk[index] & 0xff; }
-
-static int binary_hash2_0(void *binary) { /*printf ("bin20 =%x\n", ((unsigned short*)binary)[0]);*/ return ((unsigned short*)binary)[0] & 0xf; }
-static int binary_hash2_1(void *binary) { /*printf ("bin21 =%x\n", ((unsigned short*)binary)[0]);*/ return ((unsigned short*)binary)[0] & 0xff; }
-static int binary_hash2_2(void *binary) { /*printf ("bin22 =%x\n", ((unsigned short*)binary)[0]);*/ return ((unsigned short*)binary)[0] & 0xfff; }
-static int binary_hash2_3(void *binary) { /*printf ("bin23 =%x\n", ((unsigned short*)binary)[0]);*/ return ((unsigned short*)binary)[0] & 0xffff; }
-
-static int get_hash2_0(int index) { /*printf ("\nhash20=%x\n", chk[index]);*/ return chk[index] & 0xf; }
-static int get_hash2_1(int index) { /*printf ("\nhash21=%x\n", chk[index]);*/ return chk[index] & 0xff; }
-static int get_hash2_2(int index) { /*printf ("\nhash22=%x\n", chk[index]);*/ return chk[index] & 0xfff; }
-static int get_hash2_3(int index) { /*printf ("\nhash23=%x\n", chk[index]);*/ return chk[index] & 0xffff; }
+static int binary_hash0(void *binary) { return 1; }
+static int get_hash0(int index)       { return chk[index]; }
 
 static void set_key(char *key, int index)
 {
-	MY_WORD pwkey0, pwkey1, pwkey2;
-	u8 *p;
-//	static int i;
-
 	/* Keep the PW, so we can return it in get_key if asked to do so */
-	p = (u8*)saved_key[index];
 	strnzcpy(saved_key[index], key, PLAINTEXT_LENGTH);
-//	printf ("key=%s   saved=%s\n", key, saved_key[index]);
-//	if (++i == 10) exit(0);
-
-
-	/* load the 'pwkey' one time, put it into the K12 array */
-	pwkey0.u = 0x12345678UL; pwkey1.u = 0x23456789UL; pwkey2.u = 0x34567890UL;
-	do {
-		pwkey0.u = pkzip_crc32 (pwkey0.u, *p++);
-#if ARCH_LITTLE_ENDIAN
-		pwkey1.u = (pwkey1.u + pwkey0.c[0]) * 134775813 + 1;
-		pwkey2.u = pkzip_crc32 (pwkey2.u, pwkey1.c[3]);
-#else
-		pwkey1.u = (pwkey1.u + pwkey0.c[3]) * 134775813 + 1;
-		pwkey2.u = pkzip_crc32 (pwkey2.u, pwkey1.c[0]);
-#endif
-	} while (*p);
-
-	K12[index*3] = pwkey0.u;
-	K12[index*3+1] = pwkey1.u;
-	K12[index*3+2] = pwkey2.u;
+	dirty = 1;
 }
 
+
 static char *get_key(int index)
 {
-//	printf ("getkey(%d)=%s   saved=%s\n", index, saved_key[index]);
-
 	return saved_key[index];
 }
 
@@ -647,7 +530,7 @@ static char *get_key(int index)
  */
 static void crypt_all(int _count)
 {
-	int idx1;
+	int idx;
 
 	// pkzip kinda sucks a little for multi-threading, since there is different amount of work to be
 	// done, depenging upon the password.  Thus, we pack in OMP_MOD passwords into each thread, and
@@ -658,110 +541,118 @@ static void crypt_all(int _count)
 	// first time we fail to match checksum.  So, there may be some threads which check more checksums.
 	// Again, hopefully globbing many tests into a threads working set will flatten out these differences.
 #ifdef _OPENMP
-#pragma omp parallel for private(idx1)
+#pragma omp parallel for private(idx)
 #endif
+	for (idx = 0; idx < _count; ++idx) {
+		int cur_hash_count = salt->cnt;
+		int cur_hash_idx = -1;
+		MY_WORD key0, key1, key2;
+		/* use the pwkey for each hash.  We mangle on the 12 bytes of IV to what  was computed in the pwkey load. */
+
+		if (dirty) {
+			u8 *p = (u8*)saved_key[idx];
+
+			/* load the 'pwkey' one time, put it into the K12 array */
+			key0.u = 0x12345678UL; key1.u = 0x23456789UL; key2.u = 0x34567890UL;
+			do {
+				key0.u = pkzip_crc32 (key0.u, *p++);
+#if ARCH_LITTLE_ENDIAN
+				key1.u = (key1.u + key0.c[0]) * 134775813 + 1;
+				key2.u = pkzip_crc32 (key2.u, key1.c[3]);
+#else
+				key1.u = (key1.u + key0.c[3]) * 134775813 + 1;
+				key2.u = pkzip_crc32 (key2.u, key1.c[0]);
+#endif
+			} while (*p);
+			K12[idx*3] = key0.u, K12[idx*3+1] = key1.u, K12[idx*3+2] = key2.u;
+			goto SkipKeyLoadInit;
+		}
+
+		do
+		{
+			u8 checkSum1, checkSum2;
+			const u8 *b;
+			int k;
+			u16 e;
+
+			// 2nd, and later times through the loop, AND if keys are not dirty (i.e. multiple salts
+			// for the same key load), we do NOT perform the key compute, but instead load the pre-computed
+			// key data from the array.
+			key0.u = K12[idx*3], key1.u = K12[idx*3+1], key2.u = K12[idx*3+2];
+
+SkipKeyLoadInit:;
+			b = salt->h[++cur_hash_idx];
+			k=11;
+			e = salt->c[cur_hash_idx];
 
-	for (idx1 = 0; idx1 < _count; idx1 += omp_inc) {
-		int idx, end;
-		end = idx1+omp_inc;
-		for (idx = idx1; idx < end; ++idx) {
-			int cur_hash_count = salt->cnt;
-			int cur_hash_idx = -1;
-			/* use the pwkey for each hash.  We mangle on the 12 bytes of IV to what  was computed in the pwkey load. */
 			do
 			{
-				u8 checkSum1, checkSum2;
-				MY_WORD key0, key1, key2;
-				const u8 *b = salt->h[++cur_hash_idx], *be = &b[11];
-				u16 e = salt->c[cur_hash_idx];
-
-				key0.u = K12[idx*3], key1.u = K12[idx*3+1], key2.u = K12[idx*3+2];
-				do
-				{
 #ifdef PKZIP_USE_MULT_TABLE
-					checkSum2 = *b++ ^ mult_tab [(u16)(key2.u) >> 2];	/* 6850K/GCC  7230K/VC  Midrange Core 32 bit, Win32 */
+				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 */
+				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);
+				key0.u = pkzip_crc32 (key0.u, checkSum2);
 #if ARCH_LITTLE_ENDIAN
-					key1.u = (key1.u + key0.c[0]) * 134775813 + 1;
-					key2.u = pkzip_crc32 (key2.u, key1.c[3]);
+				key1.u = (key1.u + key0.c[0]) * 134775813 + 1;
+				key2.u = pkzip_crc32 (key2.u, key1.c[3]);
 #else
-					key1.u = (key1.u + key0.c[3]) * 134775813 + 1;
-					key2.u = pkzip_crc32 (key2.u, key1.c[0]);
+				key1.u = (key1.u + key0.c[3]) * 134775813 + 1;
+				key2.u = pkzip_crc32 (key2.u, key1.c[0]);
 #endif
-				}
-				while (b < be);
+			}
+			while(--k);
 
-				/* if the hash is a 2 byte checksum type, then check that value first */
-				/* There is no reason to continue if this byte does not check out.  */
-				if (salt->chk_bytes == 2 && checkSum2 != (e&0xFF))
-					goto Failed_Bailout;
+			/* if the hash is a 2 byte checksum type, then check that value first */
+			/* There is no reason to continue if this byte does not check out.  */
+			if (salt->chk_bytes == 2 && checkSum2 != (e&0xFF))
+				goto Failed_Bailout;
 
 #ifdef PKZIP_USE_MULT_TABLE
-				checkSum1 = *b++ ^ mult_tab [(u16)(key2.u) >> 2];
+			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>>8))
-					goto Failed_Bailout;
 			}
-			while(--cur_hash_count);
+#endif
+			if (checkSum1 != (e>>8))
+				goto Failed_Bailout;
+		}
+		while(--cur_hash_count);
 
-			/* We got a checksum HIT!!!! All hash checksums matched. */
-			/* We load the proper checksum value for the gethash */
-			chk[idx] = salt->c[0];
+		/* We got a checksum HIT!!!! All hash checksums matched. */
+		/* We load the proper checksum value for the gethash */
+		chk[idx] = 1;
 
-			continue;
+		continue;
 		
 Failed_Bailout: ;
-			/* We load the wrong checksum value for the gethash */
-			chk[idx] = ~(salt->c[0]);
-		}
+		/* We load the wrong checksum value for the gethash */
+		chk[idx] = 0;
 	}
+
+	/* clear the 'dirty' flag.  Then on multiple different salt calls, we will not have to */
+	/* encrypt the passwords again. They will have already been loaded in the K12[] array. */
+	dirty = 0;
 }
 
 static int cmp_one(void *binary, int idx)
 {
-	u8 *b = (u8*)binary;
-
-#if ARCH_LITTLE_ENDIAN
-	if (b[0] == (chk[idx]&0xFF)) {
-		if (salt->compLen == 1)
-			return 1;
-		else if (b[1] == ((chk[idx]>>8)&0xFF))
-			return 1;
-	}
-#else
-	if (b[1] == (chk[idx]&0xFF)) {
-		if (salt->compLen == 1)
-			return 1;
-		else if (b[0] == ((chk[idx]>>8)&0xFF))
-			return 1;
-	}
-#endif
-	return 0;
+	return chk[idx] == 1;
 }
 
 static int cmp_all(void *binary, int count)
 {
-	int i;
-	for (i = 0; i < count; ++i) {
-		if (cmp_one(binary, i))
-			return 1;
-	}
-	return 0;
+	return memchr(chk, 1, count) != NULL;
 }
 
 static void decrypt (int idx, u8 *inp, u8 *out, int inplen) {
 	MY_WORD key0, key1, key2;
 	u8 C;
-	const u8 *b = inp, *be = &b[12];
+	int k=12;
+	const u8 *b = inp;
 
 	/* load pre-computed key data */
 	key0.u = K12[idx*3], key1.u = K12[idx*3+1], key2.u = K12[idx*3+2];
@@ -782,10 +673,10 @@ static void decrypt (int idx, u8 *inp, u
 		key1.u = (key1.u + key0.c[3]) * 134775813 + 1;
 		key2.u = pkzip_crc32 (key2.u, key1.c[0]);
 #endif
-	} while (b < be);
+	} while (--k);
 
 	/* now decrypt the rest of the data. */
-	be = &(inp[inplen]);
+	k = inplen;
 	do {
 #ifdef PKZIP_USE_MULT_TABLE
 		C = *b++ ^ mult_tab [(u16)(key2.u) >> 2];
@@ -803,7 +694,7 @@ static void decrypt (int idx, u8 *inp, u
 		key1.u = (key1.u + key0.c[3]) * 134775813 + 1;
 		key2.u = pkzip_crc32 (key2.u, key1.c[0]);
 #endif
-	} while (b < be);
+	} while (--k);
 }
 
 /*
@@ -999,13 +890,13 @@ struct fmt_main fmt_pkzip = {
 		fmt_default_prepare,
 		valid,
 		fmt_default_split,
-		get_binary,
+		fmt_default_binary,
 		get_salt,
 		{
-			binary_hash2_0,
-			binary_hash2_1,
-			binary_hash2_2,
-			binary_hash2_3,
+			binary_hash0,
+			NULL,
+			NULL,
+			NULL,
 			NULL
 		},
 		fmt_default_salt_hash,
@@ -1015,10 +906,10 @@ struct fmt_main fmt_pkzip = {
 		fmt_default_clear_keys,
 		crypt_all,
 		{
-			get_hash2_0,
-			get_hash2_1,
-			get_hash2_2,
-			get_hash2_3,
+			get_hash0,
+			NULL,
+			NULL,
+			NULL,
 			NULL
 		},
 		cmp_all,
