git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC PATCH 1/2] Base test implementation for short BLAKE2b support

From
brian m. carlson <sandals@crustytoothpaste.net>
Date
Jan 28, 2018, 17:06 UTC
Message-ID
<20180128170639.216397-2-sandals@crustytoothpaste.net>
In-Reply-To
<20180128170639.216397-1-sandals@crustytoothpaste.net>

Test the implementation of a second hash algorithm with "short" (160-bit) BLAKE2b support. Simply add an additional algorithm to the codebase without changing the use of any hash function and add a test helper.

BLAKE2b was chosen simply because it provides a readily accessible hash algorithm with arbitrary length support. A 160-bit (20-byte) hash was chosen to allow identification of tests that depend on the hash algorithm in use while not causing buffer overflows, since parts of the codebase still assume a 20-byte hash.

This is a preliminary commit for test purposes only and should not be
used in production in any way.
---
 Makefile                 |  3 +++
 cache.h                  | 16 ++++++++++++++
 hash.h                   |  9 +++++++-
 sha1_file.c              | 33 ++++++++++++++++++++++++++++
 t/helper/test-sblake2b.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 116 insertions(+), 1 deletion(-)
 create mode 100644 t/helper/test-sblake2b.c
diff --git a/Makefile b/Makefile
index 1a9b23b679..d46247586b 100644
--- a/Makefile
+++ b/Makefile
@@ -677,6 +677,7 @@ TEST_PROGRAMS_NEED_X += test-ref-store
 TEST_PROGRAMS_NEED_X += test-regex
 TEST_PROGRAMS_NEED_X += test-revision-walking
 TEST_PROGRAMS_NEED_X += test-run-command
+TEST_PROGRAMS_NEED_X += test-sblake2b
 TEST_PROGRAMS_NEED_X += test-scrap-cache-tree
 TEST_PROGRAMS_NEED_X += test-sha1
 TEST_PROGRAMS_NEED_X += test-sha1-array
@@ -1539,6 +1540,8 @@ endif
 endif
 endif
 
+EXTLIBS += -lb2
+
 ifdef SHA1_MAX_BLOCK_SIZE
 	LIB_OBJS += compat/sha1-chunked.o
 	BASIC_CFLAGS += -DSHA1_MAX_BLOCK_SIZE="$(SHA1_MAX_BLOCK_SIZE)"
diff --git a/cache.h b/cache.h
index bfde6f757a..638d832350 100644
--- a/cache.h
+++ b/cache.h
@@ -45,6 +45,10 @@ unsigned long git_deflate_bound(git_zstream *, unsigned long);
 #define GIT_SHA1_RAWSZ 20
 #define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
 
+/* The length in bytes and in hex digits of an object name (short BLAKE2b value). */
+#define GIT_SBLAKE2B_RAWSZ 20
+#define GIT_SBLAKE2B_HEXSZ (2 * GIT_SBLAKE2B_RAWSZ)
+
 /* The length in byte and in hex digits of the largest possible hash value. */
 #define GIT_MAX_RAWSZ GIT_SHA1_RAWSZ
 #define GIT_MAX_HEXSZ GIT_SHA1_HEXSZ
@@ -1013,7 +1017,13 @@ static inline void oidclr(struct object_id *oid)
 #define EMPTY_TREE_SHA1_BIN_LITERAL \
 	 "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60" \
 	 "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04"
+#define EMPTY_TREE_SBLAKE2B_HEX \
+	"f44422a644bfa5212387098f253a1e89eba94548"
+#define EMPTY_TREE_SBLAKE2B_BIN_LITERAL \
+	"\xf4\x44\x22\xa6\x44\xbf\xa5\x21\x23\x87" \
+	"\x09\x8f\x25\x3a\x1e\x89\xeb\xa9\x45\x48"
 extern const struct object_id empty_tree_oid;
+const struct object_id empty_tree_oid_sblake2b;
 #define EMPTY_TREE_SHA1_BIN (empty_tree_oid.hash)
 
 #define EMPTY_BLOB_SHA1_HEX \
@@ -1021,7 +1031,13 @@ extern const struct object_id empty_tree_oid;
 #define EMPTY_BLOB_SHA1_BIN_LITERAL \
 	"\xe6\x9d\xe2\x9b\xb2\xd1\xd6\x43\x4b\x8b" \
 	"\x29\xae\x77\x5a\xd8\xc2\xe4\x8c\x53\x91"
+#define EMPTY_BLOB_SBLAKE2B_HEX \
+	"a706650a477f63b9b00eba41272bf36ef5a7dfa2"
+#define EMPTY_BLOB_SBLAKE2B_BIN_LITERAL \
+	"\xa7\x06\x65\x0a\x47\x7f\x63\xb9\xb0\x0e" \
+	"\xba\x41\x27\x2b\xf3\x6e\xf5\xa7\xdf\xa2"
 extern const struct object_id empty_blob_oid;
+const struct object_id empty_blob_oid_sblake2b;
 #define EMPTY_BLOB_SHA1_BIN (empty_blob_oid.hash)
 
 
diff --git a/hash.h b/hash.h
index 365846a6b5..ef510bd51a 100644
--- a/hash.h
+++ b/hash.h
@@ -15,6 +15,8 @@
 #include "block-sha1/sha1.h"
 #endif
 
+#include <blake2.h>
+
 #ifndef platform_SHA_CTX
 /*
  * platform's underlying implementation of SHA-1; could be OpenSSL,
@@ -40,6 +42,8 @@
 #define git_SHA1_Update		git_SHA1_Update_Chunked
 #endif
 
+#define git_BLAKE2B_CTX		blake2b_state
+
 /*
  * Note that these constants are suitable for indexing the hash_algos array and
  * comparing against each other, but are otherwise arbitrary, so they should not
@@ -52,12 +56,15 @@
 #define GIT_HASH_UNKNOWN 0
 /* SHA-1 */
 #define GIT_HASH_SHA1 1
