Mejor algoritmo para encriptar passwords

17/06/2007 - 02:07 por DarthSidious | Informe spam
buenos dias, estoy necesitando un buen algoritmo para encriptar passwords de
usuarios, y obtener un hash. Queria utilizar un MD5 con algun "salt", pero me
pregunto si existe algo mejor que eso, mas alla de que para un usuario normal
eso es mas que suficiente, pero, hay algo mejor que el md5? he leido sobre
sha1, pero tengo mis dudas.

desde ya muchas gracias!!

pd. no es necesario que vengan incorporadas en el visual studio, es una
pregunta "informativa".

Preguntas similare

Leer las respuestas

#1 RFOG
17/06/2007 - 11:03 | Informe spam
En Sun, 17 Jun 2007 02:07:01 +0200, DarthSidious
escribió:

buenos dias, estoy necesitando un buen algoritmo para encriptar
passwords de
usuarios, y obtener un hash. Queria utilizar un MD5 con algun "salt",
pero me
pregunto si existe algo mejor que eso, mas alla de que para un usuario
normal
eso es mas que suficiente, pero, hay algo mejor que el md5? he leido
sobre
sha1, pero tengo mis dudas.

desde ya muchas gracias!!

pd. no es necesario que vengan incorporadas en el visual studio, es una
pregunta "informativa".



Mejor que eso a fecha de hoy: no guardarlas en ningún lado.

Un HASH que se sepa es irreversible, es decir, teniendo la cadena a
"hashear", es imposible volver del HASH a la cadena. El riesgo que corres
es que dos passwords pudieran generar el mismo HASH... cosa harto difícil
pero remotamente posible.



