Reescribiendo el generador de contraseñas

Política de contraseñas


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 . , :


  • 8
  • - (!&? )
  • , bash-

, . :


  • , , -
  • ,


Bien, esto ya es complicado, así que comencemos con una función generate_random_stringque 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!

Source: https://habr.com/ru/post/undefined/


All Articles