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

[PATCH 10/10] Add time-stamping functionality to git tag

From
AWAnton Wuerfel <anton.wuerfel@fau.de>
Date
Mar 17, 2016, 18:47 UTC
Message-ID
<1458240421-3593-11-git-send-email-anton.wuerfel@fau.de>
In-Reply-To
<1458240421-3593-1-git-send-email-anton.wuerfel@fau.de>

This commit introduces command line options for git tag to allow adding trusted time-stamps from a Time Stamping Authority according to RFC3161.

The SHA-1 has used for a time-stamp signature is generated from the header data and the tag message, if present. After obtaining the time-stamp signature, it is inserted into the object header under the `timesig`-key in a custom PEM-like format. If the tag is also GPG-signed, the GPG signature includes the time-stamp signature to prevent attackers from altering the time-stamp signature or replacing it.

However, it is still possible to create tags with only a GPG signature or only a time-stamp, although it is recommended to additionally GPG-sign time-stamp signatures for the reasons stated above.

In contrast to the GPG signature, the time-stamp signatures are part of the header, emulating the way GPG signatures of signed commits are stored. This facilitates implementing RFC3161 time-stamps for commits eventually.

Signed-off-by: Anton Würfel <anton.wuerfel@fau.de>
Signed-off-by: Phillip Raffeck <phillip.raffeck@fau.de>
---
 builtin/tag.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 52 insertions(+), 3 deletions(-)
diff --git a/builtin/tag.c b/builtin/tag.c
index 1705c94..9b3d2a1 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -18,9 +18,10 @@
 #include "sha1-array.h"
 #include "column.h"
 #include "ref-filter.h"
+#include "rfc3161.h"
 
 static const char * const git_tag_usage[] = {
-	N_("git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] <tagname> [<head>]"),
+	N_("git tag [-a | -s | -u <key-id> | -t] [-f] [-m <msg> | -F <file>] <tagname> [<head>]"),
 	N_("git tag -d <tagname>..."),
 	N_("git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>]"
 		"\n\t\t[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]"),
@@ -118,6 +119,39 @@ static int do_sign(struct strbuf *buffer)
 	return sign_buffer(buffer, buffer, get_signing_key());
 }
 
+static int do_timesig(struct strbuf *buffer)
+{
+	struct strbuf sig = STRBUF_INIT;
+	int inspos, copypos;
+
+	/* find the end of the header */
+	inspos = strstr(buffer->buf, "\n\n") - buffer->buf + 1;
+
+	if (create_time_signature(buffer, &sig)) {
+		strbuf_release(&sig);
+		return -1;
+	}
+
+	for (copypos = 0; sig.buf[copypos]; ) {
+		const char *bol = sig.buf + copypos;
+		const char *eol = strchrnul(bol, '\n');
+		int len = (eol - bol) + !!*eol;
+
+		if (!copypos) {
+			strbuf_insert(buffer, inspos, time_sig_header,
+				      time_sig_header_len);
+			inspos += time_sig_header_len;
+		}
+		strbuf_insert(buffer, inspos++, " ", 1);
+		strbuf_insert(buffer, inspos, bol, len);
+		inspos += len;
+		copypos += len;
+	}
+	strbuf_release(&sig);
+
+	return 0;
+}
+
 static const char tag_template[] =
 	N_("\nWrite a message for tag:\n  %s\n"
 	"Lines starting with '%c' will be ignored.\n");
@@ -193,8 +227,11 @@ static void write_tag_body(int fd, const unsigned char *sha1)
 	free(buf);
 }
 
-static int build_tag_object(struct strbuf *buf, int sign, unsigned char *result)
+static int build_tag_object(struct strbuf *buf, int sign, int timesig,
+			    unsigned char *result)
 {
+	if (timesig && do_timesig(buf) < 0)
+		return error(_("unable to generate time-stamp signature"));
 	if (sign && do_sign(buf) < 0)
 		return error(_("unable to sign the tag"));
 	if (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0)
@@ -205,6 +242,7 @@ static int build_tag_object(struct strbuf *buf, int sign, unsigned char *result)
 struct create_tag_options {
 	unsigned int message_given:1;
 	unsigned int sign;
+	unsigned int timesig;
 	enum {
 		CLEANUP_NONE,
 		CLEANUP_SPACE,
@@ -276,7 +314,7 @@ static void create_tag(const unsigned char *object, const char *tag,
 
 	strbuf_insert(buf, 0, header_buf, header_len);
 
-	if (build_tag_object(buf, opt->sign, result) < 0) {
+	if (build_tag_object(buf, opt->sign, opt->timesig, result) < 0) {
 		if (path)
 			fprintf(stderr, _("The tag message has been left in %s\n"),
 				path);
@@ -350,6 +388,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 			     N_("tag message"), parse_msg_arg),
 		OPT_FILENAME('F', "file", &msgfile, N_("read message from file")),
 		OPT_BOOL('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
+		OPT_BOOL('t', "timestamp", &opt.timesig, N_("add trusted RFC3161 time-stamp")),
 		OPT_STRING(0, "cleanup", &cleanup_arg, N_("mode"),
 			N_("how to strip spaces and #comments from message")),
 		OPT_STRING('u', "local-user", &keyid, N_("key-id"),
@@ -387,6 +426,16 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	}
 	if (opt.sign)
 		annotate = 1;
+
+#if defined(NO_CURL) || defined(NO_OPENSSL)
+	if (opt.timesig)
+		return error("git has been compiled without RFC3161 time-stamp support. "
+			     "NO_CURL and NO_OPENSSL must not be defined");
+#else
+	if (opt.timesig)
+		annotate = 1;
+#endif
+
 	if (argc == 0 && !cmdmode)
 		cmdmode = 'l';
 
-- 
2.8.0.rc0.62.gfc8aefa.dirty
Previous: Anton Wuerfel
Message 11 of 11 in “Adding RFC3161 time-stamps to tags”
  1. 00/10 Adding RFC3161 time-stamps to tagsAnton Wuerfel, Mar 17, 2016
  2. 01/10 Add Testcases for time-stamping functionalityAnton Wuerfel, Mar 17, 2016
  3. 02/10 Documentation for time-stamping functionalityAnton Wuerfel, Mar 17, 2016
  4. 03/10 Documentation: Whitespace fixAnton Wuerfel, Mar 17, 2016
  5. 04/10 Extending internal CURL wrapper for POST uploadAnton Wuerfel, Mar 17, 2016
  6. 05/10 Make PGP macros globalAnton Wuerfel, Mar 17, 2016
  7. 06/10 Add basic RFC3161 functionalityAnton Wuerfel, Mar 17, 2016
  8. 07/10 Add git-http-timestamp helper toolAnton Wuerfel, Mar 17, 2016
  9. 08/10 Adding time-stamping helper toolAnton Wuerfel, Mar 17, 2016
  10. 09/10 Add time-stamping functionality to git verify-tagAnton Wuerfel, Mar 17, 2016
  11. 10/10 Add time-stamping functionality to git tagAnton Wuerfel, Mar 17, 2016

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.