diff -urpN john-1.7.8-jumbo-7a/src/crc32_fmt_plug.c john-1.7.8-jumbo-7b/src/crc32_fmt_plug.c
--- john-1.7.8-jumbo-7a/src/crc32_fmt_plug.c	1970-01-01 00:00:00.000000000 +0000
+++ john-1.7.8-jumbo-7b/src/crc32_fmt_plug.c	2011-09-22 22:32:16.515625000 +0000
@@ -0,0 +1,204 @@
+/*
+ * This file is part of John the Ripper password cracker,
+ *
+ * Written by Jim Fougeron <jfoug at cox.net> in 2011.  No copyright
+ * is claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2011 Jim Fougeron and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ *  This format is:   8hex:8hex  The first 8 hex is the 'starting' crc value
+ *  So, if you have a file and it's CRC is XYZ, then you would put that value
+ *  here, then when the password(s) are found, append them to the file, and get
+ *  the final CRC value.  If you want to find a password with the 'proper' CRC
+ *  value, then put 0 into the first field.  
+ *
+ *  The 2nd 8 hex value is what we are looking for.
+ *
+ */
+
+#include <string.h>
+
+#include "common.h"
+#include "formats.h"
+#include "pkzip.h"  // includes the 'inline' crc table.
+
+#define FORMAT_LABEL			"crc32"
+#define FORMAT_NAME				"crc32"
+#define ALGORITHM_NAME			"N/A"
+
+#define BENCHMARK_COMMENT		""
+#define BENCHMARK_LENGTH		0
+
+#define PLAINTEXT_LENGTH		31
+
+#define BINARY_SIZE				4
+#define SALT_SIZE				4
+
+#define MIN_KEYS_PER_CRYPT		1
+#define MAX_KEYS_PER_CRYPT		(0x4000 / (PLAINTEXT_LENGTH + 1))
+
+static struct fmt_tests tests[] = {
+	{"$crc32$00000000.4ff4f23f", "dummy"},
+	{"$crc32$00000000.00000000", ""},
+	{"$crc32$4ff4f23f.ce6eb863", "password"}, // this would be for file with contents:   'dummy'  and we want to find a password to append that is 'password'
+	{NULL}
+};
+
+static char saved_key[MAX_KEYS_PER_CRYPT][PLAINTEXT_LENGTH + 1];
+static ARCH_WORD_32 crcs[MAX_KEYS_PER_CRYPT];
+static ARCH_WORD_32 crcsalt;
+
+static int valid(char *ciphertext, struct fmt_main *pFmt)
+{
+	char *p, *q;
+	int i;
+
+	if (strncmp(ciphertext, "$crc32$", 7))
+		return 0;
+
+	p = strrchr(ciphertext, '$');
+	q = strchr(p, '.');
+	if (!q || q-p != 9)
+		return 0;
+	for (i = 0; i < 8; ++i) {
+		if (atoi16[(unsigned char)(ciphertext[7+i])] == 0x7F || 
+			atoi16[(unsigned char)(ciphertext[16+i])] == 0x7F)
+			return 0;
+	}
+	return 1;
+}
+
+static int binary_hash_0(void *binary) { return ((ARCH_WORD_32*)binary)[0] & 0xf; }
+static int binary_hash_1(void *binary) { return ((ARCH_WORD_32*)binary)[0] & 0xff; }
+static int binary_hash_2(void *binary) { return ((ARCH_WORD_32*)binary)[0] & 0xfff; }
+static int binary_hash_3(void *binary) { return ((ARCH_WORD_32*)binary)[0] & 0xffff; }
+static int binary_hash_4(void *binary) { return ((ARCH_WORD_32*)binary)[0] & 0xfffff; }
+
+static int get_hash_0(int index) { return crcs[index] & 0xf; }
+static int get_hash_1(int index) { return crcs[index] & 0xff; }
+static int get_hash_2(int index) { return crcs[index] & 0xfff; }
+static int get_hash_3(int index) { return crcs[index] & 0xffff; }
+static int get_hash_4(int index) { return crcs[index] & 0xfffff; }
+
+static void *binary(char *ciphertext)
+{
+	static ARCH_WORD_32 *out;
+	if (!out)
+		out = mem_alloc_tiny(sizeof(ARCH_WORD_32), MEM_ALIGN_WORD);
+	sscanf(&ciphertext[16], "%x", out);
+	return out;
+}
+
+static void *salt(char *ciphertext)
+{
+	static ARCH_WORD_32 *out;
+	if (!out)
+		out = mem_alloc_tiny(sizeof(ARCH_WORD_32), MEM_ALIGN_WORD);
+	sscanf(&ciphertext[7], "%x", out);
+	return out;
+}
+
+static void set_salt(void *salt)
+{
+	crcsalt = *((ARCH_WORD_32 *)salt);
+	// since we ask for the crc of a file, or zero, we need to complement here, and then
+	// complement when done.  This is to observe 'proper' CSITT crc methods.
+	crcsalt = ~crcsalt;
+}
+
+static void set_key(char *key, int index)
+{
+	char *p = saved_key[index];
+	*p = 0;
+	strncat(p, key, PLAINTEXT_LENGTH);
+}
+
+static char *get_key(int index)
+{
+	return saved_key[index];
+}
+
+static void crypt_all(int count)
+{
+	ARCH_WORD_32 crc, i;
+	unsigned char *p;
+	for (i = 0; i < count; ++i) {
+		p = (unsigned char*)saved_key[i];
+		crc = crcsalt;
+		while (*p)
+			crc = pkzip_crc32(crc, *p++);
+		crcs[i] = ~crc;
+	}	
+}
+
+static int cmp_all(void *binary, int count)
+{
+	ARCH_WORD_32 crc=((ARCH_WORD_32*)binary)[0], i;
+	for (i = 0; i < count; ++i)
+		if (crc == crcs[i]) return 1;
+	return 0;
+}
+
+static int cmp_one(void *binary, int index)
+{
+	return ((ARCH_WORD_32*)binary)[0] == crcs[index];
+}
+
+static int cmp_exact(char *source, int index)
+{
+	return 1;
+}
+
+struct fmt_main fmt_crc32 = {
+	{
+		FORMAT_LABEL,
+		FORMAT_NAME,
+		ALGORITHM_NAME,
+		BENCHMARK_COMMENT,
+		BENCHMARK_LENGTH,
+		PLAINTEXT_LENGTH,
+		BINARY_SIZE,
+		SALT_SIZE,
+		MIN_KEYS_PER_CRYPT,
+		MAX_KEYS_PER_CRYPT,
+		FMT_CASE | FMT_8_BIT | FMT_NOT_EXACT,
+		tests
+	}, {
+		fmt_default_init,
+		fmt_default_prepare,
+		valid,
+		fmt_default_split,
+		binary,
+		salt,
+		{
+			binary_hash_0,
+			binary_hash_1,
+			binary_hash_2,
+			binary_hash_3,
+			binary_hash_4
+		},
+		fmt_default_salt_hash,
+		set_salt,
+		set_key,
+		get_key,
+		fmt_default_clear_keys,
+		crypt_all,
+		{
+			get_hash_0,
+			get_hash_1,
+			get_hash_2,
+			get_hash_3,
+			get_hash_4
+		},
+		cmp_all,
+		cmp_one,
+		cmp_exact
+	}
+};
