From 7b9f5231c4e060a178d6ef05135f014ef9351410 Mon Sep 17 00:00:00 2001
From: magnum <magnum>
Date: Mon, 15 Aug 2011 02:09:01 +0200
Subject: [PATCH 38/39] thin raw-md5u

---
 src/rawmd5u_fmt_plug.c |  144 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 144 insertions(+), 0 deletions(-)
 create mode 100644 src/rawmd5u_fmt_plug.c

diff --git a/src/rawmd5u_fmt_plug.c b/src/rawmd5u_fmt_plug.c
new file mode 100644
index 0000000..bf845d7
--- /dev/null
+++ b/src/rawmd5u_fmt_plug.c
@@ -0,0 +1,144 @@
+/*
+ * This is thin md5(unicode($p)) made from rawMD5go_fmt_plug.c by magnum 2011,
+ * now linking to md5_gen(29). Below is original comments from rawMD5go:
+ *
+ * This software is Copyright © 2004 bartavelle, <bartavelle at bandecon.com>, 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.
+ *
+ * Minor changes by David Luyer <david at luyer.net> to
+ * use a modified (faster) version of Solar Designer's
+ * md5 implementation.
+ *
+ * More improvement by
+ * Balázs Bucsay - earthquake at rycon.hu - http://www.rycon.hu/
+ * (2times faster, but it's only works up to 54characters)
+ *
+ * Finally, support for SSE intrinsics
+ *
+ * This format is now 'thin', and links to md5_gen(0) format.
+ * JimF, March, 2011
+ *
+ */
+
+#include <string.h>
+#include "misc.h"
+#include "common.h"
+#include "formats.h"
+#include "md5_gen.h"
+#include "options.h"
+#include "unicode.h"
+
+#define FORMAT_LABEL			"raw-md5u"
+#define FORMAT_NAME			"md5(unicode($p))"
+#define ALGORITHM_NAME			"gen"
+
+#define BENCHMARK_COMMENT		""
+#define BENCHMARK_LENGTH		-1
+
+#define PLAINTEXT_LENGTH		54 // octets, not characters. Trimmed in init()
+#define CIPHERTEXT_LENGTH		32
+#define BINARY_SIZE				16
+#define SALT_SIZE				0
+
+/* Note, some tests may be replaced in init() depending on --enc */
+static struct fmt_tests rawmd5u_tests[] = {
+	{"16c47151c18ac087cd12b3a70746c790", "test1"},
+	{"d41d8cd98f00b204e9800998ecf8427e", ""},
+	{"d41d8cd98f00b204e9800998ecf8427e", ""},
+	{"d41d8cd98f00b204e9800998ecf8427e", ""},
+	{"d41d8cd98f00b204e9800998ecf8427e", ""},
+	{"d41d8cd98f00b204e9800998ecf8427e", ""},
+	{"9c3abef89ff76f8acd80eae37b35f64f", "test2"},
+	{"849ee1b88b5d887bdb058180a666b450", "test3"},
+	{"8c4cb7e8b33b56a833cdaa8673f3b425", "test4"},
+	{"537e738b1ac5551f65106368dc301ece", "thatsworking"},
+	{NULL}
+};
+
+static char Conv_Buf[80];
+static struct fmt_main *pFmt_MD5_gen_29;
+static void rawmd5u_init(struct fmt_main *pFmt);
+
+/* this function converts a 'native' raw md5 signature string into a md5_gen(29) syntax string */
+static char *Convert(char *Buf, char *ciphertext)
+{
+	if (strlen(ciphertext)!=32)
+		return "*";
+	sprintf(Buf, "md5_gen(29)%s", ciphertext);
+	return Buf;
+}
+
+static int valid(char *ciphertext, struct fmt_main *pFmt)
+{
+	int i;
+
+	if (strlen(ciphertext) != CIPHERTEXT_LENGTH) return 0;
+	for (i = 0; i < CIPHERTEXT_LENGTH; i++){
+		if (!(  (('0' <= ciphertext[i])&&(ciphertext[i] <= '9')) ||
+					(('a' <= ciphertext[i])&&(ciphertext[i] <= 'f'))  ))
+			return 0;
+	}
+	if (!pFmt_MD5_gen_29)
+		rawmd5u_init(pFmt);
+	return pFmt_MD5_gen_29->methods.valid(Convert(Conv_Buf, ciphertext), pFmt_MD5_gen_29);
+}
+
+static void * our_salt(char *ciphertext)
+{
+	return pFmt_MD5_gen_29->methods.salt(Convert(Conv_Buf, ciphertext));
+}
+static void * our_binary(char *ciphertext)
+{
+	return pFmt_MD5_gen_29->methods.binary(Convert(Conv_Buf, ciphertext));
+}
+
+struct fmt_main fmt_rawmd5u =
+{
+	{
+		// setup the labeling and stuff. NOTE the max and min crypts are set to 1
+		// here, but will be reset within our init() function.
+		FORMAT_LABEL, FORMAT_NAME, ALGORITHM_NAME, BENCHMARK_COMMENT, BENCHMARK_LENGTH,
+		PLAINTEXT_LENGTH, BINARY_SIZE, SALT_SIZE, 1, 1, FMT_CASE | FMT_8_BIT | FMT_UNICODE | FMT_UTF8, rawmd5u_tests
+	}, {
+		/*  All we setup here, is the pointer to valid, and the pointer to init */
+		/*  within the call to init, we will properly set this full object      */
+		rawmd5u_init,
+		fmt_default_prepare,
+		valid
+	}
+};
+
+static void rawmd5u_init(struct fmt_main *pFmt)
+{
+	if (options.utf8) {
+		// We may need three octets of input to produce two octets of key
+		fmt_rawmd5u.params.plaintext_length = 3 * PLAINTEXT_LENGTH / 2;
+		rawmd5u_tests[1].ciphertext = "94a4e171de16580742c4d141e6607bf7";
+		rawmd5u_tests[1].plaintext = "\xE2\x82\xAC";	// Euro sign
+		rawmd5u_tests[2].ciphertext = "03c60810f0e54d16e826aca385d776c8";
+		rawmd5u_tests[2].plaintext = "\xE2\x82\xAC\xE2\x82\xAC";	// 2 x euro
+		rawmd5u_tests[3].ciphertext = "2d554433d7cde7ec8d16aaf126c3be6b";
+		rawmd5u_tests[3].plaintext = "\xE2\x82\xAC\xC3\xBC";	// euro and u-umlaut
+		rawmd5u_tests[4].ciphertext = "8007d9070b27db7b30433df2cd10abc1";
+		rawmd5u_tests[4].plaintext = "\xC3\xBC\xE2\x82\xAC";	// u-umlaut and euro
+	} else {
+		// We need one octet of input to produce two octets of key
+		fmt_rawmd5u.params.plaintext_length = PLAINTEXT_LENGTH / 2;
+		if (CP_to_Unicode[0xfc] == 0x00fc) {
+			rawmd5u_tests[1].ciphertext = "ea7ab2b5c07650badab30790d0c9b63e";
+			rawmd5u_tests[1].plaintext = "\xFC";	// German u-umlaut in iso-8859-1
+			rawmd5u_tests[2].ciphertext = "f0a0b9f1dea0e458cec9a284ff434d44";
+			rawmd5u_tests[2].plaintext = "\xFC\xFC";
+			rawmd5u_tests[3].ciphertext = "d25a0b436b768777cc9a343d283dbf5a";
+			rawmd5u_tests[3].plaintext = "\xFC\xFC\xFC";
+			rawmd5u_tests[4].ciphertext = "719917322bf12168f8c55939e4fec8de";
+			rawmd5u_tests[4].plaintext = "\xFC\xFC\xFC\xFC";
+		}
+	}
+	if (pFmt->private.initialized == 0) {
+		pFmt_MD5_gen_29 = md5_gen_THIN_FORMAT_LINK(&fmt_rawmd5u, Convert(Conv_Buf, rawmd5u_tests[0].ciphertext), "thin");
+		fmt_rawmd5u.methods.binary = our_binary;
+		fmt_rawmd5u.methods.salt = our_salt;
+		pFmt->private.initialized = 1;
+	}
+}
-- 
1.7.4.1

