我需要能够在 JavaScript 中生成一个与服务器上匹配的哈希值。
这些是示例输入:
string plaintext = "1398836885";
string salt = "8xTpd9gMxF22nBcotVChIH5ocxplLQzI3Ba7xXBkMyyOVVr6e5/mupqxFHYVQD0U77BEbQ9auMWglUK63PeqCX4eB8kzBoOEAr1nXqpT3jjNwdYPQPdRvwPjdI/357CP";
正确的哈希结果是:
ovsvdWYOUIXU+LAfIYtOf7N60v6Qap6qBgS3IVwBG6k=
获取明文的代码为:
var now = ((long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
生成正确哈希的代码:
用法:
var _hash = Hashbrowns.Hash(plaintext, salt);
代码:
public static class Hashbrowns
{
private const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
public static string Hash(string plaintext, string salt = null)
{
return Hashbrowns.Hash<SHA256Cng>(plaintext, salt);
}
public static string Hash<TAlgorithm>(string plaintext, string salt = null) where TAlgorithm : HashAlgorithm, new()
{
var algorithm = Activator.CreateInstance<TAlgorithm>();
if (string.IsNullOrWhiteSpace(salt))
{
salt = Config.Salt;
}
var data = Encoding.UTF8.GetBytes(plaintext + salt);
return Convert.ToBase64String(algorithm.ComputeHash(data));
}
public static string HashPassword(string value)
{
return Hash(value, Config.Salt + Config.Spice);
}
public static string RandomString(int length)
{
var random = new Random();
return new string(
Enumerable
.Repeat(Hashbrowns.chars, length)
.Select(o => o[random.Next(o.Length)])
.ToArray()
);
}
}
JAVASCRIPT 部分
在我的 javascript 代码中,我使用 Crypto Js 来获取 SHA256:
<script type="text/javascript" src="plugin/CryptoJS v3.1.2/rollups/sha256.js"></script>
<小时/>
Hash: function(){
var o = "13988354648xTpd9gMxF22nBcotVChIH5ocxplLQzI3Ba7xXBkMyyOVVr6e5/mupqxFHYVQD0U77BEbQ9auMWglUK63PeqCX4eB8kzBoOEAr1nXqpT3jjNwdYPQPdRvwPjdI/357CP",
hash256 = CryptoJS.SHA256(o),
;
console.log(hash256.toString(CryptoJS.enc.Base64));
}
结果是:
a2fb2f75660e5085d4f8b01f218b4e7fb37ad2fe906a9eaa0604b7215c011ba9
显然,它们不一样。
幸运的是,有一个 JAVA 代码版本可以产生相同的结果。我刚刚从外包开发人员那里得到了这段代码,我告诉你,我对 JAVA 不太熟悉。
StringBuilder sb = new StringBuilder();
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.reset();
byte[] buffer = hash.getBytes("UTF-8");
md.update(buffer);
byte[] digest = md.digest();
for (int i = 0; i < digest.length; i++){
sb.append(Integer.toString((digest[i] & 0xff) + 0x100, 16).substring(1));
}
hashKey = Base64.encodeToString(digest, Base64.DEFAULT);
}
他们说他们能够使用此代码获得正确的结果。如果这个代码可以转换成javascript代码,这可能会解决这个问题。
顺便说一句,此代码是一个简单的移动应用程序(html 基础)的一部分,该应用程序将使用 PhoneGap 发布。服务器上没有可用于生成哈希值的 API。
最佳答案
哈希部分实际上工作正常 - 在这两种情况下您都得到相同的二进制数据 - 唯一的区别是 Javascript 中的输出是十六进制,而不是 base64。此 C# 代码:
using System;
class Test
{
static void Main()
{
string base64 = "ovsvdWYOUIXU+LAfIYtOf7N60v6Qap6qBgS3IVwBG6k=";
byte[] rawData = Convert.FromBase64(base64);
Console.WriteLine(BitConverter.ToString(rawData));
}
}
...打印出:
A2-FB-2F-75-66-0E-50-85-D4-F8-B0-1F-21-8B-4E-7F-B3-7A-D2-FE-90-6A-9E-AA-06-04-B7-21-5C-01-1B-A9
这与您的 Javascript 输出相同,模数大小写和字节之间的“-”。
我自己刚刚使用 Crypto-js 尝试过此操作,我认为问题是您没有 enc-base64.js
组件,该组件未包含在汇总中。只需添加:
<script type="text/javascript" src="plugin/CryptoJS v3.1.2/components/enc-base64.js"></script>
...一切都应该没问题。 (当然,请检查您是否拥有该文件...)
关于c# - JavaScript 中的 SHA256Cng,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23380851/