commit: use expected signature header for SHA-256
The transition plan anticipates that we will allow signatures using multiple algorithms in a single commit. In order to do so, we need to use a different header per algorithm so that it will be obvious over which data to compute the signature. The transition plan specifies that we should use "gpgsig-sha256", so wire up the commit code such that it can write and parse the current algorithm, and it can remove the headers for any algorithm when creating a new commit. Add tests to ensure that we write using the right header and that git fsck doesn't reject these commits. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
brian m. carlson committed
Feb 22, 2020 at 20:17 UTC
42d4e1d1128fa1cb56032ac58f65ea3dd1296a9a
5 files changed
+62
-12
builtin/commit.c
+1
-1
@@ -1659,7 +1659,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
1659
}
1660
1661
if (amend) {
1662
- const char *exclude_gpgsig[2] = { "gpgsig", NULL };
1662
+ const char *exclude_gpgsig[3] = { "gpgsig", "gpgsig-sha256", NULL };
1663
extra = read_commit_extra_headers(current_head, exclude_gpgsig);
1664
} else {
1665
struct commit_extra_header **tail = &extra;
commit.c
+23
-7
@@ -961,14 +961,22 @@ cleanup_return:
961
return ret;
962
}
963
964
-static const char gpg_sig_header[] = "gpgsig";
965
-static const int gpg_sig_header_len = sizeof(gpg_sig_header) - 1;
964
+/*
965
+ * Indexed by hash algorithm identifier.
966
+ */
967
+static const char *gpg_sig_headers[] = {
968
+ NULL,
969
+ "gpgsig",
970
+ "gpgsig-sha256",
971
+};
972
973
static int do_sign_commit(struct strbuf *buf, const char *keyid)
974
{
975
struct strbuf sig = STRBUF_INIT;
976
int inspos, copypos;
977
const char *eoh;
978
+ const char *gpg_sig_header = gpg_sig_headers[hash_algo_by_ptr(the_hash_algo)];
979
+ int gpg_sig_header_len = strlen(gpg_sig_header);
980
981
/* find the end of the header */
982
eoh = strstr(buf->buf, "\n\n");
@@ -1010,6 +1018,8 @@ int parse_signed_commit(const struct commit *commit,
1018
const char *buffer = get_commit_buffer(commit, &size);
1019
int in_signature, saw_signature = -1;
1020
const char *line, *tail;
1021
+ const char *gpg_sig_header = gpg_sig_headers[hash_algo_by_ptr(the_hash_algo)];
1022
+ int gpg_sig_header_len = strlen(gpg_sig_header);
1023
1024
line = buffer;
1025
tail = buffer + size;
@@ -1056,11 +1066,17 @@ int remove_signature(struct strbuf *buf)
1066
1067
if (in_signature && line[0] == ' ')
1068
sig_end = next;
1059
- else if (starts_with(line, gpg_sig_header) &&
1060
- line[gpg_sig_header_len] == ' ') {
1061
- sig_start = line;
1062
- sig_end = next;
1063
- in_signature = 1;
1069
+ else if (starts_with(line, "gpgsig")) {
1070
+ int i;
1071
+ for (i = 1; i < GIT_HASH_NALGOS; i++) {
1072
+ const char *p;
1073
+ if (skip_prefix(line, gpg_sig_headers[i], &p) &&
1074
+ *p == ' ') {
1075
+ sig_start = line;
1076
+ sig_end = next;
1077
+ in_signature = 1;
1078
+ }
1079
+ }
1080
} else {
1081
if (*line == '\n')
1082
/* dump the whole remainder of the buffer */
sequencer.c
+1
-1
@@ -1321,7 +1321,7 @@ static int try_to_commit(struct repository *r,
1321
return -1;
1322
1323
if (flags & AMEND_MSG) {
1324
- const char *exclude_gpgsig[] = { "gpgsig", NULL };
1324
+ const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL };
1325
const char *out_enc = get_commit_output_encoding();
1326
const char *message = logmsg_reencode(current_head, NULL,
1327
out_enc);
t/t1450-fsck.sh
+24
@@ -133,6 +133,30 @@ test_expect_success 'other worktree HEAD link pointing at a funny place' '
133
test_i18ngrep "worktrees/other/HEAD points to something strange" out
134
'
135
136
+test_expect_success 'commit with multiple signatures is okay' '
137
+ git cat-file commit HEAD >basis &&
138
+ cat >sigs <<-EOF &&
139
+ gpgsig -----BEGIN PGP SIGNATURE-----
140
+ VGhpcyBpcyBub3QgcmVhbGx5IGEgc2lnbmF0dXJlLg==
141
+ -----END PGP SIGNATURE-----
142
+ gpgsig-sha256 -----BEGIN PGP SIGNATURE-----
143
+ VGhpcyBpcyBub3QgcmVhbGx5IGEgc2lnbmF0dXJlLg==
144
+ -----END PGP SIGNATURE-----
145
+ EOF
146
+ sed -e "/^committer/q" basis >okay &&
147
+ cat sigs >>okay &&
148
+ echo >>okay &&
149
+ sed -e "1,/^$/d" basis >>okay &&
150
+ cat okay &&
151
+ new=$(git hash-object -t commit -w --stdin <okay) &&
152
+ test_when_finished "remove_object $new" &&
153
+ git update-ref refs/heads/bogus "$new" &&
154
+ test_when_finished "git update-ref -d refs/heads/bogus" &&
155
+ git fsck 2>out &&
156
+ cat out &&
157
+ ! grep "commit $new" out
158
+'
159
+
160
test_expect_success 'email without @ is okay' '
161
git cat-file commit HEAD >basis &&
162
sed "s/@/AT/" basis >okay &&
t/t7510-signed-commit.sh
+13
-3
@@ -6,6 +6,11 @@ GNUPGHOME_NOT_USED=$GNUPGHOME
6
. "$TEST_DIRECTORY/lib-gpg.sh"
7
8
test_expect_success GPG 'create signed commits' '
9
+ test_oid_cache <<-\EOF &&
10
+ header sha1:gpgsig
11
+ header sha256:gpgsig-sha256
12
+ EOF
13
+
14
test_when_finished "test_unconfig commit.gpgsign" &&
15
16
echo 1 >file && git add file &&
@@ -155,6 +160,11 @@ test_expect_success GPG 'verify signatures with --raw' '
160
)
161
'
162
163
+test_expect_success GPG 'proper header is used for hash algorithm' '
164
+ git cat-file commit fourth-signed >output &&
165
+ grep "^$(test_oid header) -----BEGIN PGP SIGNATURE-----" output
166
+'
167
+
168
test_expect_success GPG 'show signed commit with signature' '
169
git show -s initial >commit &&
170
git show -s --show-signature initial >show &&
@@ -162,7 +172,7 @@ test_expect_success GPG 'show signed commit with signature' '
172
git cat-file commit initial >cat &&
173
grep -v -e "gpg: " -e "Warning: " show >show.commit &&
174
grep -e "gpg: " -e "Warning: " show >show.gpg &&
165
- grep -v "^ " cat | grep -v "^gpgsig " >cat.commit &&
175
+ grep -v "^ " cat | grep -v "^$(test_oid header) " >cat.commit &&
176
test_cmp show.commit commit &&
177
test_cmp show.gpg verify.2 &&
178
test_cmp cat.commit verify.1
@@ -299,10 +309,10 @@ test_expect_success GPG 'check config gpg.format values' '
309
test_expect_success GPG 'detect fudged commit with double signature' '
310
sed -e "/gpgsig/,/END PGP/d" forged1 >double-base &&
311
sed -n -e "/gpgsig/,/END PGP/p" forged1 | \
302
- sed -e "s/^gpgsig//;s/^ //" | gpg --dearmor >double-sig1.sig &&
312
+ sed -e "s/^$(test_oid header)//;s/^ //" | gpg --dearmor >double-sig1.sig &&
313
gpg -o double-sig2.sig -u 29472784 --detach-sign double-base &&
314
cat double-sig1.sig double-sig2.sig | gpg --enarmor >double-combined.asc &&
305
- sed -e "s/^\(-.*\)ARMORED FILE/\1SIGNATURE/;1s/^/gpgsig /;2,\$s/^/ /" \
315
+ sed -e "s/^\(-.*\)ARMORED FILE/\1SIGNATURE/;1s/^/$(test_oid header) /;2,\$s/^/ /" \
316
double-combined.asc > double-gpgsig &&
317
sed -e "/committer/r double-gpgsig" double-base >double-commit &&
318
git hash-object -w -t commit double-commit >double-commit.commit &&