{"id":734,"date":"2018-08-03T14:04:04","date_gmt":"2018-08-03T12:04:04","guid":{"rendered":"https:\/\/blogs.gentoo.org\/mgorny\/?p=734"},"modified":"2018-08-13T17:58:38","modified_gmt":"2018-08-13T15:58:38","slug":"verifying-repo-gentoo-git-with-gverify","status":"publish","type":"post","link":"https:\/\/blogs.gentoo.org\/mgorny\/2018\/08\/03\/verifying-repo-gentoo-git-with-gverify\/","title":{"rendered":"Verifying repo\/gentoo.git with gverify"},"content":{"rendered":"<p>Git commit signatures are recursive by\u00a0design \u2014 that is, each signature covers not only the\u00a0commit in\u00a0question but also indirectly all past commits, via\u00a0tree and\u00a0parent commit hashes.  This makes user-side commit verification much simpler, as\u00a0the\u00a0user needs only to\u00a0verify the\u00a0signature on\u00a0the\u00a0most recent commit; with the\u00a0assumption that the\u00a0developer making it has verified the\u00a0earlier commit and\u00a0so on.  Sadly, this is usually not the\u00a0case at\u00a0the\u00a0moment.<\/p>\n<p>Most of\u00a0the\u00a0Gentoo developers do not really verify the\u00a0base upon which they are making their commits.  While they might verify the\u00a0commits when pulling before starting to\u00a0work on\u00a0their changes, it is rather unlikely that they verify the\u00a0correctness when they repeatedly need to\u00a0rebase before pushing.  Usually this does not cause problems as\u00a0Gentoo Infrastructure is\u00a0verifying the\u00a0commit signatures before accepting the\u00a0push.  Nevertheless, the\u00a0recent attack on\u00a0our GitHub mirrors made me realize that if\u00a0a\u00a0smart attacker was able to inject a\u00a0single malicious commit without valid signature, then a\u00a0Gentoo developer would most likely make a\u00a0signed commit on\u00a0top of\u00a0it without even noticing the\u00a0problem.<\/p>\n<p>In\u00a0this article, I would like to\u00a0shortly present my quick solution to\u00a0this\u00a0problem \u2014 <a rel='external' href='https:\/\/packages.gentoo.org\/packages\/app-portage\/gverify'>app-portage\/gverify<\/a>.  <a rel='external' href='https:\/\/github.com\/mgorny\/gverify'>gverify<\/a> is a\u00a0trivial reimplementation of\u00a0gkeys in\u00a0&lt;200 lines of\u00a0code.  It uses the\u00a0gkeys seed data (yes, this means it relies on\u00a0manual updates) combined with autogenerated developer keyrings to\u00a0provide strict verification of\u00a0commits.  Unlike gkeys, it works out-of-the-box without root privileges and\u00a0automatically updates the\u00a0keys on\u00a0use.<\/p>\n<p>The\u00a0package installs a\u00a0<kbd>gv-install<\/kbd> tool that installs two hooks on\u00a0your <kbd>repo\/gentoo.git<\/kbd> working copy.  Those are <kbd>post-merge<\/kbd> and\u00a0<kbd>pre-rebase<\/kbd> hooks that verify the\u00a0tip of\u00a0upstream master branch, respectively every time merge on\u00a0master is finished, and\u00a0every time a\u00a0rebase is about to\u00a0be started.  This covers the\u00a0two main cases \u2014 <kbd>git pull<\/kbd> and\u00a0<kbd>git pull --rebase<\/kbd>.  The\u00a0former causes a\u00a0verbose error after the\u00a0update, the\u00a0latter prevents a\u00a0rebase from proceeding.<\/p>\n<p>While this is far from perfect, it seems reasonably good solution given the\u00a0limitations of\u00a0available git hooks.  Most importantly, it should prevent the\u00a0<kbd>git pull --rebase -S &amp;&amp; git push --sign<\/kbd> loop from silently accepting a\u00a0malicious commit.  Currently the\u00a0hook verifies the\u00a0top upstream commit only; however, in\u00a0the\u00a0future I\u00a0want to\u00a0implement incremental verification of\u00a0all new commits.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Git commit signatures are recursive by\u00a0design \u2014 that is, each signature covers not only the\u00a0commit in\u00a0question but also indirectly all past commits, via\u00a0tree and\u00a0parent commit hashes. This makes user-side commit verification much simpler, as\u00a0the\u00a0user needs only to\u00a0verify the\u00a0signature on\u00a0the\u00a0most recent commit; with the\u00a0assumption that the\u00a0developer making it has verified the\u00a0earlier commit and\u00a0so on. Sadly, this &hellip; <a href=\"https:\/\/blogs.gentoo.org\/mgorny\/2018\/08\/03\/verifying-repo-gentoo-git-with-gverify\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Verifying repo\/gentoo.git with gverify&#8221;<\/span><\/a><\/p>\n","protected":false},"author":137,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[10],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/734"}],"collection":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/users\/137"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/comments?post=734"}],"version-history":[{"count":8,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/734\/revisions"}],"predecessor-version":[{"id":743,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/734\/revisions\/743"}],"wp:attachment":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/media?parent=734"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/categories?post=734"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/tags?post=734"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}