database-backed blacklisting of moduli and names

This commit is contained in:
Seth Schoen
2012-07-16 15:02:07 -07:00
parent acd5a77fc3
commit e70424dd4a
2 changed files with 36 additions and 5 deletions
+20 -5
View File
@@ -11,8 +11,12 @@ import M2Crypto
from distutils.version import LooseVersion from distutils.version import LooseVersion
assert LooseVersion(M2Crypto.version) >= LooseVersion("0.22") assert LooseVersion(M2Crypto.version) >= LooseVersion("0.22")
import hashlib import hashlib
import blacklists
# we can use temp() to get tempfiles to pass to OpenSSL subprocesses. # we can use temp() to get tempfiles to pass to OpenSSL subprocesses.
forbidden_moduli = blacklists.forbidden_moduli()
forbidden_names = blacklists.forbidden_names()
def parse(csr): def parse(csr):
""" """
Is this CSR syntactically valid? (TODO: remove) Is this CSR syntactically valid? (TODO: remove)
@@ -41,11 +45,23 @@ def goodkey(key):
"""Does this public key comply with our CA policy?""" """Does this public key comply with our CA policy?"""
key = str(key) key = str(key)
bits = modulusbits(key) bits = modulusbits(key)
if bits and bits >= 2000: if bits and bits >= 2000 and not blacklisted(key):
return True return True
else: else:
return False return False
def blacklisted(key):
"""Is this key blacklisted?"""
# There is also a modulus function that uses M2Crypto.m2.rsa_get_n
# instead of EVP.PKey, but it seems to erroneously prepend the exponent
# to the modulus or something.
bio = M2Crypto.BIO.MemoryBuffer(key)
pubkey = M2Crypto.RSA.load_pub_key_bio(bio)
pkey = M2Crypto.EVP.PKey()
pkey.assign_rsa(pubkey)
modulus = pkey.get_modulus()
return modulus in forbidden_moduli
def csr_goodkey(csr): def csr_goodkey(csr):
"""Does this CSR's embedded public key comply with our CA policy?""" """Does this CSR's embedded public key comply with our CA policy?"""
csr = str(csr) csr = str(csr)
@@ -138,9 +154,8 @@ def can_sign(name):
# the name is actually a FQDN. # the name is actually a FQDN.
name = str(name) name = str(name)
if "." not in name: return False if "." not in name: return False
# Examples of names that are forbidden by policy due to a blacklist. # Names that are forbidden by policy due to a blacklist.
if name in ["google.com", "www.google.com"]: return False return name not in forbidden_names
return True
def verify(key, data, signature): def verify(key, data, signature):
""" """
@@ -209,7 +224,7 @@ def issue(csr, subjects):
"""Issue a certificate requested by CSR, specifying the subject names """Issue a certificate requested by CSR, specifying the subject names
indicated in subjects, and return the certificate. Calls to this indicated in subjects, and return the certificate. Calls to this
function should be guarded with a lock to ensure that the calls never function should be guarded with a lock to ensure that the calls never
overlapping calls.""" overlap."""
if not subjects: if not subjects:
return None return None
csr = str(csr) csr = str(csr)
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env python
import redis
r = redis.Redis()
# Moduli should be stored in Redis in hexadecimal, all uppercase. If these
# sets don't exist, sismember returns False (not an exception).
class forbidden_moduli(object):
def __contains__(self, modulus):
return r.sismember("debian_moduli", modulus) or r.sismember("factorable_moduli", modulus)
class forbidden_names(object):
def __contains__(self, name):
return r.sismember("forbidden_names", name)