viernes, 11 de enero de 2008

Claves memorizables en PHP (y razonablemente seguras)

Bueno, ya veo que hace más de dos meses que no asomo el pelo por aquí. El caso es que he estado ocupado y después de una temporada, por fin puedo volver a CakePHP un rato.

Estoy trabajando en la parte de gestión de usuarios de una aplicación y se me ocurrió que necesitaba un generador de contraseñas para automatizar la creación de las mismas al dar de alta manual o automáticamente a usuarios (no creo que esta aplicación lleve autorregistro).

Mis usuarios odian las contraseñas puramente aleatorias del tipo ajku87hsdf6, así que pensé en utilizar uno de esos generadores de contraseñas legibles o memorizables. No encontré ninguno que me gustase, así que acabé escribiéndolo y esta es la segunda versión (muy difícil no es).

Lo de las contraseñas memorizables es bastante sencillo. Se trata de series de letras construidas de tal modo que parecen palabras y son bastante fáciles de pronunciar y memorizar por humanos. Por ejemplo: hanicu, corchuela o gafimocho.

La base del generador es la construcción de sílabas válidas en español (en este caso), combinando una consonante (o grupo consonántico) con una vocal y opcionalmente con otra consonante válida para finalizar una sílaba.

He añadido un factor de fortaleza que afecta a todo el proceso de generación de la contraseña aumentando la probabilidad de que se generen sílabas con más letras. Esto se traduce en claves más largas, con más posibilidad de repetición de caracteres, etc.

Algunas mejoras posibles serían la posibilidad de convertir al azar algunas letras en mayúsculas o incorporar más caracteres (por ejemplo los acentuados).

El uso de la función es muy simple:

$nuevaClave = claveLegible ();


Lo anterior nos daría claves de fortaleza media

o indicando la fortaleza deseada:

// baja, pasar 'l' de 'low'

$nuevaClave = claveLegible('l');

//alta, pasar 'h', de 'high'

$nuevaClave = claveLegible('h');



<?php

/**
* Genera una clavve legible que se puede memorizar por humanos con mayor facilidad
* sin que por eso se pierda demasiada seguridad
* @param $fortaleza: 'l' (baja), 'm' (media), 'h' (alta). Por defecto es 'm'. Indica
* la solidez teórica de la contraseña generada (más larga y con palabras más difíciles
* de localizar en un diccionario0)
*
* @return string La clave generada
* @author Frankie
**/
function claveLegible($fortaleza = 'm') {
// Preparamos los parámetros de la generación a partir de la indicación de fortaleza
$fortaleza = strtolower($fortaleza);
if ($fortaleza == 'h') {
$factor = 0;
$numeroSilabas = 5;
} elseif ($fortaleza == 'l' ) {
$factor = 4;
$numeroSilabas = 3;
} else {
$factor = 2;
$numeroSilabas = 4;
}
// Fuentes de los caracteres, si quieres modificar la probabilidad de cada uno, añade los que desees
$consonantes = array('b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'ñ', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z', ' ');
$grupos = array('b', 'bl', 'br', 'c', 'ch', 'cl', 'cr', 'd', 'f', 'fl', 'fr', 'g', 'h', 'j', 'k', 'l', 'll', 'm', 'n', 'ñ', 'p', 'pr', 'pl', 'q', 'r', 's', 't', 'tr', 'v', 'w', 'x', 'y', 'z', ' ');
$vocales = array('a', 'e', 'i', 'o', 'u');
$diptongos = array('a', 'e', 'i', 'o', 'u', 'ai', 'au', 'ei', 'eu', 'ia', 'ie', 'io', 'oi', 'ou', 'ua', 'ue', 'uo');
$finales = array(' ', 'n', 'l', 's', 'r', 'd');
// Generación de la contraseña. Cada sílaba se construye con una consontante o grupo inicial, una vocal y una consonante final. Se introduce un factor de aleatoriedad regulado por la fortaleza para generar sílabas más o menos simples.
$clave = '';
for ($i=0; $i < $numeroSilabas; $i++) {
$consonante = rand(0,$factor) ? $consonantes[rand(0, count($consonantes)-1)] : $grupos[rand(0, count($grupos)-1)] ;
$vocal = rand(0, 2*$factor) ? $vocales[rand(0, count($vocales)-1)] : $diptongos[rand(0, count($diptongos)-1)];
$final = rand(0, 4*$factor) ? '' : $finales[rand(0, count($finales)-1)];
$clave .= trim($consonante . $vocal . $final);
}
return $clave;

}

// Test
//
// for ($i=0; $i < 20; $i++) {
// echo claveLegible('m') . chr(10);
// }

?>


Addenda: Uso en CakePHP

Yo he creado una carpeta Utilidades bajo Vendors y he puesto la función en un archivo clave_legible.php.

Cuando necesites usarla en Cake, no tienes más que cargarla con una llamada

vendor('utilidades/clave_legible')

8 comentarios:

Anónimo dijo...

Hola Fran, trate de probar tu codigo pero no logro imprimirlo, por favor agradecería tu ayuda.

Frankie dijo...

Prueba a bajarlo de aquí

clave_legible.php

thesundevil dijo...

Fran, el enlace no me funciona, al abrir me pide loguearme, cree la cuenta pero nada. Te agradeceria que lo envies a mi correo kramer1484@hotmail.com. Gracias

thesundevil dijo...

Muchas gracias Fran, recepcione el codigo, pero no logro visualizar al momento de lanzarlo en el navegador, que es lo que esta pasando????

Frankie dijo...

@thesundevil, ¿qué estás intentando hacer exactamente? el código tal cual está no hace nada, puedes quitar las marcar de comentarios de la parte final que pone "Test" para ver cómo funciona la función, valga la redundancia.

thesundevil dijo...

Fran, si funcionó Gracias por tu ayuda. Te comento lo que quiero realizar, quiero simular la generación de registros aleatorios, me explico, por ejemplo tengo la tabla cliente con sus respectivos campos(id_cliente;nombre;sexo; y edad) y quiero q los registros se generen automaticamente llenando los campos, ya que tu codigo es de utilidad para generar los nombres aleatorios con sentido. Gracias espero tus comentarios.

Frankie dijo...

No se me había ocurrido ese uso, pero es cierto que está bien para generar "palabras". Me alegro que sea útil.

thesundevil dijo...

Fran te envio un prototipo de mas o menos como quiero que sea.A ver si me ayudas, ya que quiero realizar un proyecto de simulación en la universidad. Muchas gracias.