[gthumb] added gsignature, to compute hash based signatures.



commit 38b9afff1dc5a47beccc8144f61c12725ba6691b
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sun Apr 11 23:34:06 2010 +0200

    added gsignature, to compute hash based signatures.

 gthumb/Makefile.am      |    2 +
 gthumb/gsignature.c     |  215 ++++++++++++++++++++++++++++++++++++++++++
 gthumb/gsignature.h     |   57 +++++++++++
 tests/Makefile.am       |    7 +-
 tests/gsignature-test.c |  238 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 518 insertions(+), 1 deletions(-)
---
diff --git a/gthumb/Makefile.am b/gthumb/Makefile.am
index 29d3d39..8e48bb6 100644
--- a/gthumb/Makefile.am
+++ b/gthumb/Makefile.am
@@ -34,6 +34,7 @@ PUBLIC_HEADER_FILES = 					\
 	gio-utils.h					\
 	glib-utils.h					\
 	gnome-desktop-thumbnail.h			\
+	gsignature.h					\
 	gth-async-task.h				\
 	gth-buffer-data.h				\
 	gth-browser.h					\
@@ -144,6 +145,7 @@ gthumb_SOURCES = 					\
 	gconf-utils.c					\
 	gio-utils.c					\
 	glib-utils.c					\
+	gsignature.c					\
 	gth-async-task.c				\
 	gth-browser.c					\
 	gth-browser-actions-callbacks.c			\
