Intento hacer un hash de una cadena usando SHA256, estoy usando el siguiente código:
using System;
using System.Security.Cryptography;
using System.Text;
public class Hash
{
public static string getHashSha256(string text)
{
byte[] bytes = Encoding.Unicode.GetBytes(text);
SHA256Managed hashstring = new SHA256Managed();
byte[] hash = hashstring.ComputeHash(bytes);
string hashString = string.Empty;
foreach (byte x in hash)
{
hashString += String.Format("{0:x2}", x);
}
return hashString;
}
}
Sin embargo, este código da resultados significativamente diferentes en comparación con mis amigos php, así como generadores en línea (como este generador )
¿Alguien sabe cuál es el error? Diferentes bases?
Respuestas:
Encoding.Unicode
es el nombre engañoso de Microsoft para UTF-16 (una codificación de doble ancho, utilizada en el mundo de Windows por razones históricas pero no utilizada por nadie más). http://msdn.microsoft.com/en-us/library/system.text.encoding.unicode.aspxSi inspecciona su
bytes
matriz, verá que cada segundo byte es0x00
(debido a la codificación de doble ancho).Deberías estar usando en su
Encoding.UTF8.GetBytes
lugar.Pero también, verá resultados diferentes dependiendo de si considera o no que el
'\0'
byte de terminación es parte de los datos que está troquelando. El hash de los dos bytes"Hi"
dará un resultado diferente al de los tres bytes"Hi"
. Tendrás que decidir qué quieres hacer. (Presumiblemente quiere hacer lo que sea que esté haciendo el código PHP de su amigo).Para el texto ASCII,
Encoding.UTF8
definitivamente será adecuado. Si busca una compatibilidad perfecta con el código de su amigo, incluso en entradas no ASCII, será mejor que pruebe algunos casos de prueba con caracteres no ASCII comoé
y家
y vea si sus resultados aún coinciden. Si no, tendrás que descubrir qué codificación está usando realmente tu amigo; podría ser una de las "páginas de códigos" de 8 bits que solían ser populares antes de la invención de Unicode. (Una vez más, creo que Windows es la razón principal por la que alguien todavía debe preocuparse por las "páginas de códigos").fuente
short
s codificados con UTF16 ", pero no "ordenar por bytes codificados por UTF16" a menos que esté en un sistema big endian, que no es Windows). Sin embargo, "ordenar" en Unicode es realmente un tema complicado que debería guardarse para otro día.También tuve este problema con otro estilo de implementación, pero olvidé dónde lo obtuve, ya que fue hace 2 años.
Cuando ingreso algo como
abcdefghi2013
por alguna razón, da resultados diferentes y produce errores en mi módulo de inicio de sesión. Luego intenté modificar el código de la misma manera que lo sugerido por Quuxplusone y cambié la codificaciónASCII
paraUTF8
que finalmente funcionara.Gracias de nuevo Quuxplusone por la maravillosa y detallada respuesta. :)
fuente
hash += bit.ToString("x2");
que tengo una pregunta aquí: estaba usandoConvert.ToBase64String(byte[] encryptedBytes)
para convertir de bytes a cadena. eso me estaba dando un resultado diferente. Entonces, ¿cuál es la diferencia entre estos dos métodos de conversión de bytes a cadena ...?La razón por la que obtiene resultados diferentes es porque no usa la misma codificación de cadena. El enlace que coloca para el sitio web en línea que calcula SHA256 usa la codificación UTF8, mientras que en su ejemplo usó la codificación Unicode. Son dos codificaciones diferentes, por lo que no obtienes el mismo resultado. Con el ejemplo anterior, obtiene el mismo hash SHA256 del sitio web vinculado. Debe usar la misma codificación también en PHP.
El mínimo absoluto que todo desarrollador de software debe saber absolutamente, positivamente sobre los conjuntos de caracteres y Unicode (¡sin excusas!)
https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/
fuente
En la versión de PHP, puede enviar 'verdadero' en el último parámetro, pero el valor predeterminado es 'falso'. El siguiente algoritmo es equivalente a la función hash predeterminada de PHP al pasar 'sha256' como primer parámetro:
fuente
ASCII
y hacer en subyte[] arrBytes = System.Text.Encoding.UTF8.GetBytes(strData)
lugar.fuente
La forma más corta y rápida de la historia. ¡Solo 1 línea!
fuente