Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a65afb7

Browse files
committed
Introduce git_commit_extract_signature
This returns the GPG signature for a commit and its contents without the signature block, allowing for the verification of the commit's signature.
1 parent 0f9d154 commit a65afb7

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

include/git2/commit.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,18 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor(
263263
*/
264264
GIT_EXTERN(int) git_commit_header_field(git_buf *out, const git_commit *commit, const char *field);
265265

266+
/**
267+
* Extract the signature from a commit
268+
*
269+
* @param signature the signature block
270+
* @param signed_data signed data; this is the commit contents minus the signature block
271+
* @param repo the repository in which the commit exists
272+
* @param commit_id the commit from which to extract the data
273+
* @param field the name of the header field containing the signature
274+
* block; pass `NULL` to extract the default 'gpgsig'
275+
*/
276+
GIT_EXTERN(int) git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_repository *repo, git_oid *commit_id, const char *field);
277+
266278
/**
267279
* Create new commit in the repository from a list of `git_object` pointers
268280
*

src/commit.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,3 +616,89 @@ int git_commit_header_field(git_buf *out, const git_commit *commit, const char *
616616
giterr_set_oom();
617617
return -1;
618618
}
619+
620+
int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_repository *repo, git_oid *commit_id, const char *field)
621+
{
622+
git_odb_object *obj;
623+
git_odb *odb;
624+
const char *buf;
625+
const char *h, *eol;
626+
int error;
627+
628+
git_buf_sanitize(signature);
629+
git_buf_sanitize(signed_data);
630+
631+
if (!field)
632+
field = "gpgsig";
633+
634+
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
635+
return error;
636+
637+
if ((error = git_odb_read(&obj, odb, commit_id)) < 0)
638+
return error;
639+
640+
buf = git_odb_object_data(obj);
641+
642+
while ((h = strchr(buf, '\n')) && h[1] != '\0' && h[1] != '\n') {
643+
h++;
644+
if (git__prefixcmp(buf, field)) {
645+
if (git_buf_put(signed_data, buf, h - buf) < 0)
646+
return -1;
647+
648+
buf = h;
649+
continue;
650+
}
651+
652+
h = buf;
653+
h += strlen(field);
654+
eol = strchr(h, '\n');
655+
if (h[0] != ' ') {
656+
buf = h;
657+
continue;
658+
}
659+
if (!eol)
660+
goto malformed;
661+
662+
h++; /* skip the SP */
663+
664+
git_buf_put(signature, h, eol - h);
665+
if (git_buf_oom(signature))
666+
goto oom;
667+
668+
/* If the next line starts with SP, it's multi-line, we must continue */
669+
while (eol[1] == ' ') {
670+
git_buf_putc(signature, '\n');
671+
h = eol + 2;
672+
eol = strchr(h, '\n');
673+
if (!eol)
674+
goto malformed;
675+
676+
git_buf_put(signature, h, eol - h);
677+
}
678+
679+
if (git_buf_oom(signature))
680+
goto oom;
681+
682+
git_odb_object_free(obj);
683+
return git_buf_puts(signed_data, eol+1);
684+
}
685+
686+
giterr_set(GITERR_INVALID, "this commit is not signed");
687+
error = GIT_ENOTFOUND;
688+
goto cleanup;
689+
690+
malformed:
691+
giterr_set(GITERR_OBJECT, "malformed header");
692+
error = -1;
693+
goto cleanup;
694+
oom:
695+
giterr_set_oom();
696+
error = -1;
697+
goto cleanup;
698+
699+
cleanup:
700+
git_odb_object_free(obj);
701+
git_buf_clear(signature);
702+
git_buf_clear(signed_data);
703+
return error;
704+
}

tests/commit/parse.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,3 +456,52 @@ cpxtDQQMGYFpXK/71stq\n\
456456
git_buf_free(&buf);
457457
git_commit__free(commit);
458458
}
459+
460+
void test_commit_parse__extract_signature(void)
461+
{
462+
git_odb *odb;
463+
git_oid commit_id;
464+
git_buf signature = GIT_BUF_INIT, signed_data = GIT_BUF_INIT;
465+
const char *gpgsig = "-----BEGIN PGP SIGNATURE-----\n\
466+
Version: GnuPG v1.4.12 (Darwin)\n\
467+
\n\
468+
iQIcBAABAgAGBQJQ+FMIAAoJEH+LfPdZDSs1e3EQAJMjhqjWF+WkGLHju7pTw2al\n\
469+
o6IoMAhv0Z/LHlWhzBd9e7JeCnanRt12bAU7yvYp9+Z+z+dbwqLwDoFp8LVuigl8\n\
470+
JGLcnwiUW3rSvhjdCp9irdb4+bhKUnKUzSdsR2CK4/hC0N2i/HOvMYX+BRsvqweq\n\
471+
AsAkA6dAWh+gAfedrBUkCTGhlNYoetjdakWqlGL1TiKAefEZrtA1TpPkGn92vbLq\n\
472+
SphFRUY9hVn1ZBWrT3hEpvAIcZag3rTOiRVT1X1flj8B2vGCEr3RrcwOIZikpdaW\n\
473+
who/X3xh/DGbI2RbuxmmJpxxP/8dsVchRJJzBwG+yhwU/iN3MlV2c5D69tls/Dok\n\
474+
6VbyU4lm/ae0y3yR83D9dUlkycOnmmlBAHKIZ9qUts9X7mWJf0+yy2QxJVpjaTGG\n\
475+
cmnQKKPeNIhGJk2ENnnnzjEve7L7YJQF6itbx5VCOcsGh3Ocb3YR7DMdWjt7f8pu\n\
476+
c6j+q1rP7EpE2afUN/geSlp5i3x8aXZPDj67jImbVCE/Q1X9voCtyzGJH7MXR0N9\n\
477+
ZpRF8yzveRfMH8bwAJjSOGAFF5XkcR/RNY95o+J+QcgBLdX48h+ZdNmUf6jqlu3J\n\
478+
7KmTXXQcOVpN6dD3CmRFsbjq+x6RHwa8u1iGn+oIkX908r97ckfB/kHKH7ZdXIJc\n\
479+
cpxtDQQMGYFpXK/71stq\n\
480+
=ozeK\n\
481+
-----END PGP SIGNATURE-----";
482+
483+
const char *data = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\
484+
parent 34734e478d6cf50c27c9d69026d93974d052c454\n\
485+
author Ben Burkert <[email protected]> 1358451456 -0800\n\
486+
committer Ben Burkert <[email protected]> 1358451456 -0800\n\
487+
\n\
488+
a simple commit which works\n";
489+
490+
491+
cl_git_pass(git_repository_odb__weakptr(&odb, g_repo));
492+
cl_git_pass(git_odb_write(&commit_id, odb, passing_commit_cases[4], strlen(passing_commit_cases[4]), GIT_OBJ_COMMIT));
493+
494+
cl_git_pass(git_commit_extract_signature(&signature, &signed_data, g_repo, &commit_id, NULL));
495+
cl_assert_equal_s(gpgsig, signature.ptr);
496+
cl_assert_equal_s(data, signed_data.ptr);
497+
498+
git_buf_clear(&signature);
499+
git_buf_clear(&signed_data);
500+
501+
cl_git_pass(git_commit_extract_signature(&signature, &signed_data, g_repo, &commit_id, "gpgsig"));
502+
cl_assert_equal_s(gpgsig, signature.ptr);
503+
cl_assert_equal_s(data, signed_data.ptr);
504+
505+
git_buf_free(&signature);
506+
git_buf_free(&signed_data);
507+
}

0 commit comments

Comments
 (0)