+/* 20-byte BLAKE2b ("short" BLAKE2b) */
+#define GIT_HASH_SBLAKE2 2
 /* Number of algorithms supported (including unknown). */
-#define GIT_HASH_NALGOS (GIT_HASH_SHA1 + 1)
+#define GIT_HASH_NALGOS (GIT_HASH_SBLAKE2 + 1)
 
 /* A suitably aligned type for stack allocations of hash contexts. */
 union git_hash_ctx {
 	git_SHA_CTX sha1;
+	git_BLAKE2B_CTX blake2b;
 };
 typedef union git_hash_ctx git_hash_ctx;
 
diff --git a/sha1_file.c b/sha1_file.c
index d9e2b1f285..5067b22a30 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -38,6 +38,12 @@ const struct object_id empty_tree_oid = {
 const struct object_id empty_blob_oid = {
 	EMPTY_BLOB_SHA1_BIN_LITERAL
 };
+const struct object_id empty_tree_oid_sblake2b = {
+	EMPTY_TREE_SBLAKE2B_BIN_LITERAL
+};
+const struct object_id empty_blob_oid_sblake2b = {
+	EMPTY_BLOB_SBLAKE2B_BIN_LITERAL
+};
 
 static void git_hash_sha1_init(void *ctx)
 {
@@ -54,6 +60,21 @@ static void git_hash_sha1_final(unsigned char *hash, void *ctx)
 	git_SHA1_Final(hash, (git_SHA_CTX *)ctx);
 }
 
+static void git_hash_sblake2b_init(void *ctx)
+{
+	blake2b_init((git_BLAKE2B_CTX *)ctx, GIT_SBLAKE2B_RAWSZ);
+}
+
+static void git_hash_sblake2b_update(void *ctx, const void *data, size_t len)
+{
+	blake2b_update((git_BLAKE2B_CTX *)ctx, data, len);
+}
+
+static void git_hash_sblake2b_final(unsigned char *hash, void *ctx)
+{
+	blake2b_final((git_BLAKE2B_CTX *)ctx, hash, GIT_SBLAKE2B_RAWSZ);
+}
+
 static void git_hash_unknown_init(void *ctx)
 {
 	die("trying to init unknown hash");
@@ -93,6 +114,18 @@ const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
 		&empty_tree_oid,
 		&empty_blob_oid,
 	},
+	{
+		"sblake2b",
+		/* "sb2b", big-endian */
+		0x73623262,
+		GIT_SBLAKE2B_RAWSZ,
+		GIT_SBLAKE2B_HEXSZ,
+		git_hash_sblake2b_init,
+		git_hash_sblake2b_update,
+		git_hash_sblake2b_final,
+		&empty_tree_oid_sblake2b,
+		&empty_blob_oid_sblake2b,
+	}
 };
 
 /*
diff --git a/t/helper/test-sblake2b.c b/t/helper/test-sblake2b.c
new file mode 100644
index 0000000000..6623aaa4d5
--- /dev/null
+++ b/t/helper/test-sblake2b.c
@@ -0,0 +1,56 @@
+#include "cache.h"
+
+int cmd_main(int ac, const char **av)
+{
+	git_hash_ctx ctx;
+	unsigned char hash[GIT_MAX_RAWSZ];
+	unsigned bufsz = 8192;
+	int binary = 0;
+	char *buffer;
+
+	if (ac == 2) {
+		if (!strcmp(av[1], "-b"))
+			binary = 1;
+		else
+			bufsz = strtoul(av[1], NULL, 10) * 1024 * 1024;
+	}
+
+	if (!bufsz)
+		bufsz = 8192;
+
+	while ((buffer = malloc(bufsz)) == NULL) {
+		fprintf(stderr, "bufsz %u is too big, halving...\n", bufsz);
+		bufsz /= 2;
+		if (bufsz < 1024)
+			die("OOPS");
+	}
+
+	hash_algos[GIT_HASH_SBLAKE2].init_fn(&ctx);
+
+	while (1) {
+		ssize_t sz, this_sz;
+		char *cp = buffer;
+		unsigned room = bufsz;
+		this_sz = 0;
+		while (room) {
+			sz = xread(0, cp, room);
+			if (sz == 0)
+				break;
+			if (sz < 0)
+				die_errno("test-sha1");
+			this_sz += sz;
+			cp += sz;
+			room -= sz;
+		}
+		if (this_sz == 0)
+			break;
+		hash_algos[GIT_HASH_SBLAKE2].update_fn(&ctx, buffer, this_sz);
+	}
+	hash_algos[GIT_HASH_SBLAKE2].final_fn(hash, &ctx);
+
+	if (binary)
+		fwrite(hash, 1, hash_algos[GIT_HASH_SBLAKE2].rawsz, stdout);
+	else
+		puts(sha1_to_hex(hash));
+	exit(0);
+}
Previous: brian m. carlsonNext: SZEDER Gábor
Message 3 of 9 in “alternate hash test”
  1. 0/2 alternate hash testbrian m. carlson, Jan 28, 2018
  2. 2/2 Switch default hash algorithm to short BLAKE2b for testingbrian m. carlson, Jan 28, 2018
  3. 1/2 Base test implementation for short BLAKE2b supportbrian m. carlson, Jan 28, 2018
  4. SZEDER GáborJan 28, 2018
  5. Ævar Arnfjörð BjarmasonJan 28, 2018
  6. brian m. carlsonJan 28, 2018
  7. Junio C HamanoJan 30, 2018
  8. Stefan BellerJan 31, 2018
  9. brian m. carlsonFeb 1, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.