diff --git a/gthumb/gsignature.c b/gthumb/gsignature.c
new file mode 100644
index 0000000..58fdece
--- /dev/null
+++ b/gthumb/gsignature.c
@@ -0,0 +1,215 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+#include "gsignature.h"
+
+
+/* Algorithm description: http://en.wikipedia.org/wiki/HMAC
+ * Reference implementation: http://www.faqs.org/rfcs/rfc2202.html  */
+
+
+#define BLOCK_SIZE 64 /* in gchecksum.c DATASIZE is always 64 */
+
+
+struct _GSignature
+{
+	GChecksumType  checksum_type;
+	GChecksum     *primary;
+	GChecksum     *internal;
+	guchar         opad[BLOCK_SIZE];
+	guchar         ipad[BLOCK_SIZE];
+};
+
+
+GSignature *
+g_signature_new (GChecksumType  checksum_type,
+		 const gchar   *key,
+		 gssize         key_length)
+{
+	GSignature *signature;
+	gchar      *local_key;
+	int         i;
+
+	if (key == NULL)
+		return NULL;
+
+	signature = g_slice_new0 (GSignature);
+	signature->checksum_type = checksum_type;
+	signature->primary = g_checksum_new (checksum_type);
+	signature->internal = g_checksum_new (checksum_type);
+
+	if (key_length == -1)
+		key_length = strlen (key);
+
+	if (key_length > BLOCK_SIZE) {
+		GChecksum *key_checksum;
+		gsize      digest_len;
+
+		key_checksum = g_checksum_new (checksum_type);
+		g_checksum_update (key_checksum, (guchar *) key, key_length);
+		key_length = digest_len = g_checksum_type_get_length (checksum_type);
+		local_key = g_new0 (char, key_length);
+		g_checksum_get_digest (key_checksum, (guint8 *) local_key, &digest_len);
+
+		g_checksum_free (key_checksum);
+	}
+	else
+		local_key = (gchar *) key;
+
+	for (i = 0; i < key_length; i++) {
+		signature->opad[i] = 0x5c ^ local_key[i];
+		signature->ipad[i] = 0x36 ^ local_key[i];
+	}
+
+	for (i = key_length; i < BLOCK_SIZE; i++) {
+		signature->opad[i] = 0x5c;
+		signature->ipad[i] = 0x36;
+	}
+
+	g_checksum_update (signature->primary, signature->opad, BLOCK_SIZE);
+	g_checksum_update (signature->internal, signature->ipad, BLOCK_SIZE);
+
+	if (local_key != key)
+		g_free (local_key);
+
+	return signature;
+}
+
+
+GSignature *
+g_signature_copy (const GSignature *signature)
+{
+	GSignature *copy;
+
+	g_return_val_if_fail (signature != NULL, NULL);
+
+	copy = g_slice_new (GSignature);
+	*copy = *signature;
+	copy->primary = g_checksum_copy (signature->primary);
+	copy->internal = g_checksum_copy (signature->internal);
+
+	return copy;
+}
+
+
+void
+g_signature_free (GSignature *signature)
+{
+	if (signature == NULL)
+		return;
+
+	g_checksum_free (signature->primary);
+	g_checksum_free (signature->internal);
+	g_free (signature);
+}
+
+
+void
+g_signature_reset (GSignature *signature)
+{
+	g_checksum_reset (signature->internal);
+	g_checksum_update (signature->internal, signature->ipad, BLOCK_SIZE);
+}
+
+
+void
+g_signature_update (GSignature   *signature,
+		    const guchar *data,
+		    gssize        length)
+{
+	g_checksum_update (signature->internal, data, length);
+}
+
+
+G_CONST_RETURN gchar *
+g_signature_get_string (GSignature *signature)
+{
+	guint8 *internal_digest;
+	gsize   digest_len;
+
+	digest_len = g_checksum_type_get_length (signature->checksum_type);
+	internal_digest = g_new (guint8, digest_len);
+	g_checksum_get_digest (signature->internal, internal_digest, &digest_len);
+	g_checksum_update (signature->primary, internal_digest, digest_len);
+
+	g_free (internal_digest);
+
+	return g_checksum_get_string (signature->primary);
+}
+
+
+void
+g_signature_get_value (GSignature *signature,
+		       guint8     *buffer,
+		       gsize      *buffer_len)
+{
+	guint8 *internal_digest;
+	gsize   digest_len;
+
+	digest_len = g_checksum_type_get_length (signature->checksum_type);
+	internal_digest = g_new (guint8, digest_len);
+	g_checksum_get_digest (signature->internal, internal_digest, &digest_len);
+	g_checksum_update (signature->primary, internal_digest, digest_len);
+	g_checksum_get_digest (signature->primary, buffer, buffer_len);
+
+	g_free (internal_digest);
+}
+
+
+gchar *
+g_compute_signature_for_data (GChecksumType  checksum_type,
+			      const gchar   *key,
+			      const guchar  *data,
+			      gsize          length)
+{
+	GSignature *signature;
+	gchar      *retval;
+
+	g_return_val_if_fail (data != NULL, NULL);
+
+	signature = g_signature_new (checksum_type, key, -1);
+	if (signature == NULL)
+		return NULL;
+
+	g_signature_update (signature, data, length);
+	retval = g_strdup (g_signature_get_string (signature));
+	g_signature_free (signature);
+
+	return retval;
+}
+
+
+gchar *
+g_compute_signature_for_string (GChecksumType  checksum_type,
+				const gchar   *key,
+				const gchar   *str,
+				gssize         length)
+{
+	g_return_val_if_fail (str != NULL, NULL);
+
+	if (length < 0)
+		length = strlen (str);
+
+	return g_compute_signature_for_data (checksum_type, key, (const guchar *) str, length);
+}
diff --git a/gthumb/gsignature.h b/gthumb/gsignature.h
new file mode 100644
index 0000000..e60db7d
--- /dev/null
+++ b/gthumb/gsignature.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef G_SIGNATURE_H
+#define G_SIGNATURE_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GSignature GSignature;
+
+GSignature *           g_signature_new         (GChecksumType     checksum_type,
+					        const gchar      *key,
+					        gssize            key_length);
+GSignature *           g_signature_copy        (const GSignature *signature);
+void                   g_signature_free        (GSignature       *signature);
+void                   g_signature_reset       (GSignature       *signature);
+void                   g_signature_update      (GSignature       *signature,
+                                                const guchar     *data,
+                                                gssize            length);
+G_CONST_RETURN gchar * g_signature_get_string  (GSignature       *signature);
+void                   g_signature_get_value   (GSignature       *signature,
+						guint8           *buffer,
+						gsize            *buffer_len);
+
+gchar *g_compute_signature_for_data   (GChecksumType  checksum_type,
+				       const gchar   *key,
+                                       const guchar  *data,
+                                       gsize          length);
+gchar *g_compute_signature_for_string (GChecksumType  checksum_type,
+				       const gchar   *key,
+                                       const gchar   *str,
+                                       gssize         length);
+
+G_END_DECLS
+
+#endif /* G_SIGNATURE_H */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 968ec0a..c579236 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,5 +1,5 @@
 if BUILD_TEST_SUITE
-bin_PROGRAMS = dom-test glib-utils-test
+bin_PROGRAMS = dom-test glib-utils-test gsignature_test
 endif
 
 dom_test_SOURCES = dom-test.c $(top_srcdir)/gthumb/dom.c
@@ -9,4 +9,9 @@ dom_test_CFLAGS = $(GTHUMB_CFLAGS) -I$(top_srcdir)/gthumb
 glib_utils_test_SOURCES = glib-utils-test.c $(top_srcdir)/gthumb/glib-utils.c
 glib_utils_test_LDADD = $(GTHUMB_LIBS) 
 glib_utils_test_CFLAGS = $(GTHUMB_CFLAGS) -I$(top_srcdir)/gthumb
+
+gsignature_test_SOURCES = gsignature-test.c $(top_srcdir)/gthumb/gsignature.c
+gsignature_test_LDADD = $(GTHUMB_LIBS) 
+gsignature_test_CFLAGS = $(GTHUMB_CFLAGS) -I$(top_srcdir)/gthumb
+
 -include $(top_srcdir)/git.mk
diff --git a/tests/gsignature-test.c b/tests/gsignature-test.c
new file mode 100644
index 0000000..1d9dd47
--- /dev/null
+++ b/tests/gsignature-test.c
@@ -0,0 +1,238 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+#include "gsignature.h"
+
+
+static void
+test_g_signature_md5 (void)
+{
+	char    *sig;
+	GString *key;
+	GString *data;
+	int      i;
+
+	/* -- test cases taken from http://www.faqs.org/rfcs/rfc2202.html -- */
+
+	/* test case 1 */
+
+	key = g_string_new ("");
+	for (i = 0; i < 16; i++)
+		g_string_append (key, "\x0b");
+	sig = g_compute_signature_for_string (G_CHECKSUM_MD5, key->str, "Hi There", -1);
+	g_assert_cmpstr (sig, == , "9294727a3638bb1c13f48ef8158bfc9d");
+	g_free (sig);
+	g_string_free (key, TRUE);
+
+	/* test case 2 */
+
+	sig = g_compute_signature_for_string (G_CHECKSUM_MD5, "Jefe", "what do ya want for nothing?", -1);
+	g_assert_cmpstr (sig, == , "750c783e6ab0b503eaa86e310a5db738");
+	g_free (sig);
+
+	/* test case 3 */
+
+	key = g_string_new ("");
+	for (i = 0; i < 16; i++)
+		g_string_append (key, "\xaa");
+	data = g_string_new ("");
+	for (i = 0; i < 50; i++)
+		g_string_append (data, "\xdd");
+	sig = g_compute_signature_for_string (G_CHECKSUM_MD5, key->str, data->str, -1);
+	g_assert_cmpstr (sig, == , "56be34521d144c88dbb8c733f0e8b3f6");
+	g_free (sig);
+	g_string_free (data, TRUE);
+	g_string_free (key, TRUE);
+
+	/* test case 4 */
+
+	data = g_string_new ("");
+	for (i = 0; i < 50; i++)
+		g_string_append (data, "\xcd");
+	sig = g_compute_signature_for_string (G_CHECKSUM_MD5, "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", data->str, -1);
+	g_assert_cmpstr (sig, == , "697eaf0aca3a3aea3a75164746ffaa79");
+	g_free (sig);
+	g_string_free (data, TRUE);
+
+	/* test case 5 */
+
+	key = g_string_new ("");
+	for (i = 0; i < 16; i++)
+		g_string_append (key, "\x0c");
+	sig = g_compute_signature_for_string (G_CHECKSUM_MD5, key->str, "Test With Truncation", -1);
+	g_assert_cmpstr (sig, == , "56461ef2342edc00f9bab995690efd4c");
+	g_free (sig);
+	g_string_free (key, TRUE);
+
+	/* test case 6 */
+
+	key = g_string_new ("");
+	for (i = 0; i < 80; i++)
+		g_string_append (key, "\xaa");
+	sig = g_compute_signature_for_string (G_CHECKSUM_MD5, key->str, "Test Using Larger Than Block-Size Key - Hash Key First", -1);
+	g_assert_cmpstr (sig, == , "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd");
+	g_free (sig);
+	g_string_free (key, TRUE);
+
+	/* test case 7 */
+
+	key = g_string_new ("");
+	for (i = 0; i < 80; i++)
+		g_string_append (key, "\xaa");
+	sig = g_compute_signature_for_string (G_CHECKSUM_MD5, key->str, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", -1);
+	g_assert_cmpstr (sig, == , "6f630fad67cda0ee1fb1f562db3aa53e");
+	g_free (sig);
+	g_string_free (key, TRUE);
+}
+
+
+static void
+test_g_signature_sha1 (void)
+{
+	char    *sig;
+	GString *key;
+	GString *data;
+	int      i;
+
+	/* -- test cases taken from http://www.faqs.org/rfcs/rfc2202.html -- */
+
+	/* test case 1 */
+
+	key = g_string_new ("");
+	for (i = 0; i < 20; i++)
+		g_string_append (key, "\x0b");
+	sig = g_compute_signature_for_string (G_CHECKSUM_SHA1, key->str, "Hi There", -1);
+	g_assert_cmpstr (sig, == , "b617318655057264e28bc0b6fb378c8ef146be00");
+	g_free (sig);
+	g_string_free (key, TRUE);
+
+	/* test case 2 */
+
+	sig = g_compute_signature_for_string (G_CHECKSUM_SHA1, "Jefe", "what do ya want for nothing?", -1);
+	g_assert_cmpstr (sig, == , "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79");
+	g_free (sig);
+
+	/* test case 3 */
+
+	key = g_string_new ("");
+	for (i = 0; i < 20; i++)
+		g_string_append (key, "\xaa");
+	data = g_string_new ("");
+	for (i = 0; i < 50; i++)
+		g_string_append (data, "\xdd");
+	sig = g_compute_signature_for_string (G_CHECKSUM_SHA1, key->str, data->str, -1);
+	g_assert_cmpstr (sig, == , "125d7342b9ac11cd91a39af48aa17b4f63f175d3");
+	g_free (sig);
+	g_string_free (data, TRUE);
+	g_string_free (key, TRUE);
+
+	/* test case 4 */
+
+	data = g_string_new ("");
+	for (i = 0; i < 50; i++)
+		g_string_append (data, "\xcd");
+	sig = g_compute_signature_for_string (G_CHECKSUM_SHA1, "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", data->str, -1);
+	g_assert_cmpstr (sig, == , "4c9007f4026250c6bc8414f9bf50c86c2d7235da");
+	g_free (sig);
+	g_string_free (data, TRUE);
+
+	/* test case 5 */
+
+	key = g_string_new ("");
+	for (i = 0; i < 20; i++)
+		g_string_append (key, "\x0c");
+	sig = g_compute_signature_for_string (G_CHECKSUM_SHA1, key->str, "Test With Truncation", -1);
+	g_assert_cmpstr (sig, == , "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04");
+	g_free (sig);
+	g_string_free (key, TRUE);
+
+	/* test case 6 */
+
+	key = g_string_new ("");
+	for (i = 0; i < 80; i++)
+		g_string_append (key, "\xaa");
+	sig = g_compute_signature_for_string (G_CHECKSUM_SHA1, key->str, "Test Using Larger Than Block-Size Key - Hash Key First", -1);
+	g_assert_cmpstr (sig, == , "aa4ae5e15272d00e95705637ce8a3b55ed402112");
+	g_free (sig);
+	g_string_free (key, TRUE);
+
+	/* test case 7 */
+
+	key = g_string_new ("");
+	for (i = 0; i < 80; i++)
+		g_string_append (key, "\xaa");
+	sig = g_compute_signature_for_string (G_CHECKSUM_SHA1, key->str, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", -1);
+	g_assert_cmpstr (sig, == , "e8e99d0f45237d786d6bbaa7965c7808bbff1a91");
+	g_free (sig);
+	g_string_free (key, TRUE);
+
+	/* -- test case taken from php-5.3.2/ext/hash/tests/hash_hmac_bacis.phpt -- */
+
+	sig = g_compute_signature_for_string (G_CHECKSUM_SHA1, "secret", "This is a sample string used to test the hash_hmac function with various hashing algorithms", -1);
+	g_assert_cmpstr (sig, == , "5bfdb62b97e2c987405463e9f7c193139c0e1fd0");
+	g_free (sig);
+
+	/* -- test case created using the crypto-js library (http://code.google.com/p/crypto-js/) -- */
+
+	sig = g_compute_signature_for_string (G_CHECKSUM_SHA1, "Secret Passphrase", "Message", -1);
+	g_assert_cmpstr (sig, == , "e90f713295ea4cc06c92c9248696ffafc5d01faf");
+	g_free (sig);
+
+	key = g_string_new ("");
+	for (i = 0; i < 1; i++)
+		g_string_append (key, "aa");
+	sig = g_compute_signature_for_string (G_CHECKSUM_SHA1, key->str, "Test Using Larger Than Block-Size Key - Hash Key First", -1);
+	g_assert_cmpstr (sig, == , "4f8e4da5b85182a352041a22b4d566b4b53abf9e");
+	g_free (sig);
+	g_string_free (key, TRUE);
+
+	key = g_string_new ("");
+	for (i = 0; i < 20; i++)
+		g_string_append (key, "aa");
+	sig = g_compute_signature_for_string (G_CHECKSUM_SHA1, key->str, "Test Using Larger Than Block-Size Key - Hash Key First", -1);
+	g_assert_cmpstr (sig, == , "cb8da9d75b1cd177c00e8c46bd9c17fa313b9f6c");
+	g_free (sig);
+	g_string_free (key, TRUE);
+
+	key = g_string_new ("");
+	for (i = 0; i < 80; i++)
+		g_string_append (key, "aa");
+	sig = g_compute_signature_for_string (G_CHECKSUM_SHA1, key->str, "Test Using Larger Than Block-Size Key - Hash Key First", -1);
+	g_assert_cmpstr (sig, == , "f196c43f06a566cb096a72227a3196d97236898b");
+	g_free (sig);
+	g_string_free (key, TRUE);
+}
+
+
+int
+main (int   argc,
+      char *argv[])
+{
+	g_test_init (&argc, &argv, NULL);
+
+	g_test_add_func ("/gsignature/g_compute_signature_for_string/md5", test_g_signature_md5);
+	g_test_add_func ("/gsignature/g_compute_signature_for_string/sha1", test_g_signature_sha1);
+
+	return g_test_run ();
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]