[英]Hashing a string with Sha256
我尝试使用 SHA256 hash 字符串,我使用以下代码:
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 )相比,此代码给出了明显不同的结果
有谁知道错误是什么? 不同的基地?
Encoding.Unicode
是 Microsoft 对 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 字符(例如é
和家
测试用例,看看您的结果是否仍然匹配。 如果没有,你就必须弄清楚你的朋友真正使用的是什么编码; 它可能是在 Unicode 发明之前曾经流行的 8 位“代码页”之一。 (同样,我认为 Windows 是任何人仍然需要担心“代码页”的主要原因。)
我在使用另一种实现方式时也遇到了这个问题,但我忘记了从 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 精彩而详细的回答! :)
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 和字符集的绝对最低要求(没有任何借口!)
在 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;
}
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));
}
}
有史以来最短和最快的方式。 只有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);
我正在寻找和测试这些答案,Visual Studio 向我展示了 SHA256Managed 现在已过时( 此处)
所以,我使用了 SHA256 class 代替:
Encoding enc = Encoding.UTF8;
var hashBuilder = new StringBuilder();
using var hash = SHA256.Create();
byte[] result = hash.ComputeHash(enc.GetBytes(value));
foreach (var b in result)
hashBuilder.Append(b.ToString("x2"));
string result = hashBuilder.ToString();
如果您使用的是 .NET 5 或更高版本,则可以使用新的Convert.ToHexString
方法将 hash 字节数组转换为十六进制字符串; 消除使用字符串生成器等的麻烦。
以下还使用using
块,以便处置SHA256
实例。 它还使用接受的答案建议的 UTF8 编码将密码(作为字符串传入)转换为字节数组。 此外,我们还使用新的SHA256
class,而不是旧的(现已过时的) SHA256Managed
class。
public string QuickHash(string secret)
{
using var sha256 = SHA256.Create();
var secretBytes = Encoding.UTF8.GetBytes(secret);
var secretHash = sha256.ComputeHash(secretBytes);
return Convert.ToHexString(secretHash);
}
注意:您不应该使用这种方法来散列用户密码。 SHA-256 等通用散列函数不再适合用于密码,即使您添加了盐。 这对于散列您知道具有高熵的字符串很有用,例如长时间随机生成的 session 令牌等等。 为了存储密码,您必须查看专门为此目的设计的较慢的散列函数,例如 Bcrypt、Scrypt 或 PBKDF2(后者在 .NET 中原生可用 - 请参阅此)
这在 .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);
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.