I am working on creating a signed commit via API in GitHub workflow so I just read document https://developer.github.com/v3/git/commits/#create-a-commit
I am creating a payload file with a sample data tree
827efc6d56897b048c772eb4087f854f46256132 parent
7d1b31e74ee336d15cbd21741bc88a537ed063a0 author Mona Octocat
<octocat@github.com> 1215576810 +1200 committer Mona Octocat
<octocat@github.com> 1215576810 +1200
my commit message
But I am getting Invalid in the sign commit I want to know what actually is required to do a signed commit via API as I am unable to find any blog or post.
First of all, you should try to understand how a Git commit is signed.
To save some text, refer to What data is being signed when you `git commit --gpg-sign=<key-id>`? for details of the signed data - I'm going to only reproduce it here. Apparently you won't have GitHub's private key, so you must bring your own key. Upload it in GitHub settings so it becomes "trusted".
First, perform the to-be-signed commit locally so you have the commit data. For example, I'm using the HEAD
commit of my repository, at the time of writing this answer:
~ $ cd iBug-source
~/iBug-source $ git log -1 HEAD
commit 351e7fe08176e35a9e4c91be2122921ada3cac3a (HEAD -> master, origin/master, origin/HEAD)
Author: iBug <git@ibugone.com>
Date: Mon Nov 16 02:51:19 2020 +0800
Force redirect
Extract the payload for the GPG signature (the message part) from Git. You'll need to strip off the trailing newline (as I do with perl
).
~/iBug-source $ git cat-file commit HEAD
tree fe9d12667f47065738ebcb3f6dd665a4150be267
parent fb4c5fb11f79142fc1f6f86fd7442274839626fb
author iBug <git@ibugone.com> 1605466279 +0800
committer iBug <git@ibugone.com> 1605466626 +0800
Force redirect
~/iBug-source $ git cat-file commit HEAD | perl -pe 'chomp if eof' > commit
Now I have the message payload in the commit
file. I want to create a signature using my own key.
Because Git expects a signature algorithm of SHA-1, I supplied --digest-algo SHA1
to the CLI invocation. I also added --clear-sign
(signature only, do not include message body) and --armor
(output ASCII armor format)
~/iBug-source $ gpg --clear-sign --digest-algo SHA1 --armor --local-user 0xA2C63304 commit
The above command produced the file commit.asc
with the following content:
-----BEGIN PGP SIGNATURE-----
iQIzBAEBAgAdFiEE1KqdrSj5MOe58w687j9yiKLGMwQFAl+ynVQACgkQ7j9yiKLG
MwR21BAAp3pzyUhA2/5tn/DrO+bbD9X9BQ6GHLHtiaG8gjuWmaGHzjR2XUugTrRl
aOluWR6//yNR9Uf3qIyxZahRYWYVy3Pl2UK8C+4s4alo7IjiF/7oKD3OVu5bjLvm
GcbUfeyJQtOkNNH5o0o/einIoqhNCNgiFWjjsLcxPsG2bsNnF5Kmb8ONS3gArJQB
7wT68sdj/oH82zCJU6bgEXohv3f+ZS82e8jX5jJBRL+ljz3crUl3DsgjsoKJiiUp
ZjcfNffNQu4wEB6XK2zca5IgGfcBO3MF0yA13sh1JwKa54ZEikAI4T5lVfRkjUn7
LPkwpMhw3033NyyrTFXF48i9oRSoMocJYmDOncY8Mgc+CJArvn/fT34bZ9rXH01Y
qpeSAZv7AgyXc3jSQHZPjo76i/C9BwwZ1EoGUm4svom/0ejnOteM1Ff3grVnqipX
Xo78a1BYHr0aLBxPpPaHMRlOdcMo0UYnqIm+P7VXtY0WxvPjXgemtSsXYrAMKSaa
sAJ5Dv0jqYwhbQcVb5sGLC8zg+QmSbhV4HbrXmOcP8QC9H89EJSPzLQivQePGZrQ
284vWTueNk68NyUQ5BUfXLIjYX/n6kgOeISNcvhDCVgWkvZNfN57fEOtq2FTsFKz
Dg4ukCQkabA+lFB3AiVdhhLZT5ucjSFFfnLUkwaULRP5XEgQhH8=
=YxhM
-----END PGP SIGNATURE-----
This is the signature you want in the signature
JSON field, as given by GitHub documentation.
Construct the API payload JSON:
{
"message": "Force redirect",
"author": {
"name": "iBug",
"email": "git@ibugone.com",
"date": "2020-11-16T02:51:19+08:00"
},
"committer": {
"name": "iBug",
"email": "git@ibugone.com",
"date": "2020-11-16T02:57:06+08:00"
},
"parents": [
"fb4c5fb11f79142fc1f6f86fd7442274839626fb"
],
"tree": "fe9d12667f47065738ebcb3f6dd665a4150be267",
"signature": "-----BEGIN PGP SIGNATURE-----\n\niQIzBAEBAgAdFiEE1KqdrSj5MOe58w687j9yiKLGMwQFAl+ynVQACgkQ7j9yiKLG\nMwR21BAAp3pzyUhA2/5tn/DrO+bbD9X9BQ6GHLHtiaG8gjuWmaGHzjR2XUugTrRl\naOluWR6//yNR9Uf3qIyxZahRYWYVy3Pl2UK8C+4s4alo7IjiF/7oKD3OVu5bjLvm\nGcbUfeyJQtOkNNH5o0o/einIoqhNCNgiFWjjsLcxPsG2bsNnF5Kmb8ONS3gArJQB\n7wT68sdj/oH82zCJU6bgEXohv3f+ZS82e8jX5jJBRL+ljz3crUl3DsgjsoKJiiUp\nZjcfNffNQu4wEB6XK2zca5IgGfcBO3MF0yA13sh1JwKa54ZEikAI4T5lVfRkjUn7\nLPkwpMhw3033NyyrTFXF48i9oRSoMocJYmDOncY8Mgc+CJArvn/fT34bZ9rXH01Y\nqpeSAZv7AgyXc3jSQHZPjo76i/C9BwwZ1EoGUm4svom/0ejnOteM1Ff3grVnqipX\nXo78a1BYHr0aLBxPpPaHMRlOdcMo0UYnqIm+P7VXtY0WxvPjXgemtSsXYrAMKSaa\nsAJ5Dv0jqYwhbQcVb5sGLC8zg+QmSbhV4HbrXmOcP8QC9H89EJSPzLQivQePGZrQ\n284vWTueNk68NyUQ5BUfXLIjYX/n6kgOeISNcvhDCVgWkvZNfN57fEOtq2FTsFKz\nDg4ukCQkabA+lFB3AiVdhhLZT5ucjSFFfnLUkwaULRP5XEgQhH8=\n=YxhM\n-----END PGP SIGNATURE-----\n"
}
Send it to GitHub API:
~/iBug-source $ curl -X POST \
-H 'Authorization: token xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
-H 'Accept: application/vnd.github.v3+json' \
-H 'Content-Type: application/json' \
--data @payload.json \
https://api.github.com/repos/iBug/iBug-source/git/commits
See the response (truncated):
{
"sha": "36105785c8665a400226c54a16cc4583b8f28ebd",
// Truncated
}
See the commit (archive) on GitHub website in action!
Obviously, all the above steps can be done with your favorite toolchain, and you don't even have to perform the git commit
. For example, the manually-constructed Git object is as follows, without the trailing newline:
tree fe9d12667f47065738ebcb3f6dd665a4150be267
parent fb4c5fb11f79142fc1f6f86fd7442274839626fb
author iBug <git@ibugone.com> 1605466279 +0800
committer iBug <git@ibugone.com> 1605466626 +0800
gpgsig -----BEGIN PGP SIGNATURE-----
iQIzBAEBAgAdFiEE1KqdrSj5MOe58w687j9yiKLGMwQFAl+ynVQACgkQ7j9yiKLG
MwR21BAAp3pzyUhA2/5tn/DrO+bbD9X9BQ6GHLHtiaG8gjuWmaGHzjR2XUugTrRl
aOluWR6//yNR9Uf3qIyxZahRYWYVy3Pl2UK8C+4s4alo7IjiF/7oKD3OVu5bjLvm
GcbUfeyJQtOkNNH5o0o/einIoqhNCNgiFWjjsLcxPsG2bsNnF5Kmb8ONS3gArJQB
7wT68sdj/oH82zCJU6bgEXohv3f+ZS82e8jX5jJBRL+ljz3crUl3DsgjsoKJiiUp
ZjcfNffNQu4wEB6XK2zca5IgGfcBO3MF0yA13sh1JwKa54ZEikAI4T5lVfRkjUn7
LPkwpMhw3033NyyrTFXF48i9oRSoMocJYmDOncY8Mgc+CJArvn/fT34bZ9rXH01Y
qpeSAZv7AgyXc3jSQHZPjo76i/C9BwwZ1EoGUm4svom/0ejnOteM1Ff3grVnqipX
Xo78a1BYHr0aLBxPpPaHMRlOdcMo0UYnqIm+P7VXtY0WxvPjXgemtSsXYrAMKSaa
sAJ5Dv0jqYwhbQcVb5sGLC8zg+QmSbhV4HbrXmOcP8QC9H89EJSPzLQivQePGZrQ
284vWTueNk68NyUQ5BUfXLIjYX/n6kgOeISNcvhDCVgWkvZNfN57fEOtq2FTsFKz
Dg4ukCQkabA+lFB3AiVdhhLZT5ucjSFFfnLUkwaULRP5XEgQhH8=
=YxhM
-----END PGP SIGNATURE-----
Force redirect
Using git hash-object -t commit
on the file, the same commit SHA is reproduced.
Now trying to store this crafted commit object into Git database.
Prepend with the object type header:
~/iBug-source $ printf 'commit %s\0' $(wc -c < commit) | cat - commit > object
Get the hash of the complete object:
~/iBug-source $ sha1sum object
36105785c8665a400226c54a16cc4583b8f28ebd
Create directory for the object:
~/iBug-source $ mkdir -p .git/objects/36/
Compress the object using zlib (.zz
) algorithm and save the object:
~/iBug-source $ pigz -cz object > .git/objects/36/105785c8665a400226c54a16cc4583b8f28ebd
Try if Git recognized this crafted object:
~/iBug-source $ git log -1 36105785c8665a400226c54a16cc4583b8f28ebd
commit 36105785c8665a400226c54a16cc4583b8f28ebd
Author: iBug <git@ibugone.com>
Date: Mon Nov 16 02:51:19 2020 +0800
Force redirect