Skip to content

Instantly share code, notes, and snippets.

@ShikherVerma
Last active July 27, 2017 12:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ShikherVerma/9204060b545c00597e7ad9b694cfeb9c to your computer and use it in GitHub Desktop.
Save ShikherVerma/9204060b545c00597e7ad9b694cfeb9c to your computer and use it in GitHub Desktop.
verify git push ceritifcates $ verify-certificate.py path-to-latest-push-certificate
import sys
import os
import zlib
import re
import gnupg
import subprocess
def verify_signature(gpg, signature, content):
"""This function exists because python-gnupg failed me."""
# write signature to a file and get file stream 'rb'
sign_file = open("/tmp/signature.txt", "wb")
sign_file.write(bytes(signature, "utf-8"))
sign_file.close()
sign_file = open("/tmp/signature.txt", "rb")
# write certificate to a file and get path
cert_path = "/tmp/cert.txt"
cert_file = open(cert_path, "wb")
cert_file.write(bytes(content, "utf-8"))
cert_file.close()
verified = gpg.verify_file(sign_file, cert_path)
return verified
def main():
if (len(sys.argv) != 2):
sys.exit("Usage verify-certificate.py path")
# Load the certificate file from arguments
path = sys.argv[1]
fileDir = os.path.dirname(os.path.realpath('__file__'))
filename = os.path.join(fileDir, path)
cert_compressed = open(filename, 'rb').read()
cert_text = zlib.decompress(cert_compressed).decode("utf-8")
cert_text = re.search("(?<=)(certificate.*?)(?=$)", cert_text, re.S).group(1)
# Get the information apart.
signature = re.search("(?<=)(-----BEGIN PGP SIGNATURE-----.*?)(?=$)", cert_text, re.S).group(1)
content = re.search("(?<=)(certificate.*?)(?=-----BEGIN)", cert_text, re.S).group(1)
key_id = re.search("(?<=pusher )(.*?)(?= )", cert_text, re.S).group(1)
push_data = re.search("(?<=nonce.{32}\n\n)(.*?)(?=-----BEGIN PGP SIGNATURE-----)", cert_text, re.S).group(1)
# get the gpg key using the public key id
gpg = gnupg.GPG()
gpg.recv_keys('keys.gnupg.net', key_id)
# verify the signature for the certificate
verified = verify_signature(gpg, signature, content)
if not verified:
raise ValueError("Signature failed to verify")
else:
print("GOOD SIGNATURE")
# verify the state of the repo from the push certificate
print("Assuming that this certificate is the latest one")
for line in push_data.splitlines():
commit_hash = line.split(" ")[1]
ref = line.split(" ")[2]
branch = ref.split("refs/heads/")[1]
output = subprocess.check_output(["git", "rev-parse", branch]).decode("utf-8").strip('\n')
# git rev-parse the branch to check that the hash is correct
if(output == commit_hash):
print(f"Branch {branch} is at correct hash.")
else:
print(f"ERROR : Branch {branch} should be at {commit_hash} but currently at {output}")
sys.exit(2)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment