def _load_account_key(self) -> None: """Load or create account key.""" key = None if self.path_account_key.exists(): _LOGGER.debug("Load account keyfile: %s", self.path_account_key) pem = self.path_account_key.read_bytes() key = serialization.load_pem_private_key(pem, password=None, backend=default_backend()) else: _LOGGER.debug("Create new RSA keyfile: %s", self.path_account_key) key = rsa.generate_private_key( public_exponent=65537, key_size=ACCOUNT_KEY_SIZE, backend=default_backend(), ) # Store it to file pem = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(), ) self.path_account_key.write_bytes(pem) self.path_account_key.chmod(0o600) self._account_jwk = jose.JWKRSA(key=jose.ComparableRSAKey(key))
def _generate_keypair(cls): """ generate the jwk keypair for the key request :return: the JWKRSA object """ rsa_key = generate_private_key(public_exponent=65537, key_size=4096, backend=default_backend()) return josepy.JWKRSA(key=josepy.ComparableRSAKey(rsa_key))
def load_rsa_private_key(*names: str) -> jose.ComparableRSAKey: """Load RSA private key.""" loader = _guess_loader(names[-1], crypto.FILETYPE_PEM, crypto.FILETYPE_ASN1) loader_fn: Callable[..., Any] if loader == crypto.FILETYPE_PEM: loader_fn = serialization.load_pem_private_key else: loader_fn = serialization.load_der_private_key return jose.ComparableRSAKey( loader_fn(load_vector(*names), password=None, backend=default_backend()))
def load_or_generate_private_key(keyfile, log): from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives import serialization if os.path.exists(keyfile): # Load from file. log("Reading account key from %s." % keyfile) with open(keyfile, 'rb') as f: pem = f.read() key = serialization.load_pem_private_key(pem, password=None, backend=default_backend()) elif not os.path.exists(os.path.dirname(keyfile)): # Directory for storage does not exist. raise ValueError("The path %s does not exist." % os.path.dirname(keyfile)) else: # Generate new key and write to file. log("Generating a new account key.") key = rsa.generate_private_key(public_exponent=65537, key_size=ACCOUNT_KEY_SIZE, backend=default_backend()) pem = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(), ) with open(keyfile, 'wb') as f: f.write(pem) key = jose.JWKRSA(key=jose.ComparableRSAKey(key)) return key
def register(config, account_storage, tos_cb=None): """Register new account with an ACME CA. This function takes care of generating fresh private key, registering the account, optionally accepting CA Terms of Service and finally saving the account. It should be called prior to initialization of `Client`, unless account has already been created. :param certbot.configuration.NamespaceConfig config: Client configuration. :param .AccountStorage account_storage: Account storage where newly registered account will be saved to. Save happens only after TOS acceptance step, so any account private keys or `.RegistrationResource` will not be persisted if `tos_cb` returns ``False``. :param tos_cb: If ACME CA requires the user to accept a Terms of Service before registering account, client action is necessary. For example, a CLI tool would prompt the user acceptance. `tos_cb` must be a callable that should accept `.RegistrationResource` and return a `bool`: ``True`` iff the Terms of Service present in the contained `.Registration.terms_of_service` is accepted by the client, and ``False`` otherwise. ``tos_cb`` will be called only if the client action is necessary, i.e. when ``terms_of_service is not None``. This argument is optional, if not supplied it will default to automatic acceptance! :raises certbot.errors.Error: In case of any client problems, in particular registration failure, or unaccepted Terms of Service. :raises acme.errors.Error: In case of any protocol problems. :returns: Newly registered and saved account, as well as protocol API handle (should be used in `Client` initialization). :rtype: `tuple` of `.Account` and `acme.client.Client` """ # Log non-standard actions, potentially wrong API calls if account_storage.find_all(): logger.info("There are already existing accounts for %s", config.server) if config.email is None: if not config.register_unsafely_without_email: msg = ("No email was provided and " "--register-unsafely-without-email was not present.") logger.error(msg) raise errors.Error(msg) if not config.dry_run: logger.debug("Registering without email!") # If --dry-run is used, and there is no staging account, create one with no email. if config.dry_run: config.email = None # Each new registration shall use a fresh new key rsa_key = generate_private_key(public_exponent=65537, key_size=config.rsa_key_size, backend=default_backend()) key = jose.JWKRSA(key=jose.ComparableRSAKey(rsa_key)) acme = acme_from_config_key(config, key) # TODO: add phone? regr = perform_registration(acme, config, tos_cb) acc = account.Account(regr, key) account_storage.save(acc, acme) eff.prepare_subscription(config, acc) return acc, acme
def load_rsa_private_key(*names): """Load RSA private key.""" loader = _guess_loader(names[-1], serialization.load_pem_private_key, serialization.load_der_private_key) return jose.ComparableRSAKey( loader(load_vector(*names), password=None, backend=default_backend()))