Eu tento hash uma seqüência usando SHA256, estou usando o seguinte 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;
}
}
No entanto, esse código fornece resultados significativamente diferentes em comparação com o php dos meus amigos, além de geradores on-line (como este gerador )
Alguém sabe qual é o erro? Bases diferentes?
Respostas:
Encoding.Unicode
é o nome enganoso da Microsoft para UTF-16 (uma codificação de largura dupla, usada no mundo do Windows por razões históricas, mas não usada por mais ninguém). http://msdn.microsoft.com/en-us/library/system.text.encoding.unicode.aspxSe você inspecionar sua
bytes
matriz, verá que cada segundo byte é0x00
(por causa da codificação de largura dupla).Você deveria estar usando
Encoding.UTF8.GetBytes
.Além disso, você verá resultados diferentes, dependendo de considerar ou não o
'\0'
byte final como parte dos dados que você está hash. O hash dos dois bytes"Hi"
fornecerá um resultado diferente do hash dos três bytes"Hi"
. Você terá que decidir o que deseja fazer. (Presumivelmente, você deseja fazer o que o código PHP de seu amigo estiver fazendo.)Para texto ASCII,
Encoding.UTF8
será definitivamente adequado. Se você está apontando para perfeita compatibilidade com o código do seu amigo, mesmo em entradas não-ASCII, é melhor tentar alguns casos de teste com caracteres não-ASCII, comoé
e家
para ver se os resultados ainda igualar-se. Caso contrário, você terá que descobrir qual codificação seu amigo está realmente usando; pode ser uma das "páginas de código" de 8 bits que eram populares antes da invenção do Unicode. (Mais uma vez, acho que o Windows é o principal motivo pelo qual alguém ainda precisa se preocupar com "páginas de código".)fonte
short
s codificados em UTF16 ", mas não "classificar por bytes codificados em UTF16", a menos que você esteja em um sistema big endian, o que o Windows não é.) No entanto, "classificar" no Unicode é realmente um tópico complicado que deve ser salvo para outro dia.Eu também tive esse problema com outro estilo de implementação, mas esqueci onde o consegui desde há 2 anos.
Quando introduzo algo como,
abcdefghi2013
por algum motivo, ele fornece resultados diferentes e resulta em erros no meu módulo de login. Tentei modificar o código da mesma maneira sugerida pelo Quuxplusone e alterei a codificação deASCII
paraUTF8
então finalmente funcionou!Mais uma vez obrigado Quuxplusone pela resposta maravilhosa e detalhada! :)
fonte
hash += bit.ToString("x2");
eu tenho uma pergunta aqui: eu estava usandoConvert.ToBase64String(byte[] encryptedBytes)
para converter novamente de bytes em string. isso estava me dando um resultado diferente. Então, qual é a diferença entre esses dois métodos de conversão de bytes em string?A razão pela qual você obtém resultados diferentes é porque você não usa a mesma codificação de string. O link que você colocou para o site on-line que calcula o SHA256 usa a codificação UTF8, enquanto no seu exemplo você usou a codificação Unicode. São duas codificações diferentes, para que você não obtenha o mesmo resultado. Com o exemplo acima, você obtém o mesmo hash SHA256 do site vinculado. Você precisa usar a mesma codificação também no PHP.
O mínimo absoluto que todo desenvolvedor de software deve saber absolutamente, positivamente sobre Unicode e conjuntos de caracteres (sem desculpas!)
https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/
fonte
Na versão PHP, você pode enviar 'true' no último parâmetro, mas o padrão é 'false'. O algoritmo a seguir é equivalente à função hash do PHP padrão ao passar 'sha256' como o primeiro parâmetro:
fonte
ASCII
e o fariabyte[] arrBytes = System.Text.Encoding.UTF8.GetBytes(strData)
.fonte
A maneira mais curta e rápida de todas. Apenas 1 linha!
fonte