Source code for utils.cloud_init

import crypt
import os
import string
try:  # 3.6 or above
    from secrets import choice as randchoice
except ImportError:
    from random import SystemRandom
    randchoice = SystemRandom().choice


[docs] def generate_random_salt(): """ Generate a cryptographically secure random salt for password hashing. Returns ------- salt : str A hexadecimal string representing the generated random salt. Notes ----- This function uses the os.urandom() function to generate a random salt with 16 bytes of entropy, which is then converted to a hexadecimal string. The generated salt is suitable for use in password hashing algorithms to enhance security and prevent rainbow table attacks. """ # Generate a random 16-byte salt salt = os.urandom(16) # Convert the salt to hexadecimal representation salt_hex = salt.hex() return salt_hex
[docs] def cloud_init_sha512_crypt(password: str, salt: str = None, rounds: int = None): """ Generate a SHA-512 crypt hash suitable for cloud-init configuration. Parameters ---------- password : str The password to be hashed. salt : str, optional The salt value to use in the hash (default is None, a random salt will be generated). rounds : int, optional The number of rounds for hashing (default is None, using a default of 5000 rounds). Rounds must be within the range 1000 to 999999999. Returns ------- str The SHA-512 crypt hash of the password. Notes ----- This function generates a SHA-512 crypt hash suitable for cloud-init configuration. If `salt` is not provided, a random 8-character salt is generated. The `rounds` parameter determines the number of hashing rounds; if not provided, a default of 5000 rounds is used. The resulting hash is returned as a string. """ # Adapted from code by Martijn Pieters on Stack Overflow # Original source: https://stackoverflow.com/questions/34463134/sha-512-crypt-output-written-with-python-code-is-different-from-mkpasswd if salt is None: salt = ''.join([ randchoice(string.ascii_letters + string.digits) for _ in range(8) ]) prefix = '$6$' if rounds is not None: rounds = max(1000, min(999999999, rounds or 5000)) prefix += f'rounds={rounds}$' return str(crypt.crypt(password, prefix + salt))