def _call_with_key(cls, *args, **kwargs): privkey = OpenSSL.crypto.PKey() privkey.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) privkey_pem = OpenSSL.crypto.dump_privatekey( OpenSSL.crypto.FILETYPE_PEM, privkey) from acme.crypto_util import make_csr return make_csr(privkey_pem, *args, **kwargs)
def test_revoke_by_privkey(): client = make_client(None) domains = [random_domain()] key = OpenSSL.crypto.PKey() key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) key_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key) csr_pem = acme_crypto_util.make_csr(key_pem, domains, False) order = client.new_order(csr_pem) cleanup = do_http_challenges(client, order.authorizations) try: order = client.poll_and_finalize(order) finally: cleanup() # Create a new client with the JWK as the cert private key jwk = jose.JWKRSA(key=key) net = acme_client.ClientNetwork(key, user_agent="Boulder integration tester") directory = Directory.from_json(net.get(chisel2.DIRECTORY).json()) new_client = acme_client.ClientV2(directory, net) cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, order.fullchain_pem) client.revoke(jose.ComparableX509(cert), 0)
def perform( certificate: Certificate, storage: "StorageProtocol", acme_account_email: str, acme_directory_url: str, authenticators: typing.Sequence[AuthenticatorProtocol], ) -> None: client = setup_client( storage=storage, directory_url=acme_directory_url, account_email=acme_account_email, ) orderr = client.new_order( crypto_util.make_csr(certificate.private_key, certificate.domains)) auth_challs = select_challs(orderr, authenticators) for authenticator, challs in auth_challs: account_key = client.net.key authenticator.perform(challs, account_key) for challb, _ in challs: client.answer_challenge(challb, challb.response(account_key)) try: finalized_orderr = client.poll_and_finalize(orderr) fullchain_pem = finalized_orderr.fullchain_pem.encode("utf8") certificate.set_fullchain(fullchain_pem) storage.save_certificate(certificate) finally: for authenticator, challs in auth_challs: authenticator.cleanup(challs, account_key)
def init_save_csr(privkey, names, path): """Initialize a CSR with the given private key. :param privkey: Key to include in the CSR :type privkey: :class:`certbot.util.Key` :param set names: `str` names to include in the CSR :param str path: Certificate save directory. :returns: CSR :rtype: :class:`certbot.util.CSR` """ config = zope.component.getUtility(interfaces.IConfig) csr_pem = acme_crypto_util.make_csr( privkey.pem, names, must_staple=config.must_staple) # Save CSR util.make_or_verify_dir(path, 0o755, os.geteuid(), config.strict_permissions) csr_f, csr_filename = util.unique_file( os.path.join(path, "csr-certbot.pem"), 0o644, "wb") with csr_f: csr_f.write(csr_pem) logger.debug("Creating CSR: %s", csr_filename) return util.CSR(csr_filename, csr_pem, "pem")
def request_new_certificate(hostname, accnt_key, priv_key, tmp_chall_dict, directory_url): """Runs the entire process of ACME registration and certificate request""" client = create_v2_client(directory_url, accnt_key) try: client.net.account = client.new_account( messages.NewRegistration.from_data( terms_of_service_agreed=True ) ) except errors.ConflictError as error: existing_reg = messages.RegistrationResource(uri=error.location) existing_reg = client.query_registration(existing_reg) client.update_registration(existing_reg) csr = crypto_util.make_csr(priv_key, [hostname], False) order = client.new_order(csr) log.info('Created a new order for the issuance of a certificate for %s', hostname) challb = select_http01_chall(order) _, chall_tok = challb.response_and_validation(client.net.key) v = challb.chall.encode("token") log.info('Exposing challenge on %s', v) tmp_chall_dict.set(v, ChallTok(chall_tok)) cr = client.answer_challenge(challb, challb.response(client.net.key)) log.debug('Acme CA responded to challenge request with: %s', cr) order = client.poll_and_finalize(order) return split_certificate_chain(order.fullchain_pem)
def generate_csr(domains, key_path, csr_path, key_type=RSA_KEY_TYPE): """ Generate a private key, and a CSR for the given domains using this key. :param domains: the domain names to include in the CSR :type domains: `list` of `str` :param str key_path: path to the private key that will be generated :param str csr_path: path to the CSR that will be generated :param str key_type: type of the key (misc.RSA_KEY_TYPE or misc.ECDSA_KEY_TYPE) """ if key_type == RSA_KEY_TYPE: key = crypto.PKey() key.generate_key(crypto.TYPE_RSA, 2048) elif key_type == ECDSA_KEY_TYPE: key = ec.generate_private_key(ec.SECP384R1(), default_backend()) key = key.private_bytes(encoding=Encoding.PEM, format=PrivateFormat.TraditionalOpenSSL, encryption_algorithm=NoEncryption()) key = crypto.load_privatekey(crypto.FILETYPE_PEM, key) else: raise ValueError('Invalid key type: {0}'.format(key_type)) key_bytes = crypto.dump_privatekey(crypto.FILETYPE_PEM, key) with open(key_path, 'wb') as file: file.write(key_bytes) csr_bytes = crypto_util.make_csr(key_bytes, domains) with open(csr_path, 'wb') as file: file.write(csr_bytes)
def init_save_csr(privkey, names, path): """Initialize a CSR with the given private key. :param privkey: Key to include in the CSR :type privkey: :class:`certbot.util.Key` :param set names: `str` names to include in the CSR :param str path: Certificate save directory. :returns: CSR :rtype: :class:`certbot.util.CSR` """ config = zope.component.getUtility(interfaces.IConfig) csr_pem = acme_crypto_util.make_csr(privkey.pem, names, must_staple=config.must_staple) # Save CSR util.make_or_verify_dir(path, 0o755, config.strict_permissions) csr_f, csr_filename = util.unique_file( os.path.join(path, "csr-certbot.pem"), 0o644, "wb") with csr_f: csr_f.write(csr_pem) logger.debug("Creating CSR: %s", csr_filename) return util.CSR(csr_filename, csr_pem, "pem")
def generate_csr(domains, key_path, csr_path, key_type=RSA_KEY_TYPE): """ Generate a private key, and a CSR for the given domains using this key. :param domains: the domain names to include in the CSR :type domains: `list` of `str` :param str key_path: path to the private key that will be generated :param str csr_path: path to the CSR that will be generated :param str key_type: type of the key (misc.RSA_KEY_TYPE or misc.ECDSA_KEY_TYPE) """ if key_type == RSA_KEY_TYPE: key = crypto.PKey() key.generate_key(crypto.TYPE_RSA, 2048) elif key_type == ECDSA_KEY_TYPE: with warnings.catch_warnings(): # Ignore a warning on some old versions of cryptography warnings.simplefilter('ignore', category=PendingDeprecationWarning) key = ec.generate_private_key(ec.SECP384R1(), default_backend()) key = key.private_bytes(encoding=Encoding.PEM, format=PrivateFormat.TraditionalOpenSSL, encryption_algorithm=NoEncryption()) key = crypto.load_privatekey(crypto.FILETYPE_PEM, key) else: raise ValueError('Invalid key type: {0}'.format(key_type)) key_bytes = crypto.dump_privatekey(crypto.FILETYPE_PEM, key) with open(key_path, 'wb') as file: file.write(key_bytes) csr_bytes = crypto_util.make_csr(key_bytes, domains) with open(csr_path, 'wb') as file: file.write(csr_bytes)
def new_csr(domain_name, pkey_pem=None): """Create certificate signing request.""" if pkey_pem is None: pkey = OpenSSL.crypto.PKey() pkey.generate_key(OpenSSL.crypto.TYPE_RSA, CERT_PKEY_BITS) pkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, pkey) csr_pem = crypto_util.make_csr(pkey_pem, [domain_name]) return pkey_pem, csr_pem
def gen_csr(domain_names, pkey_pem=None): if pkey_pem is None: pkey = OpenSSL.crypto.PKey() pkey.generate_key(OpenSSL.crypto.TYPE_RSA, settings.LETSENCRYPT_CERT_KEY_BITS) pkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, pkey).decode() # Generate CSR based on the domains csr_pem = crypto_util.make_csr(pkey_pem, domain_names) return pkey_pem, csr_pem
def new_csr_comp(domain_name, pkey_pem=None): """Create certificate signing request.""" if pkey_pem is None: # Create private key. pkey = OpenSSL.crypto.PKey() pkey.generate_key(OpenSSL.crypto.TYPE_RSA, CERT_PKEY_BITS) pkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, pkey) csr_pem = crypto_util.make_csr(pkey_pem, [domain_name]) return pkey_pem, csr_pem
def submit_order(self, key, names): """ Create a new order and return the OrderResource for that order with all the authorizations resolved. It will automatically create a new private key and CSR for the domain 'names'. :param key: Key for the future certificate. :param list of str names: Sequence of DNS names for which to request a new certificate. :return: The new authorization resource. :rtype: Deferred[`~acme.messages.Order`] """ # certbot helper API needs PEM. pem_key = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(), ) csr_pem = make_csr(pem_key, names) identifiers = [fqdn_identifier(name) for name in names] message = messages.NewOrder(identifiers=identifiers) response = yield self._client.post(self.directory.newOrder, message) self._expect_response(response, [http.CREATED]) order_uri = self._maybe_location(response) authorizations = [] order_body = yield response.json() for uri in order_body['authorizations']: # We do a POST-as-GET respose = yield self._client.post(uri, obj=None) self._expect_response(response, [http.CREATED]) body = yield respose.json() authorizations.append( messages.AuthorizationResource( body=messages.Authorization.from_json(body), uri=uri, )) order = messages.OrderResource( body=messages.Order.from_json(order_body), uri=order_uri, authorizations=authorizations, csr_pem=csr_pem, ) # TODO: Not sure if all these sanity checks are required. for identifier in order.body.identifiers: if identifier not in identifiers: raise errors.UnexpectedUpdate(order) defer.returnValue(order)
def new_csr_comp(domain_names, pkey_pem): '''Create certificate signing request.''' if not pkey_pem: pkey = OpenSSL.crypto.PKey() pkey.generate_key(OpenSSL.crypto.TYPE_RSA, KEY_BITS) pkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, pkey) csr_pem = crypto_util.make_csr(pkey_pem, domain_names) return pkey_pem, csr_pem
def run_acme_reg_to_finish(domain, accnt_key, priv_key, hostname, tmp_chall_dict, directory_url): """Runs the entire process of ACME registeration""" client = create_v2_client(directory_url, accnt_key) # First we need to create a registration with the email address provided # and accept the terms of service log.info("Using boulder server %s", directory_url) client.net.account = client.new_account( messages.NewRegistration.from_data( terms_of_service_agreed=True ) ) # Now we need to open an order and request our certificate # NOTE: We'll let ACME generate a CSR for our private key as there's # a lot of utility code it uses to generate the CSR in a specific # fashion. Better to use what LE provides than to roll our own as we # we doing with the v1 code # # This will also let us support multi-domain certificat requests in the # future, as well as mandate OCSP-Must-Staple if/when GL's HTTPS server # supports it csr = crypto_util.make_csr(priv_key, [hostname], False) order = client.new_order(csr) authzr = order.authorizations log.info('Created a new order for %s', hostname) # authrz is a list of Authorization resources, we need to find the # HTTP-01 challenge and use it for auth_req in authzr: # pylint: disable=not-an-iterable for chall_body in auth_req.body.challenges: if isinstance(chall_body.chall, challenges.HTTP01): challb = chall_body break if challb is None: raise Exception("HTTP01 challenge unavailable!") _, chall_tok = challb.response_and_validation(client.net.key) v = chall_body.chall.encode("token") log.info('Exposing challenge on %s', v) tmp_chall_dict.set(v, ChallTok(chall_tok)) cr = client.answer_challenge(challb, challb.response(client.net.key)) log.debug('Acme CA responded to challenge request with: %s', cr) order = client.poll_and_finalize(order) return split_certificate_chain(order.fullchain_pem)
def run_acme_reg_to_finish(domain, accnt_key, priv_key, hostname, tmp_chall_dict, directory_url): """Runs the entire process of ACME registeration""" client = create_v2_client(directory_url, accnt_key) # First we need to create a registration with the email address provided # and accept the terms of service log.info("Using boulder server %s", directory_url) client.net.account = client.new_account( messages.NewRegistration.from_data( terms_of_service_agreed=True ) ) # Now we need to open an order and request our certificate # NOTE: We'll let ACME generate a CSR for our private key as there's # a lot of utility code it uses to generate the CSR in a specific # fashion. Better to use what LE provides than to roll our own as we # we doing with the v1 code # # This will also let us support multi-domain certificat requests in the # future, as well as mandate OCSP-Must-Staple if/when GL's HTTPS server # supports it csr = crypto_util.make_csr(priv_key, [hostname], False) order = client.new_order(csr) authzr = order.authorizations log.info('Created a new order for %s', hostname) # authrz is a list of Authorization resources, we need to find the # HTTP-01 challenge and use it for auth_req in authzr: # pylint: disable=not-an-iterable for chall_body in auth_req.body.challenges: if isinstance(chall_body.chall, challenges.HTTP01): challb = chall_body break if challb is None: raise Exception("HTTP01 challenge unavailable!") response, chall_tok = challb.response_and_validation(client.net.key) v = chall_body.chall.encode("token") log.info('Exposing challenge on %s', v) tmp_chall_dict.set(v, ChallTok(chall_tok)) cr = client.answer_challenge(challb, challb.response(client.net.key)) log.debug('Acme CA responded to challenge request with: %s', cr) order = client.poll_and_finalize(order) return split_certificate_chain(order.fullchain_pem)
def _new_csr_comp(domain_name, pkey_pem=None): """ Create certificate signing request. Создание ключей для подписания запросов """ if pkey_pem is None: # Create private key. pkey = OpenSSL.crypto.PKey() pkey.generate_key(OpenSSL.crypto.TYPE_RSA, CERT_PKEY_BITS) pkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, pkey) csr_pem = crypto_util.make_csr(pkey_pem, domain_name) return pkey_pem, csr_pem
def new_csr_comp(domain_name, pkey_pem=None): """Create certificate signing request.""" if pkey_pem is None: # Create private key. pkey = OpenSSL.crypto.PKey() pkey.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) pkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, pkey) kf = open(account_key, "wb") kf.write(pkey_pem) kf.close() csr_pem = crypto_util.make_csr(pkey_pem, [domain_name]) cf = open(csr, "wb") cf.write(csr_pem) cf.close() return pkey_pem, csr_pem, pkey
def _generate_csr(self) -> bytes: """Load or create private key.""" if self.path_private_key.exists(): _LOGGER.debug("Load private keyfile: %s", self.path_private_key) key_pem = self.path_private_key.read_bytes() else: _LOGGER.debug("create private keyfile: %s", self.path_private_key) key = OpenSSL.crypto.PKey() key.generate_key(OpenSSL.crypto.TYPE_RSA, PRIVATE_KEY_SIZE) key_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key) self.path_private_key.write_bytes(key_pem) self.path_private_key.chmod(0o600) return crypto_util.make_csr(key_pem, [self._domain])
def handle(self, *args, **kwargs): try: d = "*." + DOMAIN domains = list(set([d, DOMAIN, kwargs['domain'],])) letsencryptkey = os.path.join(FILES_DIR, 'ssl/account.pem') servercertpath = os.path.join(FILES_DIR, 'ssl/server.crt') serverkeypath = os.path.join(FILES_DIR, 'ssl/server.key') sys.stdout.write("[+] Writting to: {}\n".format(FILES_DIR)) self.start_verify_server(EXTERNAL_IP) TXTRECORDS.append("test123") client = self.create_acme_client(EMAIL) #Generate csr sys.stdout.write("[+] Generating server csr\t") serverkey = self.gen_key() pem = crypto.dump_privatekey(crypto.FILETYPE_PEM, serverkey) with open(serverkeypath, 'w') as f: f.write(pem.decode('utf-8')) csr = acme_crypto_util.make_csr(pem, domains, False) sys.stdout.write("OK!\n") sys.stdout.write("[+] Generating server cert\t") order = client.new_order(csr) for a in order.authorizations: c = self.get_challenge(a, challenges.DNS01) name, value = (c.validation_domain_name(a.body.identifier.value), c.validation(client.net.key)) TXTRECORDS.append(value) client.answer_challenge(c, c.response(client.net.key)) print(TXTRECORDS) order = client.poll_and_finalize(order) print(order) cert = crypto.load_certificate(crypto.FILETYPE_PEM, order.fullchain_pem) with open(servercertpath, 'w') as file: print("writting file") file.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8')) sys.stdout.write("OK!\n") sys.stdout.write("[+] Successfully signed certificate for '{}'\n".format(d)) sys.stdout.write("[+] Certificate and keys can be found under {}\n".format(os.path.join(FILES_DIR, 'ssl/'))) except acme.errors.ValidationError as e: raise sys.stdout.write("FAILED!\n")
def obtain_certificate(self, domains): """Obtains a certificate from the ACME server. `.register` must be called before `.obtain_certificate` :param list domains: domains to get a certificate :returns: certificate as PEM string, chain as PEM string, newly generated private key (`.util.Key`), and DER-encoded Certificate Signing Request (`.util.CSR`). :rtype: tuple """ # Create CSR from names if self.config.dry_run: key = util.Key(file=None, pem=crypto_util.make_key(self.config.rsa_key_size)) csr = util.CSR(file=None, form="pem", data=acme_crypto_util.make_csr( key.pem, domains, self.config.must_staple)) else: key = crypto_util.init_save_key(self.config.rsa_key_size, self.config.key_dir) csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir) orderr = self._get_order_and_authorizations( csr.data, self.config.allow_subset_of_names) authzr = orderr.authorizations auth_domains = set(a.body.identifier.value for a in authzr) successful_domains = [d for d in domains if d in auth_domains] # allow_subset_of_names is currently disabled for wildcard # certificates. The reason for this and checking allow_subset_of_names # below is because successful_domains == domains is never true if # domains contains a wildcard because the ACME spec forbids identifiers # in authzs from containing a wildcard character. if self.config.allow_subset_of_names and successful_domains != domains: if not self.config.dry_run: os.remove(key.file) os.remove(csr.file) return self.obtain_certificate(successful_domains) else: cert, chain = self.obtain_certificate_from_csr(csr, orderr) return cert, chain, key, csr
def generate_csr(self): """ Generates a new CSR using the object's `domains` and `private_key` values.\n - :return [`bytes`]: the encoded CSR PEM data string. This method will update the `csr` property of the object with the same value.\n - :raises `InvalidDomain`: when no valid `domains` are set.\n - :raises `InvalidPrivateKey`: when no `private_key` exists for this object.\n\n ## Example\n ```python >>> client.generate_csr() b'-----BEGIN CERTIFICATE REQUEST-----\\nMIHxMIGZAgECMAAwWTATBgckjkn...' ``` """ self.__validate_domains__() self.__validate_private_key__() self.csr = crypto_util.make_csr(self.private_key, self.domains) return self.csr
def obtain_certificate(self, domains): """Obtains a certificate from the ACME server. `.register` must be called before `.obtain_certificate` :param list domains: domains to get a certificate :returns: certificate as PEM string, chain as PEM string, newly generated private key (`.util.Key`), and DER-encoded Certificate Signing Request (`.util.CSR`). :rtype: tuple """ # Create CSR from names if self.config.dry_run: key = util.Key(file=None, pem=crypto_util.make_key(self.config.rsa_key_size)) csr = util.CSR(file=None, form="pem", data=acme_crypto_util.make_csr( key.pem, domains, self.config.must_staple)) else: key = crypto_util.init_save_key(self.config.rsa_key_size, self.config.key_dir) csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir) orderr = self.acme.new_order(csr.data) authzr = self.auth_handler.handle_authorizations( orderr, self.config.allow_subset_of_names) orderr = orderr.update(authorizations=authzr) auth_domains = set(a.body.identifier.value for a in authzr) successful_domains = [d for d in domains if d in auth_domains] if successful_domains != domains: if not self.config.dry_run: os.remove(key.file) os.remove(csr.file) return self.obtain_certificate(successful_domains) else: cert, chain = self.obtain_certificate_from_csr(csr, orderr) return cert, chain, key, csr
def generate_private_key(operation_id: int, **kwargs): operation = Operation.query.get(operation_id) service_instance = operation.service_instance operation.step_description = "Creating credentials for Lets Encrypt" flag_modified(operation, "step_description") db.session.add(operation) db.session.commit() if service_instance.new_certificate is not None: return certificate = Certificate() certificate.service_instance = service_instance service_instance.new_certificate = certificate certificate.subject_alternative_names = service_instance.domain_names # Create private key. private_key = OpenSSL.crypto.PKey() private_key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) # Get the PEM private_key_pem_in_binary = OpenSSL.crypto.dump_privatekey( OpenSSL.crypto.FILETYPE_PEM, private_key ) # Get the CSR for the domains csr_pem_in_binary = crypto_util.make_csr( private_key_pem_in_binary, service_instance.domain_names ) # Store them as text for later certificate.private_key_pem = private_key_pem_in_binary.decode("utf-8") certificate.csr_pem = csr_pem_in_binary.decode("utf-8") db.session.add(service_instance) db.session.add(operation) db.session.add(certificate) db.session.commit()
def obtain_certificate(self, domains): """Obtains a certificate from the ACME server. `.register` must be called before `.obtain_certificate` :param list domains: domains to get a certificate :returns: `.CertificateResource`, certificate chain (as returned by `.fetch_chain`), and newly generated private key (`.util.Key`) and DER-encoded Certificate Signing Request (`.util.CSR`). :rtype: tuple """ authzr = self.auth_handler.get_authorizations( domains, self.config.allow_subset_of_names) auth_domains = set(a.body.identifier.value for a in authzr) domains = [d for d in domains if d in auth_domains] # Create CSR from names if self.config.dry_run: key = util.Key(file=None, pem=crypto_util.make_key(self.config.rsa_key_size)) csr = util.CSR(file=None, form="pem", data=acme_crypto_util.make_csr( key.pem, domains, self.config.must_staple)) else: key = crypto_util.init_save_key(self.config.rsa_key_size, self.config.key_dir) csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir) certr, chain = self.obtain_certificate_from_csr(domains, csr, authzr=authzr) return certr, chain, key, csr
def test_blocked_key_cert(): # Only config-next has a blocked keys file configured. if not CONFIG_NEXT: return with open("test/test-ca.key", "r") as f: pemBytes = f.read() domains = [random_domain(), random_domain()] csr = acme_crypto_util.make_csr(pemBytes, domains, False) client = chisel2.make_client(None) order = client.new_order(csr) authzs = order.authorizations testPass = False cleanup = chisel2.do_http_challenges(client, authzs) try: order = client.poll_and_finalize(order) except acme_errors.Error as e: # TODO(@cpu): this _should_ be type # urn:ietf:params:acme:error:badPublicKey but this will require # refactoring the `csr` package error handling. # See https://github.com/letsencrypt/boulder/issues/4418 if e.typ != "urn:ietf:params:acme:error:malformed": raise Exception( "problem did not have correct error type, had {0}".format( e.typ)) if e.detail != "Error finalizing order :: invalid public key in CSR: public key is forbidden": raise Exception( "problem did not have correct error detail, had {0}".format( e.detail)) testPass = True if testPass is False: raise Exception( "expected cert creation to fail with Error when using blocked key")
def obtain_certificate(self, domains): """Obtains a certificate from the ACME server. `.register` must be called before `.obtain_certificate` :param list domains: domains to get a certificate :returns: `.CertificateResource`, certificate chain (as returned by `.fetch_chain`), and newly generated private key (`.util.Key`) and DER-encoded Certificate Signing Request (`.util.CSR`). :rtype: tuple """ authzr = self.auth_handler.get_authorizations( domains, self.config.allow_subset_of_names) auth_domains = set(a.body.identifier.value for a in authzr) domains = [d for d in domains if d in auth_domains] # Create CSR from names if self.config.dry_run: key = util.Key(file=None, pem=crypto_util.make_key(self.config.rsa_key_size)) csr = util.CSR(file=None, form="pem", data=acme_crypto_util.make_csr( key.pem, domains, self.config.must_staple)) else: key = crypto_util.init_save_key( self.config.rsa_key_size, self.config.key_dir) csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir) certr, chain = self.obtain_certificate_from_csr( domains, csr, authzr=authzr) return certr, chain, key, csr
def obtain_certificate(self, domains, old_keypath=None): """Obtains a certificate from the ACME server. `.register` must be called before `.obtain_certificate` :param list domains: domains to get a certificate :returns: certificate as PEM string, chain as PEM string, newly generated private key (`.util.Key`), and DER-encoded Certificate Signing Request (`.util.CSR`). :rtype: tuple """ # We need to determine the key path, key PEM data, CSR path, # and CSR PEM data. For a dry run, the paths are None because # they aren't permanently saved to disk. For a lineage with # --reuse-key, the key path and PEM data are derived from an # existing file. if old_keypath is not None: # We've been asked to reuse a specific existing private key. # Therefore, we'll read it now and not generate a new one in # either case below. # # We read in bytes here because the type of `key.pem` # created below is also bytes. with open(old_keypath, "rb") as f: keypath = old_keypath keypem = f.read() key: Optional[util.Key] = util.Key(file=keypath, pem=keypem) logger.info("Reusing existing private key from %s.", old_keypath) else: # The key is set to None here but will be created below. key = None key_size = self.config.rsa_key_size elliptic_curve = "secp256r1" # key-type defaults to a list, but we are only handling 1 currently if isinstance(self.config.key_type, list): self.config.key_type = self.config.key_type[0] if self.config.elliptic_curve and self.config.key_type == 'ecdsa': elliptic_curve = self.config.elliptic_curve self.config.auth_chain_path = "./chain-ecdsa.pem" self.config.auth_cert_path = "./cert-ecdsa.pem" self.config.key_path = "./key-ecdsa.pem" elif self.config.rsa_key_size and self.config.key_type.lower( ) == 'rsa': key_size = self.config.rsa_key_size # Create CSR from names if self.config.dry_run: key = key or util.Key( file=None, pem=crypto_util.make_key( bits=key_size, elliptic_curve=elliptic_curve, key_type=self.config.key_type, ), ) csr = util.CSR(file=None, form="pem", data=acme_crypto_util.make_csr( key.pem, domains, self.config.must_staple)) else: key = key or crypto_util.generate_key( key_size=key_size, key_dir=self.config.key_dir, key_type=self.config.key_type, elliptic_curve=elliptic_curve, strict_permissions=self.config.strict_permissions, ) csr = crypto_util.generate_csr(key, domains, self.config.csr_dir, self.config.must_staple, self.config.strict_permissions) orderr = self._get_order_and_authorizations( csr.data, self.config.allow_subset_of_names) authzr = orderr.authorizations auth_domains = set(a.body.identifier.value for a in authzr) successful_domains = [d for d in domains if d in auth_domains] # allow_subset_of_names is currently disabled for wildcard # certificates. The reason for this and checking allow_subset_of_names # below is because successful_domains == domains is never true if # domains contains a wildcard because the ACME spec forbids identifiers # in authzs from containing a wildcard character. if self.config.allow_subset_of_names and successful_domains != domains: if not self.config.dry_run: os.remove(key.file) os.remove(csr.file) return self.obtain_certificate(successful_domains) else: cert, chain = self.obtain_certificate_from_csr(csr, orderr) return cert, chain, key, csr
def make_csr(domains): key = OpenSSL.crypto.PKey() key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key) return acme_crypto_util.make_csr(pem, domains, False)
def obtain_certificate(self, domains, old_keypath=None): """Obtains a certificate from the ACME server. `.register` must be called before `.obtain_certificate` :param list domains: domains to get a certificate :returns: certificate as PEM string, chain as PEM string, newly generated private key (`.util.Key`), and DER-encoded Certificate Signing Request (`.util.CSR`). :rtype: tuple """ # We need to determine the key path, key PEM data, CSR path, # and CSR PEM data. For a dry run, the paths are None because # they aren't permanently saved to disk. For a lineage with # --reuse-key, the key path and PEM data are derived from an # existing file. if old_keypath is not None: # We've been asked to reuse a specific existing private key. # Therefore, we'll read it now and not generate a new one in # either case below. # # We read in bytes here because the type of `key.pem` # created below is also bytes. with open(old_keypath, "rb") as f: keypath = old_keypath keypem = f.read() key = util.Key(file=keypath, pem=keypem) # type: Optional[util.Key] logger.info("Reusing existing private key from %s.", old_keypath) else: # The key is set to None here but will be created below. key = None # Create CSR from names if self.config.dry_run: key = key or util.Key(file=None, pem=crypto_util.make_key(self.config.rsa_key_size)) csr = util.CSR(file=None, form="pem", data=acme_crypto_util.make_csr( key.pem, domains, self.config.must_staple)) else: key = key or crypto_util.init_save_key(self.config.rsa_key_size, self.config.key_dir) csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir) orderr = self._get_order_and_authorizations(csr.data, self.config.allow_subset_of_names) authzr = orderr.authorizations auth_domains = set(a.body.identifier.value for a in authzr) # pylint: disable=not-an-iterable successful_domains = [d for d in domains if d in auth_domains] # allow_subset_of_names is currently disabled for wildcard # certificates. The reason for this and checking allow_subset_of_names # below is because successful_domains == domains is never true if # domains contains a wildcard because the ACME spec forbids identifiers # in authzs from containing a wildcard character. if self.config.allow_subset_of_names and successful_domains != domains: if not self.config.dry_run: os.remove(key.file) os.remove(csr.file) return self.obtain_certificate(successful_domains) else: cert, chain = self.obtain_certificate_from_csr(csr, orderr) return cert, chain, key, csr
def _call_with_key(cls, *args, **kwargs): privkey = OpenSSL.crypto.PKey() privkey.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) privkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, privkey) from acme.crypto_util import make_csr return make_csr(privkey_pem, *args, **kwargs)
def run_acme_reg_to_finish(domain, accnt_key, priv_key, hostname, tmp_chall_dict, directory_url): '''Runs the entire process of ACME registeration''' client = create_v2_client(directory_url, accnt_key) # First we need to create a registration with the email address provided # and accept the terms of service log.info("Using boulder server %s", directory_url) client.net.account = client.new_account( messages.NewRegistration.from_data(terms_of_service_agreed=True)) # Now we need to open an order and request our certificate # NOTE: We'll let ACME generate a CSR for our private key as there's # a lot of utility code it uses to generate the CSR in a specific # fashion. Better to use what LE provides than to roll our own as we # we doing with the v1 code # # This will also let us support multi-domain certificat requests in the # future, as well as mandate OCSP-Must-Staple if/when GL's HTTPS server # supports it csr = crypto_util.make_csr(priv_key, [hostname], False) order = client.new_order(csr) authzr = order.authorizations log.info('Created a new order for %s', hostname) # authrz is a list of Authorization resources, we need to find the # HTTP-01 challenge and use it for auth_req in authzr: # pylint: disable=not-an-iterable for chall_body in auth_req.body.challenges: if isinstance(chall_body.chall, challenges.HTTP01): challb = chall_body break if challb is None: raise Exception("HTTP01 challenge unavailable!") response, chall_tok = challb.response_and_validation(client.net.key) v = chall_body.chall.encode("token") log.info('Exposing challenge on %s', v) tmp_chall_dict.set(v, ChallTok(chall_tok)) cr = client.answer_challenge(challb, challb.response(client.net.key)) log.debug('Acme CA responded to challenge request with: %s', cr) # Wrap this step and log the failure particularly here because this is # the expected point of failure for applications that are not reachable # from the public internet. try: order = client.poll_and_finalize(order) except messages.Error as error: log.err("Failed in request issuance step %s", error) raise # ACME V2 returns a full chain certificate, and ACME doesn't ship with # helper functions out of the box. Fortunately, searching through cerbot # this is easily enough to do with pyOpenSSL cert = load_certificate(FILETYPE_PEM, order.fullchain_pem) cert_str = dump_certificate(FILETYPE_PEM, cert).decode() chain_str = order.fullchain_pem[len(cert_str):].lstrip() # pylint: disable=no-member expr_date = convert_asn1_date(cert.get_notAfter()) log.info('Retrieved cert using ACME that expires on %s', expr_date) return cert_str, chain_str
def wildcard_request(cn, account): def dns_check_ns1(): recieved_data_dup = [] recieved_data = [] ns1_resolver = dns.resolver.Resolver() #ns1_resolver.nameservers = ['130.193.8.82','2a03:b780::1:1'] ns1_resolver.nameservers = ['173.245.58.51'] for data in validation_data: domainname = data[1] #challenge = data[0] answers = ns1_resolver.query(domainname, 'txt') for rdata in answers: recieved_data_dup.append( [str(rdata).replace('"', ''), domainname]) #Deduplication of ns records (in case of more cnames) for i in recieved_data_dup: if i not in recieved_data: recieved_data.append(i) # print sorted(recieved_data) # print sorted(validation_data) if sorted(validation_data) == sorted(recieved_data): return True else: return False #Check if CN is valid domain domain_regex = re.compile( "^([a-zA-Z0-9]([\-a-zA-Z0-9]{0,61}[a-zA-Z0-9])?\.)*([a-zA-Z0-9]([\-a-zA-Z0-9]{0,61}[a-zA-Z0-9])+\.)([a-zA-Z0-9]+([\-a-zA-Z0-9]{0,61}[a-zA-Z])+)$" ) if not domain_regex.match(cn): print 'First argument is not valid CN' sys.exit(1) #Check if registrar exists if account not in os.listdir(REG_DIRECTORY): print "This account does not exists, register it first with new_account.py" sys.exit(1) #Load files from disk with open(REG_DIRECTORY + "/" + account + "/private.key", "rb") as key_file: privkey = serialization.load_pem_private_key(key_file.read(), password=None, backend=default_backend()) with open(REG_DIRECTORY + "/" + account + "/reguri.txt", "r") as reguri_file: reg_uri = reguri_file.read() #Compose regr key = jose.JWKRSA(key=privkey) regr = messages.RegistrationResource( body=messages.Registration(key=key.public_key()), uri=reg_uri) #Init ACME net = ClientNetwork(key) directory = net.get(DIRECTORY_URL).json() acme = client.ClientV2(directory, net) #Check if registration is valid if acme.query_registration(regr).body.status == u'valid': print "Registration valid" else: print "Registration invalid" sys.exit(1) #Generate private key for certificate pkey = OpenSSL.crypto.PKey() pkey.generate_key(OpenSSL.crypto.TYPE_RSA, BITS) #Serialize key for output pkey_printable = OpenSSL.crypto.dump_privatekey( OpenSSL.crypto.FILETYPE_PEM, pkey, cipher=None, passphrase=None) #Compose request for acme req = crypto_util.make_csr( OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, pkey), [cn, '*.' + cn]) #begin order orderr = acme.new_order(req) validation_data = [] for authr in orderr.authorizations: for chalr in authr.body.challenges: if type(chalr.chall) == type(challenges.DNS01()): validation_data.append([ str(chalr.chall.validation(key)), chalr.chall.validation_domain_name(cn) ]) #print validation_data #Now, call DNS writing function to apply challenges dns_apply(cn, validation_data) #Check if DNS is valid on our server sys.stdin.readline() #DEBUG: wait for manual DNS input limiter = 2 while not dns_check_ns1(): if limiter != 0: print "DNS records are not correct, trying again in few seconds" limiter = limiter - 1 time.sleep(5) else: print "DNS are not correct even after several tries. Aborting" sys.exit(1) for authr in orderr.authorizations: for chalr in authr.body.challenges: if type(chalr.chall) == type(challenges.DNS01()): try: acme.answer_challenge(chalr, challenges.DNS01Response()) except: print chalr.chall.encode( 'token' ) + " already answered (challenge failed, you have to generate new one)" #After filling DNS and waiting for propagation, finalize order try: res = acme.poll_and_finalize(orderr) finally: dns_remove(cn) #logging.info(res) cert = x509.load_pem_x509_certificate(str(res.fullchain_pem), default_backend()) output_data = { 'wildcard': { 'cn': cn, 'private_key': str(pkey_printable), 'certificate': str(res.fullchain_pem), 'expiration': cert.not_valid_after.strftime( "%x %X" ) #Locale-specific time+date representation. Edit to your need } } print json.dumps(output_data)