Visita mi blog principal: http://rfog.blogsome.com
Y este sobre programación: http://geeks.ms/blogs/rfog
Libros, ciencia ficción y programación
Hablar de la democracia y callar al pueblo es una farsa. Hablar de
humanismo y negar a los hombres es una mentira.
Respuesta Responder a este mensaje
#2 Diego Jancic
17/06/2007 - 21:58 | Informe spam
Hola,
Ademas de eso hay algunos algoritmos que encriptan un password de
formas diferentes cada vez que se hace, y todo eso lo hace de forma
irreversible...
Lo que tienen de bueno es que si alguien consigue el password
encriptado con un MD5 o similar, lo pone en google y puede ser que
aparezca... Hay paginas en internet que manejan una base de datos de
password comunes hasheados (ej: http://gdataonline.com/seekhash.php),
y si vos buscas una password simple (ej:
25f9e794323b453885f5181f1b624d0b) te lo dan al toque...

Saludos,
Diego
Respuesta Responder a este mensaje
#3 RFOG
18/06/2007 - 10:30 | Informe spam
En Sun, 17 Jun 2007 21:58:31 +0200, Diego Jancic
escribió:

Hola,
Ademas de eso hay algunos algoritmos que encriptan un password de
formas diferentes cada vez que se hace, y todo eso lo hace de forma
irreversible...




Ya, pero entonces no puedes comprobar si la pass la han introducido bien o
no. Si cada vez que la encriptas te da un valor diferente y éste es
irreversible...

Lo que tienen de bueno es que si alguien consigue el password
encriptado con un MD5 o similar, lo pone en google y puede ser que
aparezca... Hay paginas en internet que manejan una base de datos de
password comunes hasheados (ej: http://gdataonline.com/seekhash.php),
y si vos buscas una password simple (ej:
25f9e794323b453885f5181f1b624d0b) te lo dan al toque...

Saludos,
Diego




LMQLP (La Madre Que Los Parió).

Siempre queda el código contra código. Lo que no recuerdo (ni encuentro)
es el algoritmo. Le pasas una cadena basura. El código te devuelve otra
cadena basura, que pasada a un método junto a la clave de acceso buena te
dice si es correcto o no... El punto crítico está en que es necesario
guardar la clave que convierte la basura que le pasas en la basura que
devuelve, y luego el bloque de código que hace la comparación con la clave
buena pasada... Lo que al final es lo mismo que clave pública/privada, ya
que una de ellas la tienes que guardar localmente y es el punto débil.

El algoritmo de arriba iría bien si el envío y recepción de la basura así
como la decodificación se hiciera en un servidor web aislado... pero
menuda trabajina para que luego aprovechen cualquer agujero de seguridad,
y peten el servidor y se lleven todos los códigos...
Visita mi blog principal: http://rfog.blogsome.com
Y este sobre programación: http://geeks.ms/blogs/rfog
Libros, ciencia ficción y programación
Hablar de la democracia y callar al pueblo es una farsa. Hablar de
humanismo y negar a los hombres es una mentira.
Respuesta Responder a este mensaje
#4 Diego Jancic
18/06/2007 - 13:53 | Informe spam
Jejej... obviamente si se puede, el tema es que no podes encriptarla y
comparar directo contra la base de datos... Al algoritmo le tenes que
pasar el password mas la cadena encriptada y te dice si es correcto...
Si queres revisarla podes mirar abajo el codigo, de todas formas vi
mas de una implementacion similar y (aunque no se mucho de
criptografia) parece bastante buena..

Saludos,
Diego

using System;
using System.Text;
using System.Security.Cryptography;

namespace GDA.Services.Security.Utilities
{
/// <summary>
/// This class generates and compares hashes using MD5, SHA1, SHA256,
SHA384,
/// and SHA512 hashing algorithms. Before computing a hash, it
appends a
/// randomly generated salt to the plain text, and stores this salt
appended
/// to the result. To verify another plain text value against the
given hash,
/// this class will retrieve the salt value from the hash string and
use it
/// when computing a new hash of the plain text. Appending a salt
value to
/// the hash may not be the most efficient approach, so when using
hashes in
/// a real-life application, you may choose to store them separately.
You may
/// also opt to keep results as byte arrays instead of converting
them into
/// base64-encoded strings.
/// </summary>
public class PasswordHash
{
private static string algorithm = "SHA512";

/// <summary>
/// Generates a hash for the given plain text value and returns a
/// base64-encoded result. Before the hash is computed, a random
salt
/// is generated and appended to the plain text. This salt is stored
at
/// the end of the hash value, so it can be used later for hash
/// verification.
/// </summary>
/// <param name="plainText">
/// Plaintext value to be hashed. The function does not check
whether
/// this parameter is null.
/// </param>
/// <returns>
/// Hash value formatted as a base64-encoded string.
/// </returns>
public static string ComputeHash(string plainText)
{
return ComputeHash(plainText, null);
}

/// <summary>
/// Generates a hash for the given plain text value and returns a
/// base64-encoded result. Before the hash is computed, a random
salt
/// is generated and appended to the plain text. This salt is stored
at
/// the end of the hash value, so it can be used later for hash
/// verification.
/// </summary>
/// <param name="plainText">
/// Plaintext value to be hashed. The function does not check
whether
/// this parameter is null.
/// </param>
/// <returns>
/// Hash value formatted as a base64-encoded string.
/// </returns>
private static string ComputeHash(string plainText, byte[]
saltBytes)
{
// Name of the hash algorithm. Allowed values are: "MD5", "SHA1",
// "SHA256", "SHA384", and "SHA512" (if any other value is
specified
// MD5 hashing algorithm will be used). This value is case-
insensitive.

if (saltBytes == null)
{
// Define min and max salt sizes.
int minSaltSize = 4;
int maxSaltSize = 8;

// Generate a random number for the size of the salt.
Random random = new Random();
int saltSize = random.Next(minSaltSize, maxSaltSize);

// Allocate a byte array, which will hold the salt.
saltBytes = new byte[saltSize];

// Initialize a random number generator.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

// Fill the salt with cryptographically strong byte values.
rng.GetNonZeroBytes(saltBytes);
}

// Convert plain text into a byte array.
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

// Allocate array, which will hold plain text and salt.
byte[] plainTextWithSaltBytes new byte[plainTextBytes.Length + saltBytes.Length];

// Copy plain text bytes into resulting array.
for (int i = 0; i < plainTextBytes.Length; i++)
plainTextWithSaltBytes[i] = plainTextBytes[i];

// Append salt bytes to the resulting array.
for (int i = 0; i < saltBytes.Length; i++)
plainTextWithSaltBytes[plainTextBytes.Length + i] = saltBytes[i];

// Because we support multiple hashing algorithms, we must define
// hash object as a common (abstract) base class. We will specify
the
// actual hashing algorithm class later during object creation.
HashAlgorithm hash;

// Make sure hashing algorithm name is specified.
if (algorithm == null)
algorithm = "";

// Initialize appropriate hashing algorithm class.
switch (algorithm.ToUpper())
{
case "SHA1":
hash = new SHA1Managed();
break;

case "SHA256":
hash = new SHA256Managed();
break;

case "SHA384":
hash = new SHA384Managed();
break;

case "SHA512":
hash = new SHA512Managed();
break;

default:
hash = new MD5CryptoServiceProvider();
break;
}

// Compute hash value of our plain text with appended salt.
byte[] hashBytes = hash.ComputeHash(plainTextWithSaltBytes);

// Create array which will hold hash and original salt bytes.
byte[] hashWithSaltBytes = new byte[hashBytes.Length +
saltBytes.Length];

// Copy hash bytes into resulting array.
for (int i = 0; i < hashBytes.Length; i++)
hashWithSaltBytes[i] = hashBytes[i];

// Append salt bytes to the result.
for (int i = 0; i < saltBytes.Length; i++)
hashWithSaltBytes[hashBytes.Length + i] = saltBytes[i];

// Convert result into a base64-encoded string.
string hashValue = Convert.ToBase64String(hashWithSaltBytes);

// Return the result.
return hashValue;
}

/// <summary>
/// Compares a hash of the specified plain text value to a given
hash
/// value. Plain text is hashed with the same salt value as the
original
/// hash.
/// </summary>
/// <param name="plainText">
/// Plain text to be verified against the specified hash. The
function
/// does not check whether this parameter is null.
/// </param>
/// <param name="hashValue">
/// Base64-encoded hash value produced by ComputeHash function. This
value
/// includes the original salt appended to it.
/// </param>
/// <returns>
/// If computed hash mathes the specified hash the function the
return
/// value is true; otherwise, the function returns false.
/// </returns>
public static bool VerifyHash(string plainText, string hashValue)
{
// Name of the hash algorithm. Allowed values are: "MD5", "SHA1",
// "SHA256", "SHA384", and "SHA512" (if any other value is
specified,
// MD5 hashing algorithm will be used). This value is case-
insensitive.

// Convert base64-encoded hash value into a byte array.
byte[] hashWithSaltBytes = Convert.FromBase64String(hashValue);

// We must know size of hash (without salt).
int hashSizeInBits, hashSizeInBytes;

// Make sure that hashing algorithm name is specified.
if (algorithm == null)
algorithm = "";

// Size of hash is based on the specified algorithm.
switch (algorithm.ToUpper())
{
case "SHA1":
hashSizeInBits = 160;
break;

case "SHA256":
hashSizeInBits = 256;
break;

case "SHA384":
hashSizeInBits = 384;
break;

case "SHA512":
hashSizeInBits = 512;
break;

default: // Must be MD5
hashSizeInBits = 128;
break;
}

// Convert size of hash from bits to bytes.
hashSizeInBytes = hashSizeInBits / 8;

// Make sure that the specified hash value is long enough.
if (hashWithSaltBytes.Length < hashSizeInBytes)
return false;

// Allocate array to hold original salt bytes retrieved from hash.
byte[] saltBytes = new byte[hashWithSaltBytes.Length -
hashSizeInBytes];

// Copy salt from the end of the hash to the new array.
for (int i = 0; i < saltBytes.Length; i++)
saltBytes[i] = hashWithSaltBytes[hashSizeInBytes + i];

// Compute a new hash string.
string expectedHashString = ComputeHash(plainText, saltBytes);

// If the computed hash matches the specified hash,
// the plain text value must be correct.
return (hashValue == expectedHashString);
}
}
}
Respuesta Responder a este mensaje
#5 RFOG
18/06/2007 - 15:27 | Informe spam
¡A la buchaca!

Gracias. :-)

Lo miraré cuando tenga que hacer algo de eso, aunque generalmente uso el
que te he comentado... pero no puedo ponerlo aquí porque la parte
encriptada está en un chip que ponemos a nuestras placas CE y las llamadas
para generar la semilla y la encriptación son meros envoltorios de acceso
al hardware, que es el que trabaja.

En Mon, 18 Jun 2007 13:53:28 +0200, Diego Jancic
escribió:

Jejej... obviamente si se puede, el tema es que no podes encriptarla y
comparar directo contra la base de datos... Al algoritmo le tenes que
pasar el password mas la cadena encriptada y te dice si es correcto...
Si queres revisarla podes mirar abajo el codigo, de todas formas vi
mas de una implementacion similar y (aunque no se mucho de
criptografia) parece bastante buena..

Saludos,
Diego

using System;
using System.Text;
using System.Security.Cryptography;

namespace GDA.Services.Security.Utilities
{
/// <summary>
/// This class generates and compares hashes using MD5, SHA1, SHA256,
SHA384,
/// and SHA512 hashing algorithms. Before computing a hash, it
appends a
/// randomly generated salt to the plain text, and stores this salt
appended
/// to the result. To verify another plain text value against the
given hash,
/// this class will retrieve the salt value from the hash string and
use it
/// when computing a new hash of the plain text. Appending a salt
value to
/// the hash may not be the most efficient approach, so when using
hashes in
/// a real-life application, you may choose to store them separately.
You may
/// also opt to keep results as byte arrays instead of converting
them into
/// base64-encoded strings.
/// </summary>
public class PasswordHash
{
private static string algorithm = "SHA512";

/// <summary>
/// Generates a hash for the given plain text value and returns a
/// base64-encoded result. Before the hash is computed, a random
salt
/// is generated and appended to the plain text. This salt is stored
at
/// the end of the hash value, so it can be used later for hash
/// verification.
/// </summary>
/// <param name="plainText">
/// Plaintext value to be hashed. The function does not check
whether
/// this parameter is null.
/// </param>
/// <returns>
/// Hash value formatted as a base64-encoded string.
/// </returns>
public static string ComputeHash(string plainText)
{
return ComputeHash(plainText, null);
}

/// <summary>
/// Generates a hash for the given plain text value and returns a
/// base64-encoded result. Before the hash is computed, a random
salt
/// is generated and appended to the plain text. This salt is stored
at
/// the end of the hash value, so it can be used later for hash
/// verification.
/// </summary>
/// <param name="plainText">
/// Plaintext value to be hashed. The function does not check
whether
/// this parameter is null.
/// </param>
/// <returns>
/// Hash value formatted as a base64-encoded string.
/// </returns>
private static string ComputeHash(string plainText, byte[]
saltBytes)
{
// Name of the hash algorithm. Allowed values are: "MD5", "SHA1",
// "SHA256", "SHA384", and "SHA512" (if any other value is
specified
// MD5 hashing algorithm will be used). This value is case-
insensitive.

if (saltBytes == null)
{
// Define min and max salt sizes.
int minSaltSize = 4;
int maxSaltSize = 8;

// Generate a random number for the size of the salt.
Random random = new Random();
int saltSize = random.Next(minSaltSize, maxSaltSize);

// Allocate a byte array, which will hold the salt.
saltBytes = new byte[saltSize];

// Initialize a random number generator.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

// Fill the salt with cryptographically strong byte values.
rng.GetNonZeroBytes(saltBytes);
}

// Convert plain text into a byte array.
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

// Allocate array, which will hold plain text and salt.
byte[] plainTextWithSaltBytes > new byte[plainTextBytes.Length + saltBytes.Length];

// Copy plain text bytes into resulting array.
for (int i = 0; i < plainTextBytes.Length; i++)
plainTextWithSaltBytes[i] = plainTextBytes[i];

// Append salt bytes to the resulting array.
for (int i = 0; i < saltBytes.Length; i++)
plainTextWithSaltBytes[plainTextBytes.Length + i] = saltBytes[i];

// Because we support multiple hashing algorithms, we must define
// hash object as a common (abstract) base class. We will specify
the
// actual hashing algorithm class later during object creation.
HashAlgorithm hash;

// Make sure hashing algorithm name is specified.
if (algorithm == null)
algorithm = "";

// Initialize appropriate hashing algorithm class.
switch (algorithm.ToUpper())
{
case "SHA1":
hash = new SHA1Managed();
break;

case "SHA256":
hash = new SHA256Managed();
break;

case "SHA384":
hash = new SHA384Managed();
break;

case "SHA512":
hash = new SHA512Managed();
break;

default:
hash = new MD5CryptoServiceProvider();
break;
}

// Compute hash value of our plain text with appended salt.
byte[] hashBytes = hash.ComputeHash(plainTextWithSaltBytes);

// Create array which will hold hash and original salt bytes.
byte[] hashWithSaltBytes = new byte[hashBytes.Length +
saltBytes.Length];

// Copy hash bytes into resulting array.
for (int i = 0; i < hashBytes.Length; i++)
hashWithSaltBytes[i] = hashBytes[i];

// Append salt bytes to the result.
for (int i = 0; i < saltBytes.Length; i++)
hashWithSaltBytes[hashBytes.Length + i] = saltBytes[i];

// Convert result into a base64-encoded string.
string hashValue = Convert.ToBase64String(hashWithSaltBytes);

// Return the result.
return hashValue;
}

/// <summary>
/// Compares a hash of the specified plain text value to a given
hash
/// value. Plain text is hashed with the same salt value as the
original
/// hash.
/// </summary>
/// <param name="plainText">
/// Plain text to be verified against the specified hash. The
function
/// does not check whether this parameter is null.
/// </param>
/// <param name="hashValue">
/// Base64-encoded hash value produced by ComputeHash function. This
value
/// includes the original salt appended to it.
/// </param>
/// <returns>
/// If computed hash mathes the specified hash the function the
return
/// value is true; otherwise, the function returns false.
/// </returns>
public static bool VerifyHash(string plainText, string hashValue)
{
// Name of the hash algorithm. Allowed values are: "MD5", "SHA1",
// "SHA256", "SHA384", and "SHA512" (if any other value is
specified,
// MD5 hashing algorithm will be used). This value is case-
insensitive.

// Convert base64-encoded hash value into a byte array.
byte[] hashWithSaltBytes = Convert.FromBase64String(hashValue);

// We must know size of hash (without salt).
int hashSizeInBits, hashSizeInBytes;

// Make sure that hashing algorithm name is specified.
if (algorithm == null)
algorithm = "";

// Size of hash is based on the specified algorithm.
switch (algorithm.ToUpper())
{
case "SHA1":
hashSizeInBits = 160;
break;

case "SHA256":
hashSizeInBits = 256;
break;

case "SHA384":
hashSizeInBits = 384;
break;

case "SHA512":
hashSizeInBits = 512;
break;

default: // Must be MD5
hashSizeInBits = 128;
break;
}

// Convert size of hash from bits to bytes.
hashSizeInBytes = hashSizeInBits / 8;

// Make sure that the specified hash value is long enough.
if (hashWithSaltBytes.Length < hashSizeInBytes)
return false;

// Allocate array to hold original salt bytes retrieved from hash.
byte[] saltBytes = new byte[hashWithSaltBytes.Length -
hashSizeInBytes];

// Copy salt from the end of the hash to the new array.
for (int i = 0; i < saltBytes.Length; i++)
saltBytes[i] = hashWithSaltBytes[hashSizeInBytes + i];

// Compute a new hash string.
string expectedHashString = ComputeHash(plainText, saltBytes);

// If the computed hash matches the specified hash,
// the plain text value must be correct.
return (hashValue == expectedHashString);
}
}
}






Visita mi blog principal: http://rfog.blogsome.com
Y este sobre programación: http://geeks.ms/blogs/rfog
Libros, ciencia ficción y programación
Nadie mas muerto que el olvidado.
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida