mirror of
https://github.com/certbot/certbot.git
synced 2026-08-02 19:31:51 +02:00
use M2Crypto in CSR verify/sign/encrypt
This commit is contained in:
+53
-28
@@ -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!"""
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
Reference in New Issue
Block a user