From 43530c8837857026a6a90d29e1ac7ea83be5665e Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Fri, 18 Mar 2016 06:28:36 -0400 Subject: [PATCH] Add verify-commits from Bitcoin Core --- contrib/verify-commits/allow-revsig-commits | 0 contrib/verify-commits/gpg.sh | 33 +++++++++++ contrib/verify-commits/pre-push-hook.sh | 16 ++++++ contrib/verify-commits/trusted-git-root | 1 + contrib/verify-commits/trusted-keys | 3 + contrib/verify-commits/verify-commits.sh | 61 +++++++++++++++++++++ 6 files changed, 114 insertions(+) create mode 100644 contrib/verify-commits/allow-revsig-commits create mode 100755 contrib/verify-commits/gpg.sh create mode 100755 contrib/verify-commits/pre-push-hook.sh create mode 100644 contrib/verify-commits/trusted-git-root create mode 100644 contrib/verify-commits/trusted-keys create mode 100755 contrib/verify-commits/verify-commits.sh diff --git a/contrib/verify-commits/allow-revsig-commits b/contrib/verify-commits/allow-revsig-commits new file mode 100644 index 00000000..e69de29b diff --git a/contrib/verify-commits/gpg.sh b/contrib/verify-commits/gpg.sh new file mode 100755 index 00000000..f84c9a8c --- /dev/null +++ b/contrib/verify-commits/gpg.sh @@ -0,0 +1,33 @@ +#!/bin/bash +INPUT=$(/dev/null); do + case "$LINE" in + "[GNUPG:] VALIDSIG "*) + while read KEY; do + case "$LINE" in "[GNUPG:] VALIDSIG $KEY "*) VALID=true;; esac + done < ./contrib/verify-commits/trusted-keys + ;; + "[GNUPG:] REVKEYSIG "*) + [ "$BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG" != 1 ] && exit 1 + while read KEY; do + case "$LINE" in "[GNUPG:] REVKEYSIG ${KEY:24:40} "*) + REVSIG=true + GOODREVSIG="[GNUPG:] GOODSIG ${KEY:24:40} " + ;; + esac + done < ./contrib/verify-commits/trusted-keys + ;; + esac +done +if ! $VALID; then + exit 1 +fi +if $VALID && $REVSIG; then + echo "$INPUT" | gpg --trust-model always "$@" | grep "\[GNUPG:\] \(NEWSIG\|SIG_ID\|VALIDSIG\)" 2>/dev/null + echo "$GOODREVSIG" +else + echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null +fi diff --git a/contrib/verify-commits/pre-push-hook.sh b/contrib/verify-commits/pre-push-hook.sh new file mode 100755 index 00000000..d52f5756 --- /dev/null +++ b/contrib/verify-commits/pre-push-hook.sh @@ -0,0 +1,16 @@ +#!/bin/bash +if ! [[ "$2" =~ ^(git@)?(www.)?github.com(:|/)petertodd/python-bitcoinlib(.git)?$ ]]; then + exit 0 +fi + +while read LINE; do + set -- A $LINE + if [ "$4" != "refs/heads/master" ]; then + continue + fi + if ! ./contrib/verify-commits/verify-commits.sh $3 > /dev/null 2>&1; then + echo "ERROR: A commit is not signed, can't push" + ./contrib/verify-commits/verify-commits.sh + exit 1 + fi +done < /dev/stdin diff --git a/contrib/verify-commits/trusted-git-root b/contrib/verify-commits/trusted-git-root new file mode 100644 index 00000000..376255a3 --- /dev/null +++ b/contrib/verify-commits/trusted-git-root @@ -0,0 +1 @@ +22cc8167a98ea026b6a4fe16aa2adc2de17aa97f diff --git a/contrib/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys new file mode 100644 index 00000000..802ee5b3 --- /dev/null +++ b/contrib/verify-commits/trusted-keys @@ -0,0 +1,3 @@ +15CC9446387233AF0104F6132481403DA5F091FB +C5DDF20211D8F6E5F6E010F8C085F21CE7F4B9DC +14FCC76E05E775AAE61ABEFF9EC4568398C13B16 diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh new file mode 100755 index 00000000..c0ebeaeb --- /dev/null +++ b/contrib/verify-commits/verify-commits.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +REALPATH=$(realpath "$0") +DIR=$(dirname "$REALPATH") + +VERIFIED_ROOT=$(cat "${DIR}/trusted-git-root") + +IS_REVSIG_ALLOWED () { + while read LINE; do + [ "$LINE" = "$1" ] && return 0 + done < "${DIR}/allow-revsig-commits" + return 1 +} + +HAVE_FAILED=false +IS_SIGNED () { + if [ $1 = $VERIFIED_ROOT ]; then + return 0; + fi + if IS_REVSIG_ALLOWED "$1"; then + export BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG=1 + else + export BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG=0 + fi + if ! git -c "gpg.program=${DIR}/gpg.sh" verify-commit $1 > /dev/null 2>&1; then + return 1; + fi + local PARENTS=$(git show -s --format=format:%P $1) + for PARENT in $PARENTS; do + if IS_SIGNED $PARENT > /dev/null; then + return 0; + fi + done + if ! "$HAVE_FAILED"; then + echo "No parent of $1 was signed with a trusted key!" > /dev/stderr + echo "Parents are:" > /dev/stderr + for PARENT in $PARENTS; do + git show -s $PARENT > /dev/stderr + done + HAVE_FAILED=true + fi + return 1; +} + +if [ x"$1" = "x" ]; then + TEST_COMMIT="HEAD" +else + TEST_COMMIT="$1" +fi + +IS_SIGNED "$TEST_COMMIT" +RES=$? +if [ "$RES" = 1 ]; then + if ! "$HAVE_FAILED"; then + echo "$TEST_COMMIT was not signed with a trusted key!" + fi +else + echo "There is a valid path from $TEST_COMMIT to $VERIFIED_ROOT where all commits are signed!" +fi + +exit $RES