def gen_cert(self, domain: str, key: Optional[crypto.PKey] = None, bits: int = 2048) -> Tuple[crypto.X509, crypto.PKey]: """Generate tls-alpn-01 certificate. :param str domain: Domain verified by the challenge. :param OpenSSL.crypto.PKey key: Optional private key used in certificate generation. If not provided (``None``), then fresh key will be generated. :param int bits: Number of bits for newly generated key. :rtype: `tuple` of `OpenSSL.crypto.X509` and `OpenSSL.crypto.PKey` """ if key is None: key = crypto.PKey() key.generate_key(crypto.TYPE_RSA, bits) der_value = b"DER:" + codecs.encode(self.h, 'hex') acme_extension = crypto.X509Extension(self.ID_PE_ACME_IDENTIFIER_V1, critical=True, value=der_value) return crypto_util.gen_ss_cert(key, [domain], force_san=True, extensions=[acme_extension]), key
def gen_cert(self, key=None, bits=2048): """Generate tls-sni-01 certificate. :param OpenSSL.crypto.PKey key: Optional private key used in certificate generation. If not provided (``None``), then fresh key will be generated. :param int bits: Number of bits for newly generated key. :rtype: `tuple` of `OpenSSL.crypto.X509` and `OpenSSL.crypto.PKey` """ if key is None: key = OpenSSL.crypto.PKey() key.generate_key(OpenSSL.crypto.TYPE_RSA, bits) return ( crypto_util.gen_ss_cert( key, [ # z_domain is too big to fit into CN, hence first dummy domain "dummy", self.z_domain.decode(), ], force_san=True, ), key, )
def test_deploy_cert(plugin, temp_dir, domains): """Tests deploy_cert returning True if the tests are successful""" cert = crypto_util.gen_ss_cert(util.KEY, domains) cert_path = os.path.join(temp_dir, "cert.pem") with open(cert_path, "wb") as f: f.write(OpenSSL.crypto.dump_certificate( OpenSSL.crypto.FILETYPE_PEM, cert)) for domain in domains: try: plugin.deploy_cert(domain, cert_path, util.KEY_PATH, cert_path, cert_path) plugin.save() # Needed by the Apache plugin except le_errors.Error: logger.error("**** Plugin failed to deploy certificate for %s:", domain, exc_info=True) return False if not _save_and_restart(plugin, "deployed"): return False success = True time.sleep(3) for domain in domains: verified = validator.Validator().certificate( cert, domain, "127.0.0.1", plugin.https_port) if not verified: logger.error("**** Could not verify certificate for domain %s", domain) success = False if success: logger.info("HTTPS validation succeeded") return success
def gen_cert(self, domain, key=None, bits=2048): """Generate tls-alpn-01 certificate. :param unicode domain: Domain verified by the challenge. :param OpenSSL.crypto.PKey key: Optional private key used in certificate generation. If not provided (``None``), then fresh key will be generated. :param int bits: Number of bits for newly generated key. :rtype: `tuple` of `OpenSSL.crypto.X509` and `OpenSSL.crypto.PKey` """ if key is None: key = crypto.PKey() key.generate_key(crypto.TYPE_RSA, bits) # Instead of using a ASN.1 encoding library just append the OCTET STRING tag (0x04) # and the length of the SHA256 hash (0x20) since both of these should never change der_value = b"DER:0420" + codecs.encode(self.h, 'hex') acme_extension = crypto.X509Extension(self.ID_PE_ACME_IDENTIFIER_V1, critical=True, value=der_value) return crypto_util.gen_ss_cert(key, [domain], force_san=True, extensions=[acme_extension]), key
def test_deploy_cert(plugin, temp_dir, domains): """Tests deploy_cert returning True if the tests are successful""" cert = crypto_util.gen_ss_cert(util.KEY, domains) cert_path = os.path.join(temp_dir, "cert.pem") with open(cert_path, "w") as f: f.write(OpenSSL.crypto.dump_certificate( OpenSSL.crypto.FILETYPE_PEM, cert)) for domain in domains: try: plugin.deploy_cert(domain, cert_path, util.KEY_PATH, cert_path, cert_path) plugin.save() # Needed by the Apache plugin except le_errors.Error as error: logger.error("Plugin failed to deploy ceritificate for %s:", domain) logger.exception(error) return False if not _save_and_restart(plugin, "deployed"): return False success = True for domain in domains: verify = functools.partial(validator.Validator().certificate, cert, domain, "127.0.0.1", plugin.https_port) if not _try_until_true(verify): logger.error("Could not verify certificate for domain %s", domain) success = False if success: logger.info("HTTPS validation succeeded") return success
def test_sn_collisions(self): from acme.crypto_util import gen_ss_cert for _ in range(self.cert_count): cert = gen_ss_cert(self.key, ['dummy'], force_san=True) self.serial_num.append(cert.get_serial_number()) self.assertTrue(len(set(self.serial_num)) > 1)
def test_deploy_cert(plugin, temp_dir, domains): """Tests deploy_cert returning True if the tests are successful""" cert = crypto_util.gen_ss_cert(util.KEY, domains) cert_path = os.path.join(temp_dir, "cert.pem") with open(cert_path, "w") as f: f.write( OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)) for domain in domains: try: plugin.deploy_cert(domain, cert_path, util.KEY_PATH) except le_errors.Error as error: logger.error("Plugin failed to deploy ceritificate for %s:", domain) logger.exception(error) return False if not _save_and_restart(plugin, "deployed"): return False success = True for domain in domains: verify = functools.partial(validator.Validator().certificate, cert, domain, "127.0.0.1", plugin.https_port) if not _try_until_true(verify): logger.error("Could not verify certificate for domain %s", domain) success = False if success: logger.info("HTTPS validation succeeded") return success
def test_sn_collisions(self): from acme.crypto_util import gen_ss_cert for _ in range(self.cert_count): cert = gen_ss_cert(self.key, ['dummy'], force_san=True, ips=[ipaddress.ip_address("10.10.10.10")]) self.serial_num.append(cert.get_serial_number()) self.assertGreaterEqual(len(set(self.serial_num)), self.cert_count)
def __init__(self, *args, **kwargs): super(PluginIOTestMixin, self).__init__(*args, **kwargs) raw_key = gen_pkey(1024) self.all_data = IOPlugin.Data( account_key=jose.JWKRSA(key=rsa.generate_private_key( public_exponent=65537, key_size=1024, backend=default_backend(), )), key=ComparablePKey(raw_key), cert=jose.ComparableX509(crypto_util.gen_ss_cert(raw_key, ['a'])), chain=[ jose.ComparableX509(crypto_util.gen_ss_cert(raw_key, ['b'])), jose.ComparableX509(crypto_util.gen_ss_cert(raw_key, ['c'])), ], ) self.key_data = IOPlugin.EMPTY_DATA._replace(key=self.all_data.key)
def gen_cert(self, chall, domain, key): """Generate DVSNI certificate. :param .DVSNI chall: Corresponding challenge. :param unicode domain: :param OpenSSL.crypto.PKey """ return crypto_util.gen_ss_cert(key, [ domain, chall.nonce_domain.decode(), self.z_domain(chall).decode()])
def _get_snakeoil_paths(self): # TODO: generate only once tmp_dir = os.path.join(self.config.work_dir, "snakeoil") le_key = crypto_util.init_save_key(key_size=1024, key_dir=tmp_dir, keyname="key.pem") key = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, le_key.pem) cert = acme_crypto_util.gen_ss_cert(key, domains=[socket.gethostname()]) cert_path = os.path.join(tmp_dir, "cert.pem") cert_pem = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert) with open(cert_path, "w") as cert_file: cert_file.write(cert_pem) return cert_path, le_key.file
def gen_cert(self, chall, domain, key): """Generate DVSNI certificate. :param .DVSNI chall: Corresponding challenge. :param unicode domain: :param OpenSSL.crypto.PKey """ return crypto_util.gen_ss_cert(key, [ domain, chall.nonce_domain.decode(), self.z_domain(chall).decode() ])
def _get_snakeoil_paths(self): # TODO: generate only once tmp_dir = os.path.join(self.config.work_dir, "snakeoil") le_key = crypto_util.init_save_key( key_size=1024, key_dir=tmp_dir, keyname="key.pem") key = OpenSSL.crypto.load_privatekey( OpenSSL.crypto.FILETYPE_PEM, le_key.pem) cert = acme_crypto_util.gen_ss_cert(key, domains=[socket.gethostname()]) cert_pem = OpenSSL.crypto.dump_certificate( OpenSSL.crypto.FILETYPE_PEM, cert) cert_file, cert_path = util.unique_file(os.path.join(tmp_dir, "cert.pem")) with cert_file: cert_file.write(cert_pem) return cert_path, le_key.file
def _get_snakeoil_paths(self): """Generate invalid certs that let us create ssl directives for Nginx""" # TODO: generate only once tmp_dir = os.path.join(self.config.work_dir, "snakeoil") le_key = crypto_util.init_save_key( key_size=1024, key_dir=tmp_dir, keyname="key.pem") key = OpenSSL.crypto.load_privatekey( OpenSSL.crypto.FILETYPE_PEM, le_key.pem) cert = acme_crypto_util.gen_ss_cert(key, domains=[socket.gethostname()]) cert_pem = OpenSSL.crypto.dump_certificate( OpenSSL.crypto.FILETYPE_PEM, cert) cert_file, cert_path = util.unique_file( os.path.join(tmp_dir, "cert.pem"), mode="wb") with cert_file: cert_file.write(cert_pem) return cert_path, le_key.file
def _get_snakeoil_paths(self): """Generate invalid certs that let us create ssl directives for Nginx""" # TODO: generate only once tmp_dir = os.path.join(self.config.work_dir, "snakeoil") le_key = crypto_util.init_save_key( {"type": "rsa", "size": 1024}, key_dir=tmp_dir, keyname="key.pem") key = OpenSSL.crypto.load_privatekey( OpenSSL.crypto.FILETYPE_PEM, le_key.pem) cert = acme_crypto_util.gen_ss_cert(key, domains=[socket.gethostname()]) cert_pem = OpenSSL.crypto.dump_certificate( OpenSSL.crypto.FILETYPE_PEM, cert) cert_file, cert_path = util.unique_file( os.path.join(tmp_dir, "cert.pem"), mode="wb") with cert_file: cert_file.write(cert_pem) return cert_path, le_key.file
def gen_cert(self, key=None, bits=2048): """Generate tls-sni-01 certificate. :param OpenSSL.crypto.PKey key: Optional private key used in certificate generation. If not provided (``None``), then fresh key will be generated. :param int bits: Number of bits for newly generated key. :rtype: `tuple` of `OpenSSL.crypto.X509` and `OpenSSL.crypto.PKey` """ if key is None: key = OpenSSL.crypto.PKey() key.generate_key(OpenSSL.crypto.TYPE_RSA, bits) return crypto_util.gen_ss_cert(key, [ # z_domain is too big to fit into CN, hence first dummy domain 'dummy', self.z_domain.decode()], force_san=True), key
def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) # one self-signed key for all DVSNI and SimpleHTTP certificates self.key = OpenSSL.crypto.PKey() self.key.generate_key(OpenSSL.crypto.TYPE_RSA, bits=2048) # TODO: generate only when the first SimpleHTTP challenge is solved self.simple_http_cert = acme_crypto_util.gen_ss_cert( self.key, domains=["temp server"]) self.served = collections.defaultdict(set) # Stuff below is shared across threads (i.e. servers read # values, main thread writes). Due to the nature of CPython's # GIL, the operations are safe, c.f. # https://docs.python.org/2/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe self.certs = {} self.simple_http_resources = set() self.servers = ServerManager(self.certs, self.simple_http_resources)
def test_installer(plugin, config, temp_dir): """Tests plugin as an installer""" backup = os.path.join(temp_dir, "backup") shutil.copytree(config, backup, symlinks=True) if plugin.get_all_names() != plugin.get_all_names_answer(): raise errors.Error("get_all_names test failed") else: logging.info("get_all_names test succeeded") domains = list(plugin.get_testable_domain_names()) cert = crypto_util.gen_ss_cert(util.KEY, domains) cert_path = os.path.join(temp_dir, "cert.pem") with open(cert_path, "w") as f: f.write( OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)) for domain in domains: plugin.deploy_cert(domain, cert_path, util.KEY_PATH) plugin.save() plugin.restart()
def test_no_name(self): from acme.crypto_util import gen_ss_cert with self.assertRaises(AssertionError): gen_ss_cert(self.key, ips=[ipaddress.ip_address("1.1.1.1")]) gen_ss_cert(self.key)