scripts: Package signing tool verifies using certificate.

Package signing tool verifies signed data using certificate instead 
of public key. It also verifies certificate, warns if it's self 
signed, fails if it's invalid.
This commit is contained in:
Bahadır Kandemir
2010-10-25 10:50:43 +00:00
parent 66f8c6cb52
commit cf3a6f52bc
2 changed files with 79 additions and 14 deletions
-1
View File
@@ -5,7 +5,6 @@ mkdir certs
openssl genrsa -des3 -out certs/enc_key.pem 1024
openssl req -new -subj '/C=TR/ST=Kocaeli/L=Gebze/CN=Pardus' -key certs/enc_key.pem -out certs/req.pem
openssl req -x509 -key certs/enc_key.pem -in certs/req.pem -out certs/cert.pem -days 365
openssl x509 -inform pem -in certs/cert.pem -pubkey -noout > certs/pub_key.pem
# Feel free to share 'certs/cert.pem' and 'certs/pub_key.pem' with anyone, keep others to yourself.
+79 -13
View File
@@ -15,13 +15,18 @@ import sys
import tempfile
import zipfile
def sign_data(data, certificate, password_fd):
# Certificate validity
VALID = 1
SELF_SIGNED = 0
INVALID = -1
def sign_data(data, key_file, password_fd):
"""
Signs data with given certificate.
Arguments:
data: Data to be signed
certificate: Private certificate
key_file: Private key
password_fd: File that contains passphrase
Returns:
Signed data
@@ -31,7 +36,7 @@ def sign_data(data, certificate, password_fd):
# Use OpenSSL to sign data
command = '/usr/bin/openssl dgst -sha1 -sign %s -passin fd:%d'
command = command % (certificate, password_fd.fileno())
command = command % (key_file, password_fd.fileno())
command = shlex.split(command)
pipe = subprocess.Popen(command, stdin=subprocess.PIPE,
@@ -48,14 +53,62 @@ def sign_data(data, certificate, password_fd):
return signed_ascii
def verify_data(data, signature, key_file):
def get_public_key(cert_file):
"""
Verifies signature of data signed with given key file.
Extracts public key from certificate.
Arguments:
cert_file: Certificate
Returns:
Public key
"""
# Use OpenSSL to extract public key
command = "openssl x509 -inform pem -in %s -pubkey -noout"
command = command % cert_file
command = shlex.split(command)
pipe = subprocess.Popen(command, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
key_ascii = pipe.stdout.read()
return key_ascii
def verify_certificate(cert_file):
"""
Verifies a certificate.
Arguments:
cert_file: Certificate
Returns:
VALID, SELF_SIGNED or INVALID
"""
# Use OpenSSL to verify certificate
command = '/usr/bin/openssl verify %s'
command = command % cert_file
command = shlex.split(command)
pipe = subprocess.Popen(command, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
lines = pipe.stdout.read().split('\n')
if len(lines) < 2:
return INVALID
elif lines[1].startswith("error"):
code = lines[1].split()[1]
if code == '18':
return SELF_SIGNED
else:
return INVALID
else:
return VALID
def verify_data(data, signature, cert_file):
"""
Verifies signature of data signed with given certificate.
Arguments:
data: Original data
signature_file: Signed data
key_file: Public keyfile
cert_file: Certificate
Returns:
True if valid, False if invalid
"""
@@ -69,9 +122,14 @@ def verify_data(data, signature, key_file):
data_file.write(data)
data_file.flush()
# Keep public key in a temporary file
pub_file = tempfile.NamedTemporaryFile()
pub_file.write(get_public_key(cert_file))
pub_file.flush()
# Use OpenSSL to verify signature
command = '/usr/bin/openssl dgst -sha1 -verify %s -signature %s %s'
command = command % (key_file, signature_file.name, data_file.name)
command = command % (pub_file.name, signature_file.name, data_file.name)
command = shlex.split(command)
pipe = subprocess.Popen(command, stdout=subprocess.PIPE,
@@ -81,6 +139,7 @@ def verify_data(data, signature, key_file):
# Destroy temporary files
signature_file.close()
data_file.close()
pub_file.close()
return result == 0
@@ -107,13 +166,13 @@ def get_zip_hashes(zip_obj):
return "\n".join(hashes)
def verify_zipfile(filename, key_file):
def verify_zipfile(filename, cert_file):
"""
Verifies integrity of a ZIP file.
Arguments:
filename: ZIP filename
key_file: Public keyfile
cert_file: Certificate
Returns:
True if valid, False if invalid
"""
@@ -133,7 +192,7 @@ def verify_zipfile(filename, key_file):
zip_obj.close()
# Verify signed data
return verify_data(hashes, signature, key_file)
return verify_data(hashes, signature, cert_file)
def sign_zipfile(filename, certificate, password_fd):
"""
@@ -164,7 +223,7 @@ def print_usage():
print "Usage:"
print " %s sign <path/to/private_key> <file.zip ...>" % sys.argv[0]
print " %s verify <path/to/public_key> <file.zip ...>" % sys.argv[0]
print " %s verify <path/to/certificate> <file.zip ...>" % sys.argv[0]
sys.exit(1)
def main():
@@ -201,13 +260,20 @@ def main():
elif operation == 'verify':
try:
key_file = sys.argv[2]
cert_file = sys.argv[2]
except IndexError:
print_usage()
cert_validity = verify_certificate(cert_file)
if cert_validity == SELF_SIGNED:
print "WARNING: Certificate is self-signed."
elif cert_validity == INVALID:
print "ERROR: Certificate is invalid"
sys.exit(1)
if len(sys.argv[3:]):
for filename in sys.argv[3:]:
if verify_zipfile(filename, key_file):
if verify_zipfile(filename, cert_file):
print "%s is valid." % filename
else:
print "%s is corrupted." % filename