我尝试使用SHA256散列字符串,我使用以下代码:
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;
}
}
但是,与我的朋友php以及在线生成器(例如This generator)
相比,此代码会产生显着不同的结果有谁知道错误是什么?不同的基础?
答案 0 :(得分:144)
Encoding.Unicode
是微软对UTF-16的误导性名称(双宽编码,由于历史原因在Windows世界中使用但未被其他任何人使用)。 http://msdn.microsoft.com/en-us/library/system.text.encoding.unicode.aspx
如果你检查bytes
数组,你会发现每隔一个字节都是0x00
(因为双宽编码)。
您应该使用Encoding.UTF8.GetBytes
代替。
但是,根据您是否认为终止'\0'
字节是您正在散列的数据的一部分,您将看到不同的结果。散列两个字节"Hi"
将得到与散列三个字节"Hi"
不同的结果。你必须决定你想做什么。 (据推测,你想要做你朋友的PHP代码所做的任何事情。)
对于ASCII文本,Encoding.UTF8
肯定是合适的。如果您的目标是完美与您朋友的代码兼容,即使在非ASCII输入上,您最好还是尝试使用非{ASCII}字符的一些测试用例,例如é
和{ {1}}并查看您的结果是否仍然匹配。如果没有,你将不得不弄清楚你的朋友正在使用什么编码;它可能是在Unicode发明之前流行的8位“代码页”之一。 (同样,我认为Windows是任何人仍然需要担心“代码页”的主要原因。)
答案 1 :(得分:91)
我还遇到了另一种实施方式的问题,但我忘记了自2年前以来我在哪里获得它。
static string sha256(string randomString)
{
var crypt = new SHA256Managed();
string hash = String.Empty;
byte[] crypto = crypt.ComputeHash(Encoding.ASCII.GetBytes(randomString));
foreach (byte theByte in crypto)
{
hash += theByte.ToString("x2");
}
return hash;
}
当我因某种原因输入类似abcdefghi2013
的内容时,它会给出不同的结果并导致我的登录模块出错。
然后我尝试以与Quuxplusone建议相同的方式修改代码,并将编码从ASCII
更改为UTF8
,然后它终于有效了!
static string sha256(string randomString)
{
var crypt = new System.Security.Cryptography.SHA256Managed();
var hash = new System.Text.StringBuilder();
byte[] crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(randomString));
foreach (byte theByte in crypto)
{
hash.Append(theByte.ToString("x2"));
}
return hash.ToString();
}
再次感谢Quuxplusone精彩而详细的回答! :)
答案 2 :(得分:4)
在PHP版本中,您可以发送' true'在最后一个参数中,但默认为' false'。传递' sha256'以下算法相当于默认的PHP哈希函数。作为第一个参数:
public static string GetSha256FromString(string strData)
{
var message = Encoding.ASCII.GetBytes(strData);
SHA256Managed hashString = new SHA256Managed();
string hex = "";
var hashValue = hashString.ComputeHash(message);
foreach (byte x in hashValue)
{
hex += String.Format("{0:x2}", x);
}
return hex;
}
答案 3 :(得分:2)
有史以来最短,最快的方法。只有1行!
public static string StringSha256Hash(string text) =>
string.IsNullOrEmpty(text) ? string.Empty : BitConverter.ToString(new System.Security.Cryptography.SHA256Managed().ComputeHash(System.Text.Encoding.UTF8.GetBytes(text))).Replace("-", string.Empty);
答案 4 :(得分:1)
public string EncryptPassword(string password, string saltorusername)
{
using (var sha256 = SHA256.Create())
{
var saltedPassword = string.Format("{0}{1}", salt, password);
byte[] saltedPasswordAsBytes = Encoding.UTF8.GetBytes(saltedPassword);
return Convert.ToBase64String(sha256.ComputeHash(saltedPasswordAsBytes));
}
}
答案 5 :(得分:1)
public static string ComputeSHA256Hash(string text)
{
using (var sha256 = new SHA256Managed())
{
return BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(text))).Replace("-", "");
}
}
之所以得到不同的结果,是因为您没有使用相同的字符串编码。您为计算SHA256的在线网站放置的链接使用UTF8编码,而在您的示例中,您使用Unicode编码。它们是两种不同的编码,因此您不会得到相同的结果。在上面的示例中,您将获得链接网站的相同SHA256哈希。您还需要在PHP中使用相同的编码。
每个软件开发人员绝对,肯定必须了解Unicode和字符集的绝对最低要求(无借口!)
答案 6 :(得分:-2)
在.NET Core 3.1中对我有用。
但是不在.NET 5预览版7中。
using System;
using System.Security.Cryptography;
using System.Text;
namespace PortalAplicaciones.Shared.Models
{
public class Encriptar
{
public static string EncriptaPassWord(string Password)
{
try
{
SHA256Managed hasher = new SHA256Managed();
byte[] pwdBytes = new UTF8Encoding().GetBytes(Password);
byte[] keyBytes = hasher.ComputeHash(pwdBytes);
hasher.Dispose();
return Convert.ToBase64String(keyBytes);
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
}
}