use M2Crypto in CSR verify/sign/encrypt

This commit is contained in:
Eric Wustrow
2012-07-12 20:30:46 -04:00
parent 0a85d8154f
commit 956ea28b95
2 changed files with 55 additions and 29 deletions
+53 -28
View File
@@ -4,6 +4,7 @@
import subprocess, tempfile, re import subprocess, tempfile, re
import M2Crypto import M2Crypto
import hashlib
# we can use tempfile.NamedTemporaryFile() to get tempfiles # we can use tempfile.NamedTemporaryFile() to get tempfiles
# to pass to OpenSSL subprocesses. # to pass to OpenSSL subprocesses.
@@ -128,38 +129,62 @@ def can_sign(name):
if name in ["google.com", "www.google.com"]: return False if name in ["google.com", "www.google.com"]: return False
return True return True
def verify(key, data): def verify(key, data, signature):
"""What string was validly signed by this public key? (or None)""" """
# Note: Only relatively short strings will work, so we normally Given a public key, some data, and its signature,
# sign a hash of the signed data rather than signing the signed verify the signature.
# data directly.
with tempfile.NamedTemporaryFile() as tmp: @type key: str
tmp.write(key) @param key: PEM-encoded string of the public key.
tmp.flush()
out, err = subprocess.Popen(["openssl", "rsautl", "-pubin", "-inkey", tmp.name, "-verify"],shell=False,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate(data) @type data: str
if out and not err: @param data: The data (before being hashed; we will use sha256 here)
return out
return None @type signature: str
@param signature: binary string of the signature
@return: True if the signature checks out, False otherwise.
"""
bio = M2Crypto.BIO.MemoryBuffer(key)
pubkey = M2Crypto.RSA.load_pub_key_bio(bio)
try:
res = pubkey.verify(hashlib.sha256(data).digest(), signature, 'sha256')
except M2Crypto.RSA.RSAError:
return False
return (res == 1)
def sign(key, data): def sign(key, data):
"""Sign this data with this private key. For client-side use.""" """
with tempfile.NamedTemporaryFile() as tmp: Sign this data with this private key. For client-side use.
tmp.write(key)
tmp.flush() @type key: str
out, err = subprocess.Popen(["openssl", "rsautl", "-inkey", tmp.name, "-sign"],shell=False,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate(data) @param key: PEM-encoded string of the private key.
if out and not err:
return out @type data: str
return None @param data: The data to be signed. Will be hashed (sha256) prior to
signing.
@return: binary string of the signature
"""
privkey = M2Crypto.RSA.load_key_string(key)
return privkey.sign(hashlib.sha256(data).digest(), 'sha256')
def encrypt(key, data): def encrypt(key, data):
"""Encrypt this data with this public key.""" """
with tempfile.NamedTemporaryFile() as tmp: Encrypt this data with this public key.
tmp.write(key)
tmp.flush() @type key: str
out, err = subprocess.Popen(["openssl", "rsautl", "-pubin", "-inkey", tmp.name, "-encrypt"],shell=False,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate(data) @param key: PEM-encoded string of the public key
if out and not err:
return out @type data: str
return None @param data: The data to be encrypted.
@return: binary string of the encrypted value, using PKCS1_OAEP_PADDING
"""
bio = M2Crypto.BIO.MemoryBuffer(key)
pubkey = M2Crypto.RSA.load_pub_key_bio(bio)
return pubkey.public_encrypt(data, M2Crypto.RSA.pkcs1_oaep_padding)
def issue(csr): def issue(csr):
"""Issue the certificate requested by this CSR and return it!""" """Issue the certificate requested by this CSR and return it!"""
+2 -1
View File
@@ -223,7 +223,8 @@ class session(object):
if not CSR.parse(csr): if not CSR.parse(csr):
self.die(r, r.BadCSR) self.die(r, r.BadCSR)
return return
if CSR.verify(CSR.pubkey(csr), sig) != sha256("(%d) (%s) (%s)" % (timestamp, recipient, csr)): digest_data = "(%d) (%s) (%s)" % (timestamp, recipient, csr)
if CSR.verify(CSR.pubkey(csr), digest_data, sig) == False:
self.die(r, r.BadSignature) self.die(r, r.BadSignature)
return return
if not CSR.csr_goodkey(csr): if not CSR.csr_goodkey(csr):