Source code for cryptopyutils.config

# -*- coding: utf-8 -*-
"""config.py - Configuration file

Configuration of defaults

You can update the config according to your needs.

"""
import os
import platform
import sys
from os.path import expanduser

import distro


[docs]class Base: """Base class""" def __init__(self, **kwargs): """Base class initiator""" for attr, value in kwargs.items(): self.__setattr__(attr, value)
[docs] def copy(self, source): """Copy attributes from a source object Args: source (obj): source object Returns: obj: self """ self.__dict__.update(source.__dict__) return self
[docs]class SysConfig(Base): """SysConfig class - System Configuration - system information - extends Base""" def __init__(self, **kwargs): super().__init__(**kwargs) self.operating_system = os.name self.sys_platform = sys.platform self.platform_system = platform.system() self.platform_release = platform.release() if self.platform_system in ["Linux"]: self.distro = distro.id() else: self.distro = None
[docs]class ProjConfig(Base): """Projconfig class - Project Configuration - extends SysConfig""" def __init__(self, **kwargs): super().__init__(**kwargs) self.sysconfig = kwargs.pop("sysconfig", SysConfig()) # Default host self.host = kwargs.pop("host", "localhost") # Default output directory self.output_directory = kwargs.pop("output_directory", expanduser("~")) # Default file_mode self.file_mode = kwargs.pop("file_mode", 0o600)
[docs]class PasswordConfig(Base): """PasswordConfig class - Password Configuration class - extends Base Args: hash_algorithm (str): the name of the hash algorithm. Defaults to SHA-256. salt_length (int) – The number of bytes of the salt. Secure values are 16 (128-bits) or longer and randomly generated. Defaults to 16. length (int) – The desired length of the derived key in bytes. Maximum is (232 - 1) * algorithm.digest_size. Defaults to 32. iterations (int) – The number of iterations to perform of the hash function. This can be used to control the length of time the operation takes. Higher numbers help mitigate brute force attacks against derived keys. Defaults to 390000. """ def __init__(self, **kwargs): """ "PasswordConfig class initiator""" super().__init__(**kwargs) self.hash_algorithm = kwargs.pop("hash_algorithm", "SHA-256") self.salt_length = kwargs.pop("salt_length", 16) self.key_length = kwargs.pop("key_length", 32) self.iterations = kwargs.pop("iterations", 390000)
[docs]class AsymConfig(ProjConfig): """AsymConfig class - Asymmetric Configuration class - extends ProjConfig""" def __init__(self, **kwargs): """AsymConfig class initiator""" super().__init__(**kwargs) # Default algorithm self.priv_key_alg = kwargs.pop("priv_key_alg", "rsa") # Default SSL Directories if not hasattr(self, "ssl_dir"): self.ssl_dir = kwargs.pop("ssl_dir", None) if self.ssl_dir is None: self.set_ssl_dir() # Default encoding self.encoding = kwargs.pop("encoding", "PEM") # Hash algorithm self.hash_alg = kwargs.pop("hash_alg", "SHA-256")
[docs] def set_ssl_dir(self, path=None): """Set the SSL directory Args: path (str, optional): Path to the SSL directory. Defaults to None. Returns: str: The path to the ssl directory """ if path is not None: self.ssl_dir = path else: # Default SSL directories if self.sysconfig.distro in [ "ubuntu", "debian", "linuxmint", "raspbian", "sles", "opensuse", "arch", "gentoo", "exherbo", "slackware", ]: self.ssl_dir = "/etc/ssl" elif self.sysconfig.distro in [ "rhel", "centos", "fedora", "amazon", "oracle", "scientific", "cloudlinux", "xenserver", "pidora", "mageia", "mandriva", ]: self.ssl_dir = "/etc/pki/tls" elif self.sysconfig.distro in ["openbsd", "netbsd", "freebsd"]: self.ssl_dir = "/etc/ssl" else: self.ssl_dir = "/etc/ssl" return self.ssl_dir
[docs]class PrivateKeyConfig(Base): """PrivateKeyConfig class - Private Key Configuration - extends AsymConfig""" def __init__(self, **kwargs): """PrivateKeyConfig class initiator""" super().__init__(**kwargs) # SSL Directory self.ssl_dir = kwargs.pop("ssl_dir", "/etc/ssl") # Default directory if not hasattr(self, "key_dir"): self.key_dir = kwargs.pop("key_dir", None) if self.key_dir is None: self.set_key_dir() # Default algorithm self.alg = kwargs.pop("alg", "RSA") # Default file mode self.file_mode = kwargs.pop("file_mode", 0o600) # Default encoding self.encoding = kwargs.pop("encoding", "PEM") # Default file format self.file_format = kwargs.pop("file_format", "PKCS8") # Default key sizes # RSA Key Size - Minimum should be 2048 bits. self.rsa_key_size = kwargs.pop("rsa_key_size", 4096) # RSA Public Exponent - 65537 self.rsa_public_exponent = kwargs.pop("rsa_public_exponent", 65537) # DSA - Minimum 1024 bits self.dsa_key_size = kwargs.pop("dsa_key_size", 4096) # Elliptic Curves - NIST P-256 and P-384 are okay (with caveats) # Ed25519 is great alternative # https://soatok.blog/2022/05/19/guidance-for-choosing-an-elliptic-curve-signature-algorithm-in-2022/ # https://malware.news/t/everyone-loves-curves-but-which-elliptic-curve-is-the-most-popular/17657 self.elliptic_curve = "SECP384R1" # Hash algorithm self.hash_alg = kwargs.pop("hash_alg", "SHA-256")
[docs] def set_key_dir(self, path=None): """Set the SSL private key directory Args: path (str: optional): Path to the SSL private key directory. Defaults to None. """ if path is not None: self.key_dir = path else: self.key_dir = os.path.join(self.ssl_dir, "private")
[docs]class PublicKeyConfig(Base): """PublicKeyConfig initiator - Public Key Configuration - extends AsymConfig""" def __init__(self, **kwargs): """PublicKeyConfig class initiator""" super().__init__(**kwargs) # SSL Directory self.ssl_dir = kwargs.pop("ssl_dir", "/etc/ssl") # Default directory if not hasattr(self, "ssl_key_dir"): self.key_dir = kwargs.pop("key_dir", None) if self.key_dir is None: self.set_key_dir() # Default algorithm self.alg = kwargs.pop("alg", "RSA") # Default file mode self.file_mode = kwargs.pop("file_mode", 0o644) # Default public encoding self.encoding = kwargs.pop("encoding", "PEM") # Default file format self.file_format = kwargs.pop("file_format", "PKCS8") # Default file format self.file_format = kwargs.pop("file_format", "SubjectPublicKeyInfo") # Hash algorithm self.hash_alg = kwargs.pop("hash_alg", "SHA-256")
[docs] def set_key_dir(self, path=None): """Set the SSL public key directory Args: path (str: optional): Path to the SSL public key directory. Defaults to None. """ if path is not None: self.key_dir = path else: self.key_dir = os.path.join(self.ssl_dir, "public")
[docs]class X509Config(AsymConfig): """X509Config class - x509 Configuration - extends AsymConfig""" def __init__(self, **kwargs): """X509Config class initiator""" super().__init__(**kwargs) # Projet configuration self.asymconfig = kwargs.pop("asymconfig", AsymConfig()) # Issuer self.issuer = { "COMMON_NAME": "www.example.com", "LOCALITY_NAME": "San Francisco", "STATE_OR_PROVINCE_NAME": "California", "ORGANIZATION_NAME": "Example inc", "ORGANIZATIONAL_UNIT_NAME": "Example Division", "COUNTRY_NAME": "US", "STREET_ADDRESS": "0000 Acme Road", } self.subject = self.issuer
[docs]class CertConfig(X509Config): """CertConfig class - x509 Certificate Configuration - extends x509Config""" def __init__(self, **kwargs): """CertConfig class initiator""" super().__init__(**kwargs) # Default directory if not hasattr(self, "cert_dir"): self.cert_dir = kwargs.pop("cert_dir", None) if self.cert_dir is None: self.set_cert_dir() # Self-signed mode False by default self.self_signed = kwargs.pop("self_signed", False) # Default file mode self.file_mode = kwargs.pop("file_mode", 0o644) # Default encoding self.encoding = kwargs.pop("encoding", "PEM") # Default expiration in days self.expiration_days = kwargs.pop("expiration_days", 3650) # Certificate authority : False = Not a certificat authority, # cannot sign other certificates if self.self_signed: self.cert_auth = kwargs.pop("cert_auth", False) else: self.cert_auth = kwargs.pop("cert_auth", True) # Default DNS Names if self.self_signed: # Bug fix: 127.0.0.1 needed in DNS names self.dns_names = kwargs.pop( "dns_names", ["localhost", "127.0.0.1"], ) else: self.dns_names = kwargs.pop("dns_names", []) # Default IP addresses if self.self_signed: self.ip_addrs = kwargs.pop("ip_addrs", ["127.0.0.1"]) else: self.ip_addrs = kwargs.pop("ip_addrs", []) # Critical: Are DNS Names and IP Addrs an important part of the certificate self.critical = kwargs.pop("critical", True) # Path Length : Can be 1 if CA=True if self.cert_auth: self.path_length = kwargs.pop("path_length", 1) else: self.path_length = kwargs.pop("path_length", None)
[docs] def set_cert_dir(self, path=None): """Set the SSL Certificate directory Args: path (str: optional): Path to the SSL certificate directory. Defaults to None. """ if path is not None: self.cert_dir = path else: self.cert_dir = os.path.join(self.asymconfig.ssl_dir, "certs")
[docs]class CSRConfig(X509Config): """CSRConfig class - x509 CSR Configuration - extends x509Config""" def __init__(self, **kwargs): """CSRConfig class initiator""" super().__init__(**kwargs) # Default directory if not hasattr(self, "csr_dir"): self.ssl_csr_dir = kwargs.pop("csr_dir", None) if self.ssl_csr_dir is None: self.set_csr_dir() # Default file mode self.file_mode = kwargs.pop("file_mode", 0o644) # Default encoding self.encoding = kwargs.pop("encoding", "PEM") # Default DNS names self.dns_names = kwargs.pop("dns_names", []) # Default IP addresses self.ip_addrs = kwargs.pop("ip_addrs", [])
[docs] def set_csr_dir(self, path=None): """Set the SSL CSR directory Args: path (str: optional): Path to the SSL CSR directory. Defaults to None. """ if path is not None: self.csr_dir = path else: self.csr_dir = os.path.join(self.asymconfig.ssl_dir, "csr")
[docs]class SSHKeyPairConfig(Base): """SSHKeyPairConfig class - Configuration for SSH Key Pair""" def __init__(self, **kwargs): """SSHKeyPairConfig class initiator""" super().__init__(**kwargs) # Default SSL Directories self.set_user_dir() self.set_host_dir() # Variables self.dsa_key_size = 1024 # Hash algorithm self.hash_alg = kwargs.pop("hash_alg", "SHA-256")
[docs] def set_user_dir(self, path=None): """Set the SSH user directory Args: path (str: optional): Path to the SSH user directory. Defaults to None. """ if path is not None: self.user_dir = path else: self.user_dir = os.path.join(expanduser("~"), "/.ssh")
[docs] def set_host_dir(self, path=None): """Set the SSH host directory Args: path (str: optional): Path to the SSH host directory. Defaults to None. """ if path is not None: self.host_dir = path else: self.host_dir = "/etc/ssh"