- Reemplazar todos los mensajes mostrados con echo por llamadas a dialog - Mostrar errores de dependencias con dialog_error_box cuando sea posible - Usar dialog para confirmaciones de operación cancelada - Mantener mensaje echo solo para el caso donde dialog no está instalado - Mejorar el mensaje de operación cancelada para mayor claridad 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
258 lines
No EOL
6.2 KiB
Bash
Executable file
258 lines
No EOL
6.2 KiB
Bash
Executable file
#!/bin/bash
|
|
#
|
|
# Script: qr_secret.sh
|
|
# Description: Extrae una contraseña secreta de una imagen QR y la guarda encriptada con SOPS
|
|
# Modified: 2025/03/15 19:30:00
|
|
# [Author] Cortana Rosero One <cortana@rosero.one>
|
|
# [Generated] Created by Claude Code (claude-3-7-sonnet-20250219)
|
|
#
|
|
# Derechos de Autor (C) [2025] [Mauro Rosero P. <mauro@roser.one>]
|
|
#
|
|
# Este programa es software libre: usted puede redistribuirlo y/o modificarlo
|
|
# bajo los términos de la Licencia Pública Affero General de GNU tal como
|
|
# lo publica la Free Software Foundation, ya sea la versión 3 de la licencia,
|
|
# o (a su elección) cualquier versión posterior.
|
|
#
|
|
# Este programa se distribuye con la esperanza de que sea útil,
|
|
# pero SIN NINGUNA GARANTÍA; sin siquiera la garantía implícita de
|
|
# COMERCIABILIDAD o IDONEIDAD PARA UN PROPÓSITO PARTICULAR. Consulte la
|
|
# Licencia Pública Affero General de GNU para obtener más detalles.
|
|
#
|
|
# Debería haber recibido una copia de la Licencia Pública Affero General
|
|
# junto con este programa. Si no la recibió, consulte <https://www.gnu.org/licenses/>.
|
|
|
|
# Configuración inicial
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
# Leer DEVSPATH desde el archivo de configuración o usar "devs" por defecto
|
|
if [ -f "$SCRIPT_DIR/config/devspath.dat" ]; then
|
|
DEVSPATH=$(cat "$SCRIPT_DIR/config/devspath.dat")
|
|
else
|
|
DEVSPATH="devs"
|
|
fi
|
|
|
|
BIN_HOME="$HOME/$DEVSPATH"
|
|
BIN_BASE="bin"
|
|
BIN_LIBS="lib"
|
|
BIN_MESG="msg"
|
|
|
|
# CHECK SHELL LANGUAGE
|
|
BIN_LANG=${LANG:0:2}
|
|
|
|
# Importar bibliotecas necesarias
|
|
source "${BIN_HOME}/${BIN_BASE}/${BIN_LIBS}/base.lib"
|
|
source "${BIN_HOME}/${BIN_BASE}/${BIN_LIBS}/console.lib"
|
|
|
|
# Cargar mensajes en el idioma del sistema o español por defecto
|
|
load_messages "${BIN_HOME}/${BIN_BASE}" "${BIN_MESG}" "${BIN_LANG}" "head"
|
|
load_messages "${BIN_HOME}/${BIN_BASE}" "${BIN_MESG}" "${BIN_LANG}" "developers"
|
|
|
|
# Variables globales
|
|
title="${head_000} ${head_002}"
|
|
apps_title="${qrmsg_000}"
|
|
|
|
# Verificar dependencias
|
|
check_dependencies() {
|
|
# Verificar si dialog está instalado
|
|
if ! command -v dialog &> /dev/null; then
|
|
# Sin dialog, tenemos que usar echo
|
|
echo "Error: ${qrmsg_013}. ${cvmsg_014}"
|
|
exit 1
|
|
fi
|
|
|
|
# Verificar si zbar está instalado
|
|
if ! command -v zbarimg &> /dev/null; then
|
|
dialog_error_box "${head_error}" "${qrmsg_014}. ${cvmsg_014}"
|
|
clear
|
|
exit 1
|
|
fi
|
|
|
|
# Verificar si sops está instalado
|
|
if ! command -v sops &> /dev/null; then
|
|
dialog_error_box "${head_error}" "${cvmsg_013}. ${cvmsg_014}"
|
|
clear
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Validar formato del nombre
|
|
validate_name() {
|
|
local name="$1"
|
|
|
|
# Verificar si el nombre está vacío
|
|
if [ -z "$name" ]; then
|
|
return 1
|
|
fi
|
|
|
|
# Verificar si el nombre contiene espacios
|
|
if [[ "$name" =~ [[:space:]] ]]; then
|
|
return 2
|
|
fi
|
|
|
|
# Verificar si el nombre contiene caracteres no permitidos
|
|
if ! [[ "$name" =~ ^[a-zA-Z0-9._-]+$ ]]; then
|
|
return 3
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Solicitar nombre del archivo
|
|
get_output_name() {
|
|
local name=""
|
|
local valid=false
|
|
|
|
while [ "$valid" != "true" ]; do
|
|
# Solicitar nombre
|
|
dialog_input_box "${qrmsg_001}" "${qrmsg_002}" ""
|
|
|
|
if [ $codex -ne 0 ]; then
|
|
# Usuario canceló
|
|
return 1
|
|
fi
|
|
|
|
name="$value"
|
|
|
|
# Validar nombre
|
|
validate_name "$name"
|
|
local validation_result=$?
|
|
|
|
case $validation_result in
|
|
0)
|
|
valid="true"
|
|
;;
|
|
1)
|
|
dialog_error_box "${qrmsg_012}" "${qrmsg_004}"
|
|
;;
|
|
2)
|
|
dialog_error_box "${qrmsg_012}" "${qrmsg_005}"
|
|
;;
|
|
3)
|
|
dialog_error_box "${qrmsg_012}" "${qrmsg_006}"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
echo "$name"
|
|
return 0
|
|
}
|
|
|
|
# Seleccionar archivo QR
|
|
select_qr_file() {
|
|
# Usar dialog directamente para seleccionar un archivo
|
|
local home_dir="$HOME/"
|
|
|
|
exec 3>&1
|
|
local selected_file=$(dialog --backtitle "$title" --title "${qrmsg_003}" \
|
|
--stdout --fselect "$home_dir" 15 60)
|
|
local exit_code=$?
|
|
exec 3>&-
|
|
|
|
if [ $exit_code -ne 0 ] || [ ! -f "$selected_file" ]; then
|
|
# Usuario canceló o no seleccionó un archivo válido
|
|
return 1
|
|
fi
|
|
|
|
echo "$selected_file"
|
|
return 0
|
|
}
|
|
|
|
# Extraer secreto de imagen QR
|
|
extract_secret() {
|
|
local qr_file="$1"
|
|
|
|
# Usar zbarimg para extraer el texto del QR
|
|
local secret=$(zbarimg --quiet --raw "$qr_file")
|
|
local result=$?
|
|
|
|
if [ $result -ne 0 ] || [ -z "$secret" ]; then
|
|
return 1
|
|
fi
|
|
|
|
# Si el secreto comienza con "otpauth://", extraer solo el secreto
|
|
if [[ "$secret" == otpauth://* ]]; then
|
|
# Extraer el valor después de "secret="
|
|
secret=$(echo "$secret" | grep -oP 'secret=\K[A-Z0-9]+')
|
|
|
|
# Si no se pudo extraer el secreto, mostrar error
|
|
if [ -z "$secret" ]; then
|
|
return 2
|
|
fi
|
|
fi
|
|
|
|
echo "$secret"
|
|
return 0
|
|
}
|
|
|
|
# Guardar secreto encriptado con SOPS
|
|
save_encrypted_secret() {
|
|
local name="$1"
|
|
local secret="$2"
|
|
local output_file="${DEVELOPER_DIR}/${name}.totp.yaml"
|
|
|
|
# Crear archivo YAML temporal con el secreto
|
|
local temp_file=$(mktemp)
|
|
echo "secret: $secret" > "$temp_file"
|
|
|
|
# Encriptar el archivo con SOPS
|
|
sops --encrypt "$temp_file" > "$output_file"
|
|
local result=$?
|
|
|
|
# Eliminar archivo temporal
|
|
rm -f "$temp_file"
|
|
|
|
# Establecer permisos adecuados
|
|
if [ $result -eq 0 ]; then
|
|
chmod 600 "$output_file"
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Función principal
|
|
main() {
|
|
# Verificar dependencias
|
|
check_dependencies
|
|
|
|
# Solicitar nombre del archivo
|
|
local output_name=$(get_output_name)
|
|
if [ $? -ne 0 ]; then
|
|
clear
|
|
dialog_error_box "${head_info}" "${qrmsg_010}"
|
|
exit 0
|
|
fi
|
|
|
|
# Seleccionar archivo QR
|
|
local qr_file=$(select_qr_file)
|
|
if [ $? -ne 0 ]; then
|
|
clear
|
|
dialog_error_box "${head_info}" "${qrmsg_010}"
|
|
exit 0
|
|
fi
|
|
|
|
# Extraer secreto de la imagen QR
|
|
local secret=$(extract_secret "$qr_file")
|
|
local extract_status=$?
|
|
|
|
if [ $extract_status -ne 0 ]; then
|
|
dialog_error_box "${qrmsg_012}" "${qrmsg_007}"
|
|
clear
|
|
exit 1
|
|
fi
|
|
|
|
# Guardar secreto encriptado
|
|
save_encrypted_secret "$output_name" "$secret"
|
|
if [ $? -eq 0 ]; then
|
|
dialog_error_box "${qrmsg_011}" "${qrmsg_008} ${DEVELOPER_DIR}/${output_name}.totp.yaml"
|
|
else
|
|
dialog_error_box "${qrmsg_012}" "${qrmsg_009}"
|
|
clear
|
|
exit 1
|
|
fi
|
|
|
|
clear
|
|
}
|
|
|
|
# Ejecutar función principal
|
|
main |