#!/usr/bin/env bash # generate_password # ----------------- # Genera contraseñas seguras en varios modos: completo (alfanumérico + símbolos), # solo alfanumérico, passphrase de palabras o PIN numérico. # Calcula la entropía en bits para cada contraseña generada. # # USO (directo): # generate_password [full|alpha|passphrase|pin] [longitud] [cantidad] # # Depende de: /dev/urandom, python3 (para entropía), shuf (para passphrases) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../shell/bash_colors.sh" source "$SCRIPT_DIR/../shell/bash_log.sh" bash_colors bash_log_init # ─── Constantes ─────────────────────────────────────────────────────────────── _GENPW_DEFAULT_LENGTH=16 _GENPW_DEFAULT_COUNT=1 _GENPW_WORDLIST_PATHS=("/usr/share/dict/words" "/usr/dict/words" "/usr/share/dict/american-english") # ─── Funciones puras ────────────────────────────────────────────────────────── _genpw_find_wordlist() { for path in "${_GENPW_WORDLIST_PATHS[@]}"; do [[ -f "$path" ]] && echo "$path" && return done echo "" } _genpw_calc_entropy() { local charset_size="$1" local length="$2" python3 -c "import math; print(f'{math.log2(${charset_size}**${length}):.1f}')" 2>/dev/null || echo "?" } # ─── Funciones de generación ────────────────────────────────────────────────── _genpw_gen_full() { local length="$1" # Alfanumérico + símbolos (excluye ambiguos: 0OlI1) tr -dc 'A-HJ-NP-Za-km-z2-9!@#$%^&*()_+-=[]{}|;:,.<>?' \ < /dev/urandom | head -c "$length" echo } _genpw_gen_alpha() { local length="$1" tr -dc 'A-HJ-NP-Za-km-z2-9' \ < /dev/urandom | head -c "$length" echo } _genpw_gen_passphrase() { local words="$1" local wordlist wordlist="$(_genpw_find_wordlist)" if [[ -z "$wordlist" ]]; then error "generate_password: no se encontró diccionario (sudo apt install wamerican)" >&2 return 1 fi local phrase="" for ((i=0; i&2 return 1 fi local charset_size entropy case "$mode" in full) charset_size=78 entropy="$(_genpw_calc_entropy $charset_size "$length")" info "Contraseñas alfanuméricas + símbolos (longitud: ${length}, entropía: ~${entropy} bits)" echo "" for ((i=1; i<=count; i++)); do _genpw_gen_full "$length" done ;; alpha) charset_size=56 entropy="$(_genpw_calc_entropy $charset_size "$length")" info "Contraseñas alfanuméricas (longitud: ${length}, entropía: ~${entropy} bits)" echo "" for ((i=1; i<=count; i++)); do _genpw_gen_alpha "$length" done ;; passphrase) info "Passphrases (${length} palabras)" echo "" for ((i=1; i<=count; i++)); do _genpw_gen_passphrase "$length" || return 1 done ;; pin) charset_size=10 entropy="$(_genpw_calc_entropy $charset_size "$length")" info "PINs numéricos (longitud: ${length}, entropía: ~${entropy} bits)" echo "" for ((i=1; i<=count; i++)); do _genpw_gen_pin "$length" done ;; *) error "generate_password: modo no válido '$mode'. Use: full|alpha|passphrase|pin" >&2 return 1 ;; esac } # Ejecutar si se llama directamente if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then generate_password "$@" fi