11

Generador de contraseñas con Interfaz Gráfica

Andrés Rodrigo
Aleiva
18698

Índice de contenido

  • Introducción
  • Conocimientos previos
  • Objetivos del proyecto
  • Archivos necesarios
  • Lógica del programa
  • Organizando el espacio de trabajo
  • Archivo: entity
  • Archivo: model & utility
  • Archivo: controller & utility
  • Archivo: view
  • Personalizar y agregar características al proyecto
  • Repositorio en Github
  • Documentación
  • Conclusiones

Introducción

Bienvenida y bienvenido a este tutorial en el que realizaremos un generador de contraseñas con una interfaz gráfica. En un inicio puede parecer mucha teoría, pero es esta misma la que permite trabajar con esta metodología de manera muy veloz y con efectividad (siempre y cuando se practique con estructuras similares).

No te deprimas sino entiendes toda la teoría, esta puede resultar confusa y pesada en un inicio. Sin embargo, si pones en práctica esta metodología y lees el código con paciencia, podrás trabajar ágilmente pudiendo implementar nuevas funcionalidades durante el desarrollo del mismo.

Al finalizar este tutorial tendrás un programa idéntico o hasta mejor al que se muestra en las siguientes capturas de pantalla y con la posibilidad de agregar nuevas características y modificar valores para personalizarlo:

MainMenu
ExampleMedium
ExampleCopy
ExampleLong

Espero que con estas capturas de pantalla te motives para terminar este proyecto 😄. Además, al final del tutorial hay un apartado con ideas para complementar y mejorar el proyecto (todas realizadas en el proyecto actual). Sin embargo, no tengas miedo de explorar con las ideas que te surjan y no olvides compartirlo 📣.

Conocimientos previos

Para el desarrollo del proyecto haremos uso del paradigma de la Programación Orientada a Objetos (POO) y el lenguaje de programación: Python.

  • Puedes acceder al curso de POO de Platzi o leer un resumen teórico para repasar los conocimientos.
  • Puedes acceder al curso de Python Básico o al de Python Orientado a Objetos. En este caso, con haber cursado cualquiera de los dos será más que suficiente.
  • Opcionalmente será bueno si tienes conocimientos de la librería Tkinter. Pero no te preocupes si no lo sabes, en este tutorial te daremos el código básico y comentado para que, de interesarte el tema, puedas explorar y experimentar por tu cuenta con los código escritos. Adicionalmente, se dejará la documentación respectiva para profundizar en esta librería.

Nota: El programa lo he desarrollado totalmente en inglés, pero la explicación en este tutorial está totalmente en español.

Objetivos del proyecto

Nuestro proyecto tiene como fin:

  • Tener un diagrama de la lógica de nuestro programa que nos permita desarrollarlo con una mayor velocidad.
  • Utilizar la Programación Orientada a Objetos para una mayor escalabilidad y facilidad a la hora de incluir nuevas funcionalidades.
  • Emplear dos pilares de la POO: Abstracción y Encapsulamiento.
  • Utilizar las librerías de string y random de Python para facilitar nuestro código.
  • Implementar una interfaz gráfica de usuario (GUI) con la librería de Tkinter y Ttk.

Archivos necesarios

Primero necesitaremos el archivo .ico para que sea el ícono de nuestro programa. En este caso utilizaremos el que puedes descargar desde este link haciendo click en el recuadro verde que dice ICO. El ícono será el siguiente:

iconoProyecto

Nuestra segunda descarga es opcional, dado que podremos seleccionar otra tipografía, sin embargo, dado que queremos visualizar una contraseña será bueno distringuir entre una i mayúscula (I) y una l minúscula (l).

Es por esta razón que para el desarrollo de nuestro proyecto utilizaremos Argentum Sans Regular, ya que se puede notar claramente esta diferencia tal y como se aprecia en la siguiente imagen:

ArgentumSansLyI

Font Argentum Sans Regular: Puedes acceder a esta tipografía desde aquí. Al entrar, te desplazarás hasta ver la primera opción que dice Argentum Sans Regular y harás click en TTF y (una vez terminada la descarga) darás doble click en el archivo para abrirlo. A continuación, seleccionarás Instalar en la ventana emergente que salga.

Instalación

Lógica del programa

Listo, es hora de comenzar con nuestro proyecto 🚀. Empezaremos por analizar como va a funcionar nuestro programa. Esta será una de las partes más largas, pero no te frustres. Si tienes dudas, estas quedarán claras al plasmarlo en el código.

  • Problema/Objetivo: Escribir el código de un programa que genere contraseñas de diferentes longitudes, nos permita agregar nuevas funcionalidades, personalizarlo con POO, emplear encapsulamiento y, por si fuera poco, realizar una Interfaz Gráfica.

