
Contraseñas fuera de la política
Tengo la sensación de que ya he escrito una función para generar contraseñas cinco veces. Y lo hizo de manera diferente cada vez. Y la razón de esto son los diferentes requisitos de contraseña para diferentes proyectos y herramientas. No habrá código complejo, solo un resumen de una nueva solución simple que me llegó ayer.
Comencemos con requisitos simples de contraseña:
- debe ser de longitud arbitraria
- debe constar de caracteres impresos
import string
import random
from typing import List
def generate_password(length: int) -> str:
"""
Generate a password of a given `length`.
"""
result: List[str] = []
choices = string.printable
while len(result) < length:
symbol = random.choice(string.printable)
result.append(symbol)
return "".join(result)
Intentamos:
>>> generate_password(8)
... "1{k]/2)h"
>>> generate_password(13)
... "9ar|&:a+U]Il$"
Bueno, la tarea está completa, podemos ver fotos con gatos hasta el final de la jornada laboral.
Política repentina
, , MyDB . , :
, . :
Bien, esto ya es complicado, así que comencemos con una función generate_random_string
que simplemente generará cadenas aleatorias de lo que dieron.
import string
import random
from typing import List
def generate_random_string(length: int, *choices: str) -> str:
"""
Generate a string of a given `length`.
The result has at least one symbol from each of `choices` if `length` allows.
Arguments:
length -- Result string length.
choices -- Strings with available symbols.
"""
if not choices:
choices = (string.ascii_letters, )
all_choices = "".join(choices)
result: List[str] = []
choice_index = 0
while len(result) < length:
if choice_index < len(choices):
symbol = random.choice(choices[choice_index])
result.append(symbol)
choice_index += 1
continue
symbol = random.choice(all_choices)
result.append(symbol)
random.shuffle(result)
return "".join(result)
Entonces intentemos:
>>>
>>> generate_random_string(8, string.digits)
... "59197550"
>>>
>>> generate_random_string(8, string.ascii_letters, "!")
... "vIOWXN!o"
Genial, es hora de generar una contraseña que cumpla con todos nuestros requisitos.
def generate_mydb_password(length: int) -> str:
"""
Generate a random password for MyDB of a given `length`.
The result has at least:
- one uppercase letter
- one lowercase letter
- one digit
- one special character
Raises:
ValueError -- If `length` is lesser than 8.
"""
if length < 8:
raise ValueError("Password length should be at least 8")
return generate_random_string(
length,
string.ascii_uppercase,
string.ascii_lowercase,
string.digits,
"!&?",
)
Solo queda comprobar:
>>> generate_mydb_password(8)
... "P?P1&7zL"
>>> generate_mydb_password(13)
... "tR!QslK!Sl7EO"
>>> generate_mydb_password(2)
... ValueError: Password length should be at least 8
Total
Escribimos un generador de contraseñas fácil de entender y al mismo tiempo bastante aleatorio, y todavía queda mucho tiempo hasta el final de la jornada laboral. Si no hay confianza en la biblioteca random
, puede reemplazarla por la que desee.
¡Gracias por la atención!