php password hash
Generando una contraseƱa aleatoria en php (22)
Estoy tratando de generar una contraseña aleatoria en php.
Sin embargo, estoy obteniendo ''all''s'' y el tipo de devolución es de tipo array y me gustaría que sea una cadena. ¿Alguna idea sobre cómo corregir el código?
Gracias.
function randomPassword() {
$alphabet = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789";
for ($i = 0; $i < 8; $i++) {
$n = rand(0, count($alphabet)-1);
$pass[$i] = $alphabet[$n];
}
return $pass;
}
Advertencia de seguridad :
rand()
no es un generador de números pseudoaleatorios criptográficamente seguro. Busque en otra parte la generación de una cadena pseudoaleatoria criptográficamente segura en PHP .
Pruebe esto (use strlen
lugar de count
, porque count
con una cadena siempre es 1
):
function randomPassword() {
$alphabet = ''abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'';
$pass = array(); //remember to declare $pass as an array
$alphaLength = strlen($alphabet) - 1; //put the length -1 in cache
for ($i = 0; $i < 8; $i++) {
$n = rand(0, $alphaLength);
$pass[] = $alphabet[$n];
}
return implode($pass); //turn the array into a string
}
Demostración: http://codepad.org/UL8k4aYK
TL; DR:
- Usa RandomLib .
- Si no puede usar RandomLib, use
random_int()
y elrandom_str()
dadorandom_str()
. - Si no tiene
random_int()
, use random_compat .
Explicación:
Como está generando una contraseña , debe asegurarse de que la contraseña que genera sea impredecible, y la única manera de garantizar que esta propiedad esté presente en su implementación es usar un generador de números pseudoaleatorios criptográficamente seguro (CSPRNG).
El requisito de CSPRNG se puede relajar para el caso general de cadenas aleatorias, pero no cuando se trata de seguridad.
La respuesta simple, segura y correcta a la generación de contraseñas en PHP es usar RandomLib y no reinventar la rueda. Esta biblioteca ha sido auditada por expertos en seguridad de la industria, así como por mí mismo.
Para desarrolladores que prefieren inventar su propia solución, PHP 7.0.0 proporcionará random_int()
para este propósito. Si todavía está en PHP 5.x, escribimos un random_compat para que pueda usar la nueva API antes de que PHP 7 sea lanzado. Usar nuestro polyfill random_int()
es probablemente más seguro que escribir su propia implementación.
Con un generador entero aleatorio seguro a la mano, generar una cadena aleatoria segura es más fácil que circular:
<?php
/**
* Generate a random string, using a cryptographically secure
* pseudorandom number generator (random_int)
*
* For PHP 7, random_int is a PHP core function
* For PHP 5.x, depends on https://github.com/paragonie/random_compat
*
* @param int $length How many characters do we want?
* @param string $keyspace A string of all possible characters
* to select from
* @return string
*/
function random_str(
$length,
$keyspace = ''0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ''
) {
$str = '''';
$max = mb_strlen($keyspace, ''8bit'') - 1;
if ($max < 1) {
throw new Exception(''$keyspace must be at least two characters long'');
}
for ($i = 0; $i < $length; ++$i) {
$str .= $keyspace[random_int(0, $max)];
}
return $str;
}
- Crea un archivo con este código.
Llámalo como en los comentarios.
<?php /** * @usage : * include_once($path . ''/Password.php''); * $Password = new Password; * $pwd = $Password->createPassword(10); * return $pwd; * */ class Password { public function createPassword($length = 15) { $response = []; $response[''pwd''] = $this->generate($length); $response[''hashPwd''] = $this->hashPwd( $response[''pwd''] ); return $response; } private function generate($length = 15) { $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*(){}/?,><"; return substr(str_shuffle($chars),0,$length); } private function hashPwd($pwd) { return hash(''sha256'', $pwd); } } ?>
Acabo de usar str_random(8)
para genarear una cadena aleatoria para confirmar el código.
Código minúsculo con 2 líneas.
demo: http://codepad.org/5rHMHwnH
function rand_string( $length ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return substr(str_shuffle($chars),0,$length);
}
echo rand_string(8);
con rand_string puedes definir cuánto carácter crearás.
Creé un script de contraseñas más completo y seguro. Esto creará una combinación de dos mayúsculas, dos minúsculas, dos números y dos caracteres especiales. 8 caracteres en total
$char = [range(''A'',''Z''),range(''a'',''z''),range(0,9),[''*'',''%'',''$'',''#'',''@'',''!'',''+'',''?'',''.'']];
$pw = '''';
for($a = 0; $a < count($char); $a++)
{
$randomkeys = array_rand($char[$a], 2);
$pw .= $char[$a][$randomkeys[0]].$char[$a][$randomkeys[1]];
}
$userPassword = str_shuffle($pw);
Desea strlen($alphabet)
, no count
del alphabet
constante (equivalente a ''alphabet''
).
Sin embargo, rand
no es una función aleatoria adecuada para este propósito. Su salida puede predecirse fácilmente, ya que está sembrada implícitamente con la hora actual. Además, rand
no es criptográficamente seguro; por lo tanto, es relativamente fácil determinar su estado interno a partir de la salida.
En su lugar, lea desde /dev/urandom
para obtener datos criptográficos aleatorios.
En una línea:
substr(str_shuffle(''abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'') , 0 , 10 )
Esto es básicamente lo mismo que el substr(md5(uniqid()), 0, 8);
mucho más simple substr(md5(uniqid()), 0, 8);
Esto se basa en otra respuesta en esta página, https://.com/a/21498316/525649
Esta respuesta genera solo caracteres hexadecimales, 0-9,af
. Para algo que no se ve como hexadecimal, intente esto:
str_shuffle(
rtrim(
base64_encode(bin2hex(openssl_random_pseudo_bytes(5))),
''=''
).
strtoupper(bin2hex(openssl_random_pseudo_bytes(7))).
bin2hex(openssl_random_pseudo_bytes(13))
)
-
base64_encode
devuelve una amplia gama de caracteres alfanuméricos -
rtrim
quita el=
veces al final
Ejemplos:
-
32eFVfGDg891Be5e7293e54z1D23110M3ZU3FMjb30Z9a740Ej0jz4
-
b280R72b48eOm77a25YCj093DE5d9549Gc73Jg8TdD9Z0Nj4b98760
-
051b33654C0Eg201cfW0e6NA4b9614ze8D2FN49E12Y0zY557aUCb8
-
y67Q86ffd83G0z00M0Z152f7O2ADcY313gD7a774fc5FF069zdb5b7
Esto no es muy configurable para crear una interfaz para los usuarios, pero para algunos propósitos está bien. Aumente la cantidad de caracteres para tener en cuenta la falta de caracteres especiales.
He querido probar la implementación de mi propio generador de contraseñas "seguro" y "aleatorio".
Pensé que sería interesante y más flexible proporcionar un parámetro de length
y type
para la función.
Aquí hay una función que realiza algunas comprobaciones para asegurarse de que la length
no sea demasiado corta o larga (permitiendo también una longitud variable). También permite la capacidad de elegir su juego de caracteres de contraseña en el parámetro type
.
Devuelve null
si la length
o el type
no son válidos y utiliza la función mt_rand()
PHP, que es más "aleatoria" que rand()
.
<?php
/**
* Generates a random password with the given length and of the given type.
*
* @param int $length
* @param string $type
* @return string | null
*/
function random_password($length=8, $type=''alpha_numeric'') {
if ($length < 1 || $length > 1024) return null;
$lower = ''abcdefghijklmnopqrstuvwxy'';
$upper = strtoupper($lower);
$numbers = ''1234567890'';
$dash = ''-'';
$underscore = ''_'';
$symbols = ''`~!@#$%^&*()+=[]//{}|:";/'<>?,./'';
switch ($type) {
case ''lower'':
$chars = $lower;
break;
case ''upper'':
$chars = $upper;
break;
case ''numeric'':
$chars = $numbers;
break;
case ''alpha'':
$chars = $lower . $upper;
break;
case ''symbol'':
$chars = $symbols . $dash . $underscore;
break;
case ''alpha_numeric'':
$chars = $lower . $upper . $numbers;
break;
case ''alpha_numeric_dash'':
$chars = $lower . $upper . $numbers . $dash;
break;
case ''alpha_numeric_underscore'':
$chars = $lower . $upper . $numbers . $underscore;
break;
case ''alpha_numeric_dash_underscore'':
$chars = $lower . $upper . $numbers . $underscore . $dash;
break;
case ''all'':
$chars = $lower . $upper . $numbers . $underscore . $dash . $symbols;
break;
default:
return null;
}
$min = 0;
$max = strlen($chars) - 1;
$password = '''';
for ($i = 0; $i < $length; $i++) {
$random = mt_rand($min, $max);
$char = substr($chars, $random, 1);
$password .= $char;
}
return $password;
}
Otro (solo linux)
function randompassword()
{
$fp = fopen ("/dev/urandom", ''r'');
if (!$fp) { die ("Can''t access /dev/urandom to get random data. Aborting."); }
$random = fread ($fp, 1024); # 1024 bytes should be enough
fclose ($fp);
return trim (base64_encode ( md5 ($random, true)), "=");
}
Pruebe esto con mayúsculas, minúsculas, numéricos y personajes especiales
function generatePassword($_len) {
$_alphaSmall = ''abcdefghijklmnopqrstuvwxyz''; // small letters
$_alphaCaps = strtoupper($_alphaSmall); // CAPITAL LETTERS
$_numerics = ''1234567890''; // numerics
$_specialChars = ''`~!@#$%^&*()-_=+]}[{;:,<.>/?/'"/|''; // Special Characters
$_container = $_alphaSmall.$_alphaCaps.$_numerics.$_specialChars; // Contains all characters
$password = ''''; // will contain the desired pass
for($i = 0; $i < $_len; $i++) { // Loop till the length mentioned
$_rand = rand(0, strlen($_container) - 1); // Get Randomized Length
$password .= substr($_container, $_rand, 1); // returns part of the string [ high tensile strength ;) ]
}
return $password; // Returns the generated Pass
}
Digamos que necesitamos 10 Digit Pass
echo generatePassword(10);
Ejemplo de salida (s):
, IZCQ_IV / 7
@wlqsfhT (d
1! 8 + 1 / 4 @ uD
Quick One. Formato simple, limpio y consistente si eso es lo que quieres
$pw = chr(mt_rand(97,122)).mt_rand(0,9).chr(mt_rand(97,122)).mt_rand(10,99).chr(mt_rand(97,122)).mt_rand(100,999);
Sé que estás intentando generar tu contraseña de una manera específica, pero es posible que también quieras ver este método ...
$bytes = openssl_random_pseudo_bytes(2);
$pwd = bin2hex($bytes);
Se toma del sitio php.net y crea una cadena que es dos veces la longitud del número que pones en la función openssl_random_pseudo_bytes. Entonces, lo anterior crearía una contraseña de 4 caracteres de largo.
En breve...
$pwd = bin2hex(openssl_random_pseudo_bytes(4));
Crearía una contraseña de 8 caracteres de largo.
Sin embargo, tenga en cuenta que la contraseña solo contiene los números 0-9 y las letras mayúsculas af!
Si está en PHP7 puede usar la función random_int()
:
function generate_password($length = 20){
$chars = ''ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz''.
''0123456789`-=~!@#$%^&*()_+,./<>?;:[]{}/|'';
$str = '''';
$max = strlen($chars) - 1;
for ($i=0; $i < $length; $i++)
$str .= $chars[random_int(0, $max)];
return $str;
}
Respuesta anterior a continuación:
function generate_password($length = 20){
$chars = ''ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz''.
''0123456789`-=~!@#$%^&*()_+,./<>?;:[]{}/|'';
$str = '''';
$max = strlen($chars) - 1;
for ($i=0; $i < $length; $i++)
$str .= $chars[mt_rand(0, $max)];
return $str;
}
Siendo un poco más inteligente:
function strand($length){
if($length > 0)
return chr(rand(33, 126)) . strand($length - 1);
}
compruébalo here .
Su mejor apuesta es la RandomLib .
Ejemplo de uso:
$factory = new RandomLib/Factory;
$generator = $factory->getGenerator(new SecurityLib/Strength(SecurityLib/Strength::MEDIUM));
$passwordLength = 8; // Or more
$randomPassword = $generator->generateString($passwordLength);
Produce cadenas que son más fuertemente aleatorias que las funciones normales de aleatoriedad como shuffle()
y rand()
(que es lo que generalmente desea para información confidencial como contraseñas, sales y claves).
Use este código simple para generar la contraseña 12 de med-strong
$password_string = ''!@#$%*&abcdefghijklmnpqrstuwxyzABCDEFGHJKLMNPQRSTUWXYZ23456789'';
$password = substr(str_shuffle($password_string), 0, 12);
Voy a publicar una respuesta porque algunas de las respuestas existentes están cerca pero tienen una de:
- un espacio de caracteres más pequeño de lo que deseaba para que el forzamiento bruto sea más fácil o la contraseña deba ser más larga para la misma entropía
- un RNG que no se considera criptográficamente seguro
- un requisito para una biblioteca de terceros y pensé que podría ser interesante mostrar lo que podría tomar para hacerlo usted mismo
Esta respuesta count/strlen
problema del count/strlen
ya que la seguridad de la contraseña generada, al menos en mi humilde opinión, va más allá de cómo se está llegando allí. También asumiré PHP> 5.3.0.
Vamos a dividir el problema en las partes constitutivas que son:
- use alguna fuente segura de aleatoriedad para obtener datos aleatorios
- use esa información y represéntela como una cadena imprimible
Para la primera parte, PHP> 5.3.0 proporciona la función openssl_random_pseudo_bytes
. Tenga en cuenta que, si bien la mayoría de los sistemas utilizan un algoritmo criptográficamente fuerte, debe verificar para que usemos un contenedor:
/**
* @param int $length
*/
function strong_random_bytes($length)
{
$strong = false; // Flag for whether a strong algorithm was used
$bytes = openssl_random_pseudo_bytes($length, $strong);
if ( ! $strong)
{
// System did not use a cryptographically strong algorithm
throw new Exception(''Strong algorithm not available for PRNG.'');
}
return $bytes;
}
Para la segunda parte, usaremos base64_encode
ya que toma una cadena de bytes y producirá una serie de caracteres que tienen un alfabeto muy cercano al especificado en la pregunta original. Si no nos importa tener los caracteres +
, /
y =
en la cadena final y queremos un resultado de al menos $n
caracteres de longitud, podríamos simplemente usar:
base64_encode(strong_random_bytes(intval(ceil($n * 3 / 4))));
El factor 3/4
se debe al hecho de que la codificación base64 da como resultado una cadena que tiene una longitud al menos un tercio más grande que la cadena de bytes. El resultado será exacto para $n
siendo un múltiplo de 4 y hasta 3 caracteres más largos de lo contrario. Dado que los caracteres adicionales son predominantemente el carácter relleno =
, si por alguna razón tenemos una restricción para que la contraseña tenga una longitud exacta, entonces podemos truncarla a la longitud que queramos. Esto se debe especialmente a que, dado un $n
, todas las contraseñas terminarían con el mismo número de ellas, de modo que un atacante que tuviera acceso a una contraseña de resultado tendría hasta 2 caracteres menos para adivinar.
Para obtener crédito adicional, si queríamos cumplir con las especificaciones exactas como en la pregunta del OP, tendríamos que trabajar un poco más. Voy a renunciar al enfoque de conversión de base aquí e ir con uno rápido y sucio. Ambos necesitan generar más aleatoriedad de la que se utilizará en el resultado de todos modos debido al alfabeto de 62 entradas largas.
Para los caracteres adicionales en el resultado, simplemente podemos descartarlos de la cadena resultante. Si comenzamos con 8 bytes en nuestra cadena de bytes, entonces hasta aproximadamente el 25% de los caracteres de base64 serían estos caracteres "indeseables", de modo que el simple descarte de estos caracteres da como resultado una cadena no más corta que el OP deseado. Entonces simplemente podemos truncarlo para obtener la longitud exacta:
$dirty_pass = base64_encode(strong_random_bytes(8)));
$pass = substr(str_replace([''/'', ''+'', ''=''], ['''', '''', ''''], $dirty_pass, 0, 8);
Si genera contraseñas más largas, el carácter de relleno =
forma una proporción cada vez más pequeña del resultado intermedio para que pueda implementar un enfoque más sencillo, si es preocupante agotar el conjunto de entropía utilizado para el PRNG.
base_convert(uniqid(''pass'', true), 10, 36);
p.ej. e0m6ngefmj4
EDITAR
Como mencioné en los comentarios, la longitud significa que los ataques de fuerza bruta funcionarían mejor contra ella y luego los ataques de tiempo, por lo que no es realmente relevante preocuparse por "qué tan seguro era el generador aleatorio". La seguridad, específicamente para este caso de uso, necesita complementar la usabilidad, por lo que la solución anterior es realmente lo suficientemente buena para el problema requerido.
Sin embargo, en caso de que haya encontrado esta respuesta mientras buscaba un generador de cadenas aleatorias seguras (como supongo que algunas personas han basado en las respuestas), para algo como generar tokens, así es como se vería un generador de tales códigos:
function base64urlEncode($data) {
return rtrim(strtr(base64_encode($data), ''+/'', ''-_''), ''='');
}
function secureId($length = 32) {
if (function_exists(''openssl_random_pseudo_bytes'')) {
$bytes = openssl_random_pseudo_bytes($length);
return rtrim(strtr(base64_encode($bytes), ''+/'', ''0a''), ''='');
}
else { // fallback to system bytes
error_log("Missing support for openssl_random_pseudo_bytes");
$pr_bits = '''';
$fp = @fopen(''/dev/urandom'', ''rb'');
if ($fp !== false) {
$pr_bits .= @fread($fp, $length);
@fclose($fp);
}
if (strlen($pr_bits) < $length) {
error_log(''unable to read /dev/urandom'');
throw new /Exception(''unable to read /dev/urandom'');
}
return base64urlEncode($pr_bits);
}
}
<?php
// We can generate without large code..
$length = 8;
$chars = array_merge(range(0,9), range(''a'',''z''),range(''A'',''Z''),[''!'',''@'',''#'',''$'',''%'',''&'',''*'',''?'']);
//$chars = array_merge(range(0,1), range(''A'',''Z''));
shuffle($chars);
$code = implode(array_slice($chars, 0, $length));
$arr = array($code);
$password = implode("",$arr);
echo $password;