Visto el problema de esta forma resulta agobiante y confuso, así que haremos lo que todo desarrollador de Software hace: dividir un problema grande en pequeños problemas.

Por lo tanto, podemos ver que podemos divir el problema en 2 apartados: generar la contraseña y realizar la interfaz gráfica. Asimismo, dentro de generar contraseña debemos considerar utilizar POO y hacerlo personalizable. Finalmente, dentro de POO tendremos que considerar: que sea Modular y que emplee encapsulamiento.

De esta forma, tenemos el siguiente diagrama:

diagramaProblema

Entonces, llegados a este punto tenemos que ver que archivos crear y como ordernarlos para nuestro proyecto. Para eso analizaremos:

  1. Un primer archivo debe ser el que tenga una Clase con encapsulamiento del cual obtengamos los datos de las librería string la cual contiene diferentes listas con los caracteres que utilizaremos.

  2. Para que sea personalizable, debemos tener otro archivo con las constantes que podamos modificar fácilmente sus valores sin romper el código.

  3. Para mejorar la modularidad, tendremos un tercer archivo (con otra clase) que se encargará de utilizar el primer archivo creado para generar una contraseña con un parámetro (longitud que debe tener) de forma aleatoria con la librería random.

  4. Siguiendo con la modularidad, tendremos un archivo que se encargue de comunicar a la Interfaz Gráfica con el tercer archivo creado. Este archivo se encargará de seleccionar la longitud que pasará como parámetro a este tercer archivo.

  5. Finalmente, nuestro quinto y último archivo será la interfaz gráfica para la cual utilizaremos la librería Tkinter y tkk. Además, este archivo recibirá toda la interacción del usuario y se comunicará con el cuarto archivo para que este le retorne la contraseña y pueda mostrarla al usuario.

No te preocupes si no entendiste del todo esta lógica. Visualiza el siguiente gráfico que lo plasma de una manera más visual:

LogicDiagram

Tal y como se aprecia en el gráfico, se puede ver de manera más clara que empleamos el clásico Modelo-Vista-Controlador o Model-View-Controller (MVC).

Para dejar claro la lógica del programa, explicaré cada uno de los archivos y su función:

ARCHIVOFUNCIÓN
VIEWContendrá la interfáz gráfica con la librería de Tkinter y Ttk. Envía la selección de que tan fuerte debe ser la contraseña del usuario al CONTROLLER para que este le retorne la contraseña con la longitud correspondiente.
UTILITYSolo contendrá las constantes que nos permitirán hacer personalizable nuestro programa. Por ejemplo: Que tan fuerte debe ser la contraseña y las longitudes establecias por nosotros.
CONTROLLERRecibe que tan fuerte debe ser la contraseña del usuario y gracias a UTILITY puede asignarle un valor de longitud. Se comunicará con MODEL para que este le genere la contraseña aleatoria con estos datos y pueda devolvérsela a VIEW.
MODELRecibe la longitud de la contraseña de parte de CONTROLLER y, con ayuda de la librería Random, selecciona aleatoriamente caracteres de una lista de las mismas. Esta lista se la pide a ENTITY para que así pueda devolverle la contraseña a CONTROLLER.
ENTITYTiene en su poder la lista de los caracteres protegidos (encapsulamiento) para que sean inalterables y nadie pueda ver qué caracteres se emplean. Esto se logra gracias a la librería String. ENTITY se encargará de darle la información de esta lista protegida a MODEL para que él genere la contraseña y pueda enviársela a CONTROLLER y este último se la retorne a VIEW.

Si vuelves a apreciar el gráfico notarás que el recorrido, al pedir una contraseña, será el siguiente:

Path
  • Color azul: Es el camino “de ida” que se realiza.
  • Color amarillo: Es el recorrido “de regreso” que se realiza.

Nota: La librería Tkinter y Ttk no aparece con ningún color de flecha porque es lo primero que se visualiza de manera constante.

Organizando el espacio de trabajo

Ya con el diagrama en mente procederemos a crear una carpeta para almacenar los archivos de nuestro proyecto. Dentro de esta crearemos los 5 archivos mencionado anteriormente: entity.py, model.py, controller.py, utility.py y view.py. Finalmente, crearemos la carpeta “images” donde guardaremos el ícono que descargamos al inicio del proyecto (En este caso renombramos el nombre del archivo a “lock” para que sea fácil de acceder a él en el futuro).

Files

Archivo: entity

Aplicando la abstracción, notaremos que la clase Password contendrá como atributos 3 listas de los caracteres válidos que usará nuestro generador de contraseña.

