C# 使用 Sha256 散列字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12416249/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hashing a string with Sha256
提问by Nattfrosten
I try to hash a string using SHA256, I'm using the following code:
我尝试使用 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;
}
}
However, this code gives significantly different results compared to my friends php, as well as online generators (such as This generator)
但是,与我的朋友 php 以及在线生成器(例如This generator)相比,此代码给出了明显不同的结果
Does anyone know what the error is? Different bases?
有谁知道错误是什么?基数不同?
采纳答案by Quuxplusone
Encoding.Unicodeis Microsoft's misleading name for UTF-16 (a double-wide encoding, used in the Windows world for historical reasons but not used by anyone else). http://msdn.microsoft.com/en-us/library/system.text.encoding.unicode.aspx
Encoding.Unicode是 Microsoft 对 UTF-16(一种双宽编码,由于历史原因在 Windows 世界中使用,但未被其他任何人使用)的误导性名称。http://msdn.microsoft.com/en-us/library/system.text.encoding.unicode.aspx
If you inspect your bytesarray, you'll see that every second byte is 0x00(because of the double-wide encoding).
如果你检查你的bytes数组,你会看到每第二个字节是0x00(因为双宽编码)。
You should be using Encoding.UTF8.GetBytesinstead.
你应该Encoding.UTF8.GetBytes改用。
But also, you will see different results depending on whether or not you consider the terminating '\0'byte to be part of the data you're hashing. Hashing the two bytes "Hi"will give a different result from hashing the threebytes "Hi". You'll have to decide which you want to do. (Presumably you want to do whichever one your friend's PHP code is doing.)
而且,您将看到不同的结果,具体取决于您是否将终止'\0'字节视为要散列的数据的一部分。散列两个字节"Hi"将给出与散列三个字节不同的结果"Hi"。你必须决定你想做什么。(想必你想做你朋友的 PHP 代码正在做的任何一个。)
For ASCII text, Encoding.UTF8will definitely be suitable. If you're aiming for perfectcompatibility with your friend's code, even on non-ASCII inputs, you'd better try a few test cases with non-ASCII characters such as éand 家and see whether your results still match up. If not, you'll have to figure out what encoding your friend is really using; it might be one of the 8-bit "code pages" that used to be popular before the invention of Unicode. (Again, I think Windows is the main reason that anyone still needs to worry about "code pages".)
对于 ASCII 文本,Encoding.UTF8肯定会适合。如果您的目标是与朋友的代码完美兼容,即使是在非 ASCII 输入上,您最好尝试一些非 ASCII 字符的测试用例,例如é和家,看看您的结果是否仍然匹配。如果没有,你就必须弄清楚你的朋友真正使用的是什么编码;它可能是在 Unicode 发明之前曾经流行的 8 位“代码页”之一。(同样,我认为 Windows 是任何人仍然需要担心“代码页”的主要原因。)
回答by Nico Dumdum
I also had this problem with another style of implementation but I forgot where I got it since it was 2 years ago.
我在使用另一种实现方式时也遇到了这个问题,但我忘记了从 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;
}
When I input something like abcdefghi2013for some reason it gives different results and results in errors in my login module.
Then I tried modifying the code the same way as suggested by Quuxplusone and changed the encoding from ASCIIto UTF8then it finally worked!
当我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();
}
Thanks again Quuxplusone for the wonderful and detailed answer! :)
再次感谢 Quuxplusone 精彩而详细的回答!:)
回答by Rachel
In the PHP version you can send 'true' in the last parameter, but the default is 'false'. The following algorithm is equivalent to the default PHP's hash function when passing 'sha256' as the first parameter:
在 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;
}
回答by ARC
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));
}
}
回答by Auto
public static string ComputeSHA256Hash(string text)
{
using (var sha256 = new SHA256Managed())
{
return BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(text))).Replace("-", "");
}
}
The reason why you get different results is because you don't use the same string encoding. The link you put for the on-line web site that computes SHA256 uses UTF8 Encoding, while in your example you used Unicode Encoding. They are two different encodings, so you don't get the same result. With the example above you get the same SHA256 hash of the linked web site. You need to use the same encoding also in PHP.
你得到不同结果的原因是因为你没有使用相同的字符串编码。您为计算 SHA256 的在线网站放置的链接使用 UTF8 编码,而在您的示例中,您使用了 Unicode 编码。它们是两种不同的编码,因此您不会得到相同的结果。通过上面的示例,您将获得链接网站的相同 SHA256 哈希值。您还需要在 PHP 中使用相同的编码。
The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
每个软件开发人员绝对必须了解 Unicode 和字符集的绝对最低要求(没有任何借口!)
回答by Er?in Dedeo?lu
The shortest and fastest way ever. Only 1 line!
有史以来最短和最快的方式。只有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);

