En este artículo vamos a ver cómo crear un generador de contraseñas seguras mediante JavaScript. De esta manera podemos implementarlo fácilmente en nuestra web o blog. El programa está pensado para ser modificado fácilmente. De hecho, tengo previstas algunas modificaciones para la versión 2.0, que incluirán:
- Poder modificar la longitud de la contraseña, con un mínimo de 9. Se introducirá al ejecutarlo, mediante el teclado.
- Poder modificar el número de cada tipo de caracter, con un mínimo de 1 para cada uno. También se introducirá mediante el teclado.
- Poder crear una nueva contraseña al pulsar un botón, en lugar de tener que refrescar la página.
Ahora que lo tenemos claro, ¡vamos al lío!
¿Por qué un generador de contraseñas seguras?
Mediante páginas como How secure is my password podemos comprobar lo rápido que es conseguir una contraseña mediante ataques de fuerza bruta.
Con los programas adecuados y el tiempo suficiente se pueden romper contraseñas de menos de 9 caracteres en tiempos que van desde menos de 1 segundo hasta 3 días como máximo.
Gracias a este sencillo programa podemos crear nuestras propias contraseñas de manera que cumpla con nuestros criterios. Como añadido sabemos que no se está guardando en ningún sitio extraño 😉
¿Por qué un generador de contraseñas seguras con JavaScript?
JavaScript es el lenguaje de programación que se usa para el lado cliente de las páginas web. Es decir, se ejecuta en el navegador de tu ordenador. Al entrar en una página web, se descarga en forma de texto plano y se puede ver de manera sencilla mirando el código fuente de la página. Esto hace que cualquiera que acceda a la web pueda ver qué es lo que hace el programa de manera transparente.
Esto no ocurre con lenguajes de servidor como PHP, que se ejecutan en el lado del servidor y devuelven código HTML puro y duro, por lo que no podemos ver qué es lo que hace el programa propiamente dicho, a no ser que seamos el administrador de dicha página.
Ejemplo de funcionamiento del generador de contraseñas seguras con JavaScript
Al abrir el fichero en un navegador como Mozilla Firefox, Internet Explorer, Opera, Google Chrome o cualquier otro que admita JavaScript, verás el siguiente resultado:
La idea era poder ver el resultado directo desde aquí, pero uso el CDN de CloudFlare y a pesar de sus muchas ventajas, me inyecta código JavaScript en la web y me modifica mi programa, por lo que no es viable. Aún así, recomiendo el uso de algún CDN para mejorar la velocidad y seguridad de vuestra web 😉 La explicación detallada es tema para otro artículo.
De momento puedes ver mi artículo sobre cómo configurar un subdominio en un CDN como ClodFlare
Descargar el código del generador de contraseñas seguras con JavaScript
Desde el siguiente enlace puedes descargar el código correspondiente.
creador-de-password-seguros-con-javascript.zip
Pero te recomiendo crear un fork del proyecto desde mi repositorio de Github. Si todavía no usas Github, te recomiendo que hagas este curso que comento en otro de mis artículos, es gratuito y te va a facilitar la vida mucho como programador.
Vamos a ver el código puro y duro
Aquí tienes el código. Ahora lo veremos poco a poco y explicando cada parte.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
<!DOCTYPE html> <html> <head> <title>Creación de passwords seguros con JavaScript - http://38bits.com</title> <meta charset="UTF-8"> <script type="text/javascript"> var tamanyo_password = 9; // definimos el tamaño que tendrá nuestro password var caracteres_conseguidos = 0; // contador de los caracteres que hemos conseguido var caracter_temporal = ''; var array_caracteres = new Array();// array para guardar los caracteres de forma temporal for(var i = 0; i < tamanyo_password; i++){ // inicializamos el array con el valor null array_caracteres[i] = null; } var password_definitivo = ''; var numero_minimo_letras_minusculas = 1; // en ésta y las siguientes variables definimos cuántos var numero_minimo_letras_mayusculas = 1; // caracteres de cada tipo queremos en cada var numero_minimo_numeros = 1; var numero_minimo_simbolos = 1; var letras_minusculas_conseguidas = 0; var letras_mayusculas_conseguidas = 0; var numeros_conseguidos = 0; var simbolos_conseguidos = 0; // función que genera un número aleatorio entre los límites superior e inferior pasados por parámetro function genera_aleatorio(i_numero_inferior, i_numero_superior) { var i_aleatorio = Math.floor((Math.random() * (i_numero_superior - i_numero_inferior + 1)) + i_numero_inferior); return i_aleatorio; } // función que genera un tipo de caracter en base al tipo que se le pasa por parámetro (mayúscula, minúscula, número, símbolo o aleatorio) function genera_caracter(tipo_de_caracter){ // hemos creado una lista de caracteres específica, que además no tiene algunos caracteres como la "i" mayúscula ni la "l" minúscula para evitar errores de transcripción var lista_de_caracteres = '$+=?@_23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz'; var caracter_generado = ''; var valor_inferior = 0; var valor_superior = 0; switch (tipo_de_caracter){ case 'minúscula': valor_inferior = 38; valor_superior = 61; break; case 'mayúscula': valor_inferior = 14; valor_superior = 37; break; case 'número': valor_inferior = 6; valor_superior = 13; break; case 'símbolo': valor_inferior = 0; valor_superior = 5; break; case 'aleatorio': valor_inferior = 0; valor_superior = 61; } // fin del switch caracter_generado = lista_de_caracteres.charAt(genera_aleatorio(valor_inferior, valor_superior)); return caracter_generado; } // fin de la función genera_caracter() // función que guarda en una posición vacía aleatoria el caracter pasado por parámetro function guarda_caracter_en_posicion_aleatoria(caracter_pasado_por_parametro){ var guardado_en_posicion_vacia = false; var posicion_en_array = 0; while(guardado_en_posicion_vacia != true){ posicion_en_array = genera_aleatorio(0, tamanyo_password-1); // generamos un aleatorio en el rango del tamaño del password // el array ha sido inicializado con null en sus posiciones. Si es una posición vacía, guardamos el caracter if(array_caracteres[posicion_en_array] == null){ array_caracteres[posicion_en_array] = caracter_pasado_por_parametro; guardado_en_posicion_vacia = true; } } } // función que se inicia una vez que la página se ha cargado function generar_contrasenya(){ // generamos los distintos tipos de caracteres y los metemos en un password_temporal while (letras_minusculas_conseguidas < numero_minimo_letras_minusculas){ caracter_temporal = genera_caracter('minúscula'); guarda_caracter_en_posicion_aleatoria(caracter_temporal); letras_minusculas_conseguidas++; caracteres_conseguidos++; } while (letras_mayusculas_conseguidas < numero_minimo_letras_mayusculas){ caracter_temporal = genera_caracter('mayúscula'); guarda_caracter_en_posicion_aleatoria(caracter_temporal); letras_mayusculas_conseguidas++; caracteres_conseguidos++; } while (numeros_conseguidos < numero_minimo_numeros){ caracter_temporal = genera_caracter('número'); guarda_caracter_en_posicion_aleatoria(caracter_temporal); numeros_conseguidos++; caracteres_conseguidos++; } while (simbolos_conseguidos < numero_minimo_simbolos){ caracter_temporal = genera_caracter('símbolo'); guarda_caracter_en_posicion_aleatoria(caracter_temporal); simbolos_conseguidos++; caracteres_conseguidos++; } // si no hemos generado todos los caracteres que necesitamos, de forma aleatoria añadimos los que nos falten // hasta llegar al tamaño de password que nos interesa while (caracteres_conseguidos < tamanyo_password){ caracter_temporal = genera_caracter('aleatorio'); guarda_caracter_en_posicion_aleatoria(caracter_temporal); caracteres_conseguidos++; } // ahora pasamos el contenido del array a la variable password_definitivo for(var i=0; i < array_caracteres.length; i++){ password_definitivo = password_definitivo + array_caracteres[i]; } // indicamos los parámetros con los que hemos generado la contraseña document.write('Tamaño total de la contraseña: ' + tamanyo_password + '<br>'); document.write('Cantidad de minúsculas: ' + numero_minimo_letras_minusculas + '<br>'); document.write('Cantidad de mayúsculas: ' + numero_minimo_letras_mayusculas + '<br>'); document.write('Cantidad de números: ' + numero_minimo_numeros + '<br>'); document.write('Cantidad de símbolos: ' + numero_minimo_simbolos + '<br>'); document.write('El resto de caracteres hasta llegar al tamaño de la contraseña se completa con caracteres aleatorios.<br>'); // y ahora simplemente lo mostramos por pantalla document.write('Password generado: <strong>' + password_definitivo + '</strong><br>'); // e indicamos que al recargar la página se generará uno nuevo document.write('Pulse F5 para generar una nueva contraseña') } </script> </head> <body> <script type="text/javascript"> generar_contrasenya(); </script> </body> </html> |
Declaración de variables
En esta primera parte del script simplemente declaramos las variables que vamos a usar posteriormente. Es importante usar siempre la palabra reservada var
para limitar el alcance o scope de dicha variable, es decir, desde dónde es reconocida. En este programa sencillito y con mis nombres de variables tan descriptivos no tendríamos problemas si se nos olvidara, pero como siempre, hay que coger buenas costumbres.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
var tamanyo_password = 9; // definimos el tamaño que tendrá nuestro password var caracteres_conseguidos = 0; // contador de los caracteres que hemos conseguido var caracter_temporal = ''; var array_caracteres = new Array();// array para guardar los caracteres de forma temporal for(var i = 0; i < tamanyo_password; i++){ // inicializamos el array con el valor null array_caracteres[i] = null; } var password_definitivo = ''; var numero_minimo_letras_minusculas = 1; // en ésta y las siguientes variables definimos cuántos var numero_minimo_letras_mayusculas = 1; // caracteres de cada tipo queremos en cada var numero_minimo_numeros = 1; var numero_minimo_simbolos = 1; var letras_minusculas_conseguidas = 0; var letras_mayusculas_conseguidas = 0; var numeros_conseguidos = 0; var simbolos_conseguidos = 0; |
Los nombres de las variables son muy descriptivos. Podemos cambiar fácilmente los parámetros, para obtener una contraseña más larga o con mayor número de caracteres o símbolos, por ejemplo.
Función genera_aleatorio()
Ésta es una sencilla función que nos devuelve un número aleatorio (redondeando a entero) dentro de un rango que le indicamos al pasar el límite inferior y superior como parámetros.
1 2 3 4 5 |
// función que genera un número aleatorio entre los límites superior e inferior pasados por parámetro function genera_aleatorio(i_numero_inferior, i_numero_superior) { var i_aleatorio = Math.floor((Math.random() * (i_numero_superior - i_numero_inferior + 1)) + i_numero_inferior); return i_aleatorio; } |
Función genera_caracter()
Esta función nos devuelve un carácter en base al tipo que le pasamos como parámetro.
El tipo de carácter que nos devuelva será:
- Letra minúscula
- Letra mayúscula
- Número
- Símbolo
- Aleatorio (uno de los otros tipos)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
// función que genera un tipo de caracter en base al tipo que se le pasa por parámetro (mayúscula, minúscula, número, símbolo o aleatorio) function genera_caracter(tipo_de_caracter){ // hemos creado una lista de caracteres específica, que además no tiene algunos caracteres como la "i" mayúscula ni la "l" minúscula para evitar errores de transcripción var lista_de_caracteres = '$+=?@_23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz'; var caracter_generado = ''; var valor_inferior = 0; var valor_superior = 0; switch (tipo_de_caracter){ case 'minúscula': valor_inferior = 38; valor_superior = 61; break; case 'mayúscula': valor_inferior = 14; valor_superior = 37; break; case 'número': valor_inferior = 6; valor_superior = 13; break; case 'símbolo': valor_inferior = 0; valor_superior = 5; break; case 'aleatorio': valor_inferior = 0; valor_superior = 61; } // fin del switch caracter_generado = lista_de_caracteres.charAt(genera_aleatorio(valor_inferior, valor_superior)); return caracter_generado; } |
Es importante tener en cuenta que no todos los caracteres, números o símbolos se van a utilizar. Por claridad y seguridad se han omitido algunos como la «i
» mayúscula o la «l
» minúscula. El juego de caracteres concreto se ha definido en la propia función, en la variable lista_de_caracteres
.
1 |
var lista_de_caracteres = '$+=?@_23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz'; |
Flujo del programa
El programa arranca en el body
de la página, llamado a la función generar_contraseña()
.
1 2 3 4 5 |
<body> <script type="text/javascript"> generar_contrasenya(); </script> </body> |
Función generar_contraseña()
En esta función es donde se ejecuta la lógica del programa. Vamos a ir viendo sus partes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
// generamos los distintos tipos de caracteres y los metemos en un password_temporal while (letras_minusculas_conseguidas < numero_minimo_letras_minusculas){ caracter_temporal = genera_caracter('minúscula'); guarda_caracter_en_posicion_aleatoria(caracter_temporal); letras_minusculas_conseguidas++; caracteres_conseguidos++; } while (letras_mayusculas_conseguidas < numero_minimo_letras_mayusculas){ caracter_temporal = genera_caracter('mayúscula'); guarda_caracter_en_posicion_aleatoria(caracter_temporal); letras_mayusculas_conseguidas++; caracteres_conseguidos++; } while (numeros_conseguidos < numero_minimo_numeros){ caracter_temporal = genera_caracter('número'); guarda_caracter_en_posicion_aleatoria(caracter_temporal); numeros_conseguidos++; caracteres_conseguidos++; } while (simbolos_conseguidos < numero_minimo_simbolos){ caracter_temporal = genera_caracter('símbolo'); guarda_caracter_en_posicion_aleatoria(caracter_temporal); simbolos_conseguidos++; caracteres_conseguidos++; } // si no hemos generado todos los caracteres que necesitamos, de forma aleatoria añadimos los que nos falten // hasta llegar al tamaño de password que nos interesa while (caracteres_conseguidos < tamanyo_password){ caracter_temporal = genera_caracter('aleatorio'); guarda_caracter_en_posicion_aleatoria(caracter_temporal); caracteres_conseguidos++; } |
La lógica del programa está formada por 5 bucles de tipo while
que generan caracteres de cada tipo hasta llegar a la cantidad que hemos indicado previamente; en este caso 1.
Si tras crear cada tipo de caracter no hemos llegado al tamaño de las contraseñas, el último bucle genera caracteres aleatorios hasta completarla.
¿Dudas? ¿Preguntas? Y si te ha gustado, ¡comparte!
Si algo no te ha quedado claro puedes dejar un comentario. Y si te ha gustado, ya sabes, puedes compartirlo 🙂