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>
This commit is contained in:
brian m. carlson 2020-02-22 20:17:42 +00:00 коммит произвёл Junio C Hamano
Родитель e02a7141f8
Коммит 42d4e1d112
5 изменённых файлов: 62 добавлений и 12 удалений

Просмотреть файл

@ -1659,7 +1659,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
}
if (amend) {
const char *exclude_gpgsig[2] = { "gpgsig", NULL };
const char *exclude_gpgsig[3] = { "gpgsig", "gpgsig-sha256", NULL };
extra = read_commit_extra_headers(current_head, exclude_gpgsig);
} else {
struct commit_extra_header **tail = &extra;

Просмотреть файл

@ -961,14 +961,22 @@ cleanup_return:
return ret;
}
static const char gpg_sig_header[] = "gpgsig";
static const int gpg_sig_header_len = sizeof(gpg_sig_header) - 1;
/*
* Indexed by hash algorithm identifier.
*/
static const char *gpg_sig_headers[] = {
NULL,
"gpgsig",
"gpgsig-sha256",
};
static int do_sign_commit(struct strbuf *buf, const char *keyid)
{
struct strbuf sig = STRBUF_INIT;
int inspos, copypos;
const char *eoh;
const char *gpg_sig_header = gpg_sig_headers[hash_algo_by_ptr(the_hash_algo)];
int gpg_sig_header_len = strlen(gpg_sig_header);
/* find the end of the header */
eoh = strstr(buf->buf, "\n\n");
@ -1010,6 +1018,8 @@ int parse_signed_commit(const struct commit *commit,
const char *buffer = get_commit_buffer(commit, &size);
int in_signature, saw_signature = -1;
const char *line, *tail;
const char *gpg_sig_header = gpg_sig_headers[hash_algo_by_ptr(the_hash_algo)];
int gpg_sig_header_len = strlen(gpg_sig_header);
line = buffer;
tail = buffer + size;
@ -1056,11 +1066,17 @@ int remove_signature(struct strbuf *buf)
if (in_signature && line[0] == ' ')
sig_end = next;
else if (starts_with(line, gpg_sig_header) &&
line[gpg_sig_header_len] == ' ') {
sig_start = line;
sig_end = next;
in_signature = 1;
else if (starts_with(line, "gpgsig")) {
int i;
for (i = 1; i < GIT_HASH_NALGOS; i++) {
const char *p;
if (skip_prefix(line, gpg_sig_headers[i], &p) &&
*p == ' ') {
sig_start = line;
sig_end = next;
in_signature = 1;
}
}
} else {
if (*line == '\n')
/* dump the whole remainder of the buffer */

Просмотреть файл

@ -1321,7 +1321,7 @@ static int try_to_commit(struct repository *r,
return -1;
if (flags & AMEND_MSG) {
const char *exclude_gpgsig[] = { "gpgsig", NULL };
const char *exclude_gpgsig[] = { "gpgsig", "gpgsig-sha256", NULL };
const char *out_enc = get_commit_output_encoding();
const char *message = logmsg_reencode(current_head, NULL,
out_enc);

Просмотреть файл

@ -133,6 +133,30 @@ test_expect_success 'other worktree HEAD link pointing at a funny place' '
test_i18ngrep "worktrees/other/HEAD points to something strange" out
'
test_expect_success 'commit with multiple signatures is okay' '
git cat-file commit HEAD >basis &&
cat >sigs <<-EOF &&
gpgsig -----BEGIN PGP SIGNATURE-----
VGhpcyBpcyBub3QgcmVhbGx5IGEgc2lnbmF0dXJlLg==
-----END PGP SIGNATURE-----
gpgsig-sha256 -----BEGIN PGP SIGNATURE-----
VGhpcyBpcyBub3QgcmVhbGx5IGEgc2lnbmF0dXJlLg==
-----END PGP SIGNATURE-----
EOF
sed -e "/^committer/q" basis >okay &&
cat sigs >>okay &&
echo >>okay &&
sed -e "1,/^$/d" basis >>okay &&
cat okay &&
new=$(git hash-object -t commit -w --stdin <okay) &&
test_when_finished "remove_object $new" &&
git update-ref refs/heads/bogus "$new" &&
test_when_finished "git update-ref -d refs/heads/bogus" &&
git fsck 2>out &&
cat out &&
! grep "commit $new" out
'
test_expect_success 'email without @ is okay' '
git cat-file commit HEAD >basis &&
sed "s/@/AT/" basis >okay &&

Просмотреть файл

@ -6,6 +6,11 @@ GNUPGHOME_NOT_USED=$GNUPGHOME
. "$TEST_DIRECTORY/lib-gpg.sh"
test_expect_success GPG 'create signed commits' '
test_oid_cache <<-\EOF &&
header sha1:gpgsig
header sha256:gpgsig-sha256
EOF
test_when_finished "test_unconfig commit.gpgsign" &&
echo 1 >file && git add file &&
@ -155,6 +160,11 @@ test_expect_success GPG 'verify signatures with --raw' '
)
'
test_expect_success GPG 'proper header is used for hash algorithm' '
git cat-file commit fourth-signed >output &&
grep "^$(test_oid header) -----BEGIN PGP SIGNATURE-----" output
'
test_expect_success GPG 'show signed commit with signature' '
git show -s initial >commit &&
git show -s --show-signature initial >show &&
@ -162,7 +172,7 @@ test_expect_success GPG 'show signed commit with signature' '
git cat-file commit initial >cat &&
grep -v -e "gpg: " -e "Warning: " show >show.commit &&
grep -e "gpg: " -e "Warning: " show >show.gpg &&
grep -v "^ " cat | grep -v "^gpgsig " >cat.commit &&
grep -v "^ " cat | grep -v "^$(test_oid header) " >cat.commit &&
test_cmp show.commit commit &&
test_cmp show.gpg verify.2 &&
test_cmp cat.commit verify.1
@ -299,10 +309,10 @@ test_expect_success GPG 'check config gpg.format values' '
test_expect_success GPG 'detect fudged commit with double signature' '
sed -e "/gpgsig/,/END PGP/d" forged1 >double-base &&
sed -n -e "/gpgsig/,/END PGP/p" forged1 | \
sed -e "s/^gpgsig//;s/^ //" | gpg --dearmor >double-sig1.sig &&
sed -e "s/^$(test_oid header)//;s/^ //" | gpg --dearmor >double-sig1.sig &&
gpg -o double-sig2.sig -u 29472784 --detach-sign double-base &&
cat double-sig1.sig double-sig2.sig | gpg --enarmor >double-combined.asc &&
sed -e "s/^\(-.*\)ARMORED FILE/\1SIGNATURE/;1s/^/gpgsig /;2,\$s/^/ /" \
sed -e "s/^\(-.*\)ARMORED FILE/\1SIGNATURE/;1s/^/$(test_oid header) /;2,\$s/^/ /" \
double-combined.asc > double-gpgsig &&
sed -e "/committer/r double-gpgsig" double-base >double-commit &&
git hash-object -w -t commit double-commit >double-commit.commit &&