Para tener estas listas, importaremos de la librería string:

  • ascii_letters: Nos dará una lista con las letras en minúsculas y mayúsculas.
  • digits: Nos dará una lista con los números.
  • punctuation: Nos dará una lista con símbolos de puntuación (Ej. !"#$%&’()*+,-./:;<=>[email protected][]^_`{|}~.).

Sin embargo, tenemos que recordar que vamos a aplicar encapsulamiento lo cual hace que nuestros atributos sean inviolables e inalterables. Para esto utilizaremos el doble guión bajo (self.__nombreDelAtributo) para encapsularlo.

entity

Tal y como se observa, en el código hemos incluido los métodos para acceder a estos datos encapsulados. Sólo hemos puesto los métodos para acceder a ellos porque no queremos que alguien los modifique. Esto equivale al método getter.

Archivo: model & utility

Ahora, antes de empezar con model, procederemos a llenar el archivo utility con las constantes que empleará model.

Hasta este punto sabemos que model va a seleccionar aleatoriamente entre las tres listas (letras, números y signos de puntuación). Pero, no puede ser 1/3 de probabilidad para cada uno, ya que existe riesgo de que se genere una contraseña con muchos números o signos de puntuación.

<h3>Solución al problema del abuso de caracteres</h3>

Para solucionar este problema basta con agregar una probabilidad de que se consiga una de las tres listas. Entonces, si analizamos bien, la solución será generar un número aleatorio entre 1-100 y asignarle un valor tope a cada una de las constantes.

  • El primer valor se podrá elegir libremente entre 1-100 y expresará (explícitamente) la probabilidad de que se consiga este valor.

  • Para asignar la probabilidad de la segunda constante deberemos sumarle al primer valor la probabilidad de que consigamos este segundo valor (Sí, puede sonar confuso pero cuando veas la imagen inferior lo entederás claramente).

  • El último y tercer valor siempre será 100 ya que se ajustará automáticamente a su probabilidad a causa de la segunda constante.

Rates

Entonces, ¿Cómo se eligieron estos valores? Fácil, me encargué de tomar 100 muestras de contraseñas aleatorias generadas por otro generador de contraseñas famoso: LastPass. Después de tomar las 100 muestras y clasificar cuantos números y signos de puntuación habían en una extensión promedio de 11 caracteres (y aplicar un poco de estadística) hallé la probabilidad de que aparezca cada tipo de caracter (letras 69%, números 10% y puntuacioón 21%).

<h3>Model</h3>

Ahora, con las constantes creadas en utility.py podemos empezar a escribir el código de model.py.

Primero, importaremos el archivo con las constantes y la librería random con randint y choice.

  • randint: Nos permitirá obtener un número entero entre el rango que le especifiquemos.

  • choice: Nos permitirá obtener un elemento aleatorio de una secuencia (en este caso: las listas de caracteres).

Luego, consideraremos que para acceder (como indica nuestro gráfico/diagrama) a los atributos de entity deberemos crear un objeto entity. Por lo tanto, el constructor de model se encargará de crear un objeto de esta clase.

model

Como se ve en la imagen, se añadió un atributo encapsulado vacío donde posteriormente se guardará la contraseña generada.

El primer método lo llamamos generate (generar) y con un parámetro length (longitud) nos permitirá generar una contraseña de esa longitud gracias al ciclo for.

En cada iteración se generará un número entre 1 y 100 con randint que después determinará que tipo de caracter se utilizará (letras, puntuacion o digitos). Posteriormente, se empleará choice para elegir un elemento aleatorio de la lista.

Esto lo haremos accediendo al obj de la clase Password que nos retorna la lista de esos caracteres.

Finalmente, nuestro método get_password convertirá la lista self.__password (creada en la línea 11) en una cadena de string que contendrá nuestra contraseña con la longitud deseada.

Archivo: controller & utility

Siguiendo la misma lógica que la que hicimos con model y entity, en controller tendremos que crear en el constructror un objeto de la clase model como atributo (para acceder a model).

En cuanto a los métodos, emplearemos 4 niveles de fortaleza de nuestra contraseña. Estos niveles los clasificaremos como constantes en utility con números enteros simples. Además, según el nivel de fortaleza de nuestra contraseña pasaremos como parámetro la longitud que esta tendrá al obj de la clase Model.

Por lo tanto, tendremos que crear otras cuatro constantes que contengan el valor de la longitud que se tendrá. De este modo, el archivo utility quedará de la siguiente forma:

utilityfinal
ConstanteNúmero de caracteres
LENGTH_S6
LENGTH_M8
LENGTH_L12
LENGTH_XL16

En cuanto al archivo controller:

  • Implementaremos dentro del método: process_password el parámetro de strengh que nos otorgará el view.
  • Agregaremos if-elif-else para comparar este valor con las constantes creadas y ejecutará la función de generar la contraseña generate de nuestro objeto de la clase PasswordModel.
  • Al final, este método retornará (al archivo view) la contraseña con el método get_password del objeto de la clase PasswordModel.
Model

Archivo: view

El archivo view es donde vamos a empezar realizar la interfaz gráfica de nuestro programa. Esta interfaz debe permitir al usuario seleccionar el nivel de fortaleza de la contraseña.

Sin embargo, preguntarle directamente al usuario puede ocasionar de que él nunca genere una contraseña que diga “easy” o “fácil”. Por lo que, para términos prácticos utilizaremos el término de longitud: corta, mediana, larga y extra larga (short,medium, large y extra large).

La interfaz también debe tener botones que posibiliten al usuario:

  • Copiar la contraseña a su portapapeles (Clipboard) para pegarla posteriormente.
  • Generar una nueva contraseña.

Empezaremos importando todas la librerrías que ocuparemos: Ttk y Tkinter. Adicionalmente, importaremos el archivo controller.py que se encargará de solicitar y retornarnos la contraseña con los datos que le pasemos.

view

A continuación, visualizaremos la siguiente imagen que detalla el código a escribir con la explicación de lo que hace cada una de las líneas.

full

Explicar cada una los widgets, sus parámetros, funcionalidades y demás hubiera sido exhaustivo y rellenado de teoría no tan provechosa. Ya que esta librería se aprende con la práctica y no con la explicación. Por ese mismo motivo, al final de tutorial he dejado los links a la documentación utilizada para el desarrollo de este proyecto. Así como el link al repositorio en GitHub para que puedas descargarlo y empeazr a experimentar con él y hacer variantes del mismo con tus propias ideas.

El código (sin tanto comentario que lo explique y como se encuentra en GitHub) queda de la siguiente forma:

view

Personalizar y agregar características al proyecto

  • Lo primero que puedes personalizar es la cantidad de niveles de fortaleza quieres que tenga. Tendrás que agregar simplemente constantes de fortaleza y de longitud con los valores que tu quieras.
  • Puedes reemplazar los radio buttons por una barra numérica (sliders) o una entrada de texto donde se indique una longitud específica.
  • Cambiar la interfaz gráfica totalmente con otras librerías o tecnologías como QT Designer, wxGlade, etc.
  • Hacer que la contraseña aparezca en una ventana emergente y puedas copiarla en un lapso de “t” segundos antes de que se cierre automáticamente y tengas que generar otra (prueba con .after() y destroy()).
  • Hacer que las contraseñas generadas se guarden en un archivo de texto.
  • Crear una base de datos o archivo que te permita guardar el nombre de una página con la contraseña generada.
  • Convertir el programa en un archivo ejecutable con Pyinstaller.
  • Implemetar todas las características que tengas en mente. Por más “tontas” o “insignificantes” que sean te ayudarán a entender como funciona esta metodología y ganar soltura con la misma.

Acceder al repositorio en Github

Puedes acceder al repositorio del proyecto en Github desde aquí para descargar todo el proyecto y visualizarlo/modificarlo más rápidamente.

Documentación

A continuación, dejo links para acceder a la documentación de las librería empleadas. Los links están en inglés, pero, al ser la página oficial de Python, permite cambiar el idioma en una pestaña ubicada en la parte superior izquierda.

Librerías básicas:

Librerías avanzadas:

Complementario:

Conclusiones

¡Listo! Eso es todo por este tutorial, espero que hayas podido comprender las bases del mismo y que puedas practicarlo con otros ejemplos más “sencillos” o “cortos”.

Para ser honesto, todo esto puede parecer que tomó mucho tiempo de desarrollar, pero no tomó más de 40 minutos. Donde la gran parte del tiempo me tomó utilizar Tkinter y ttk (ya que no recordaba en su totalidad la sintaxis y había que alinear los elementos manualmente)

Además, gracias a la modularidad del mismo, durante el desarrollo se me fueron ocurriendo varias ideas las cuales pude implementar sin problemas en cuestión de segundos.

Por ejemplo, cuando ya tenía la interfaz gráfica terminada se me ocurrió añadir una opción de una contraseña más corta (de 6 caracteres) y solo tuve que añadir dos constantes, aumentar un elif y agregar un radio button. Todo eso no me tomó más de: 25 segundos y ya tenía esta nueva característica funcionando perfectamente sin corromper el código.

¡No tengas miedo a experimentar con tus ideas! Recuerda, la práctica hace al maestro.

Muchas gracias si llegaste hasta aquí y felicidades por comprender las bases de este proyecto 👏🎉.


Volver al índice

Escribe tu comentario
+ 2
2
1342Puntos

Encantado con tu proyecto!
Solo que tengo un problema, no puedo visualizar la interfaz gráfica,
espero que me puedas ayudar, gracias!!

1
4Puntos

Igual tengo problemas con la interfaz y el código en GitHub se cayó