diff -urpN john-1.7.3.1/src/Makefile john-1.7.3.1-gencrypt/src/Makefile
--- john-1.7.3.1/src/Makefile	2008-07-18 01:28:55 +0000
+++ john-1.7.3.1-gencrypt/src/Makefile	2009-09-02 11:50:28 +0000
@@ -17,7 +17,7 @@ NULL = /dev/null
 CPPFLAGS = -E
 CFLAGS = -c -Wall -O2 -fomit-frame-pointer
 ASFLAGS = -c
-LDFLAGS = -s
+LDFLAGS = -s -lcrypt
 OPT_NORMAL = -funroll-loops
 OPT_INLINE = -finline-functions
 
@@ -28,6 +28,7 @@ JOHN_OBJS_MINIMAL = \
 	BF_fmt.o BF_std.o \
 	AFS_fmt.o \
 	LM_fmt.o \
+	crypt_fmt.o \
 	batch.o bench.o charset.o common.o compiler.o config.o cracker.o \
 	crc32.o external.o formats.o getopt.o idle.o inc.o john.o list.o \
 	loader.o logger.o math.o memory.o misc.o options.o params.o path.o \
diff -urpN john-1.7.3.1/src/crypt_fmt.c john-1.7.3.1-gencrypt/src/crypt_fmt.c
--- john-1.7.3.1/src/crypt_fmt.c	1970-01-01 00:00:00 +0000
+++ john-1.7.3.1-gencrypt/src/crypt_fmt.c	2009-09-02 13:01:34 +0000
@@ -0,0 +1,216 @@
+/* public domain proof-of-concept code by Solar Designer */
+
+#define _XOPEN_SOURCE /* for crypt(3) */
+#include <string.h>
+#include <unistd.h>
+
+#include "arch.h"
+#include "params.h"
+#include "formats.h"
+
+#define FORMAT_LABEL			"crypt"
+#define FORMAT_NAME			"generic crypt(3)"
+#define ALGORITHM_NAME			"?/" ARCH_BITS_STR
+
+#define BENCHMARK_COMMENT		""
+#define BENCHMARK_LENGTH		0
+
+#define PLAINTEXT_LENGTH		72
+
+#define BINARY_SIZE			128
+#define SALT_SIZE			BINARY_SIZE
+
+#define MIN_KEYS_PER_CRYPT		1
+#define MAX_KEYS_PER_CRYPT		1
+
+static struct fmt_tests tests[] = {
+	{"CCNf8Sbh3HDfQ", "U*U*U*U*"},
+	{"CCX.K.MFy4Ois", "U*U***U"},
+	{"CC4rMpbg9AMZ.", "U*U***U*"},
+	{"XXxzOu6maQKqQ", "*U*U*U*U"},
+	{"SDbsugeBiC58A", ""},
+	{NULL}
+};
+
+static char saved_key[PLAINTEXT_LENGTH + 1];
+static char saved_salt[SALT_SIZE];
+static char *crypt_out;
+
+static int valid(char *ciphertext)
+{
+#if 1
+	int l = strlen(ciphertext);
+	return l >= 13 && l < BINARY_SIZE;
+#else
+/* Poor load time, but more effective at rejecting bad/unsupported hashes */
+	char *r = crypt("", ciphertext);
+	int l = strlen(r);
+	return
+	    !strncmp(r, ciphertext, 2) &&
+	    l == strlen(ciphertext) &&
+	    l >= 13 && l < BINARY_SIZE;
+#endif
+}
+
+static void *binary(char *ciphertext)
+{
+	static char out[BINARY_SIZE];
+	strncpy(out, ciphertext, sizeof(out)); /* NUL padding is required */
+	return out;
+}
+
+static void *salt(char *ciphertext)
+{
+	static char out[SALT_SIZE];
+	int cut = sizeof(out);
+
+#if 1
+/* This piece is optional, but matching salts are not detected without it */
+	switch (strlen(ciphertext)) {
+	case 13:
+	case 24:
+		cut = 2;
+		break;
+
+	case 20:
+		if (ciphertext[0] == '_') cut = 9;
+		break;
+
+	case 34:
+		if (!strncmp(ciphertext, "$1$", 3)) {
+			char *p = strchr(ciphertext + 3, '$');
+			if (p) cut = p - ciphertext;
+		}
+		break;
+
+	case 59:
+		if (!strncmp(ciphertext, "$2$", 3)) cut = 28;
+		break;
+
+	case 60:
+		if (!strncmp(ciphertext, "$2a$", 4)) cut = 29;
+		break;
+	}
+#endif
+
+	/* NUL padding is required */
+	memset(out, 0, sizeof(out));
+	memcpy(out, ciphertext, cut);
+
+	return out;
+}
+
+static int binary_hash_0(void *binary)
+{
+	return ((unsigned char *)binary)[12] & 0xF;
+}
+
+static int binary_hash_1(void *binary)
+{
+	return ((unsigned char *)binary)[12] & 0xFF;
+}
+
+static int binary_hash_2(void *binary)
+{
+	return
+	    (((unsigned char *)binary)[12] & 0xFF) |
+	    ((int)(((unsigned char *)binary)[11] & 0xF) << 8);
+}
+
+static int get_hash_0(int index)
+{
+	return (unsigned char)crypt_out[12] & 0xF;
+}
+
+static int get_hash_1(int index)
+{
+	return (unsigned char)crypt_out[12] & 0xFF;
+}
+
+static int get_hash_2(int index)
+{
+	return
+	    ((unsigned char)crypt_out[12] & 0xFF) |
+	    ((int)((unsigned char)crypt_out[11] & 0xF) << 8);
+}
+
+static int salt_hash(void *salt)
+{
+	int pos = strlen((char *)salt) - 2;
+
+	return
+	    (((unsigned char *)salt)[pos] & 0xFF) |
+	    ((int)(((unsigned char *)salt)[pos + 1] & 3) << 8);
+}
+
+static void set_salt(void *salt)
+{
+	strcpy(saved_salt, salt);
+}
+
+static void set_key(char *key, int index)
+{
+	strcpy(saved_key, key);
+}
+
+static char *get_key(int index)
+{
+	return saved_key;
+}
+
+static void crypt_all(int count)
+{
+	crypt_out = crypt(saved_key, saved_salt);
+}
+
+static int cmp_all(void *binary, int count)
+{
+	return !strcmp((char *)binary, crypt_out);
+}
+
+static int cmp_exact(char *source, int index)
+{
+	return 1;
+}
+
+struct fmt_main fmt_crypt = {
+	{
+		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,
+		tests
+	}, {
+		fmt_default_init,
+		valid,
+		fmt_default_split,
+		binary,
+		salt,
+		{
+			binary_hash_0,
+			binary_hash_1,
+			binary_hash_2
+		},
+		salt_hash,
+		set_salt,
+		set_key,
+		get_key,
+		fmt_default_clear_keys,
+		crypt_all,
+		{
+			get_hash_0,
+			get_hash_1,
+			get_hash_2
+		},
+		cmp_all,
+		cmp_all,
+		cmp_exact
+	}
+};
diff -urpN john-1.7.3.1/src/john.c john-1.7.3.1-gencrypt/src/john.c
--- john-1.7.3.1/src/john.c	2006-05-08 14:49:28 +0000
+++ john-1.7.3.1-gencrypt/src/john.c	2009-09-02 11:50:11 +0000
@@ -38,6 +38,7 @@ extern int CPU_detect(void);
 
 extern struct fmt_main fmt_DES, fmt_BSDI, fmt_MD5, fmt_BF;
 extern struct fmt_main fmt_AFS, fmt_LM;
+extern struct fmt_main fmt_crypt;
 
 extern int unshadow(int argc, char **argv);
 extern int unafs(int argc, char **argv);
@@ -64,6 +65,7 @@ static void john_register_all(void)
 	john_register_one(&fmt_BF);
 	john_register_one(&fmt_AFS);
 	john_register_one(&fmt_LM);
+	john_register_one(&fmt_crypt);
 
 	if (!fmt_list) {
 		fprintf(stderr, "Unknown ciphertext format name requested\n");