Kev*_*sen 6 javascript c# hash react-native expo
我正在尝试构建 SHA256 ComputeHash 的等效版本(来自 C#,与下面示例的输出完全相同),以响应 Native/JavaScript。这是以下 C#:
public static string Hash(string input)
{
if (string.IsNullOrWhiteSpace(input)) return "";
using (SHA256 hasher = SHA256.Create())
{
// Convert the input string to a byte array and compute the hash.
byte[] data = hasher.ComputeHash(Encoding.Unicode.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("X2"));
}
// Return the hexadecimal string.
return $"0x{sBuilder.ToString().ToLower()}";
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试了以下方法,但它没有生成相同的哈希值:
import * as Crypto from 'expo-crypto';
const hash = await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
"StringIWantToHash"
);
Run Code Online (Sandbox Code Playgroud)
有人知道 JavaScript 有什么问题吗,或者是否有 C# 版本的完全相同的版本?
嗯,这是一个编码问题。
Encoding.Unicode是 Microsoft 对 UTF-16(一种双宽编码,由于历史原因在 Windows 世界中使用,但没有被其他任何人使用)的误导性名称。http://msdn.microsoft.com/en-us/library/system.text.encoding.unicode.aspx(请参阅此答案)
你应该改用Encoding.UTF8.GetBytes。
像这样使用js-sha256库:
const jssha = require('js-sha256')
function hash(input)
{
const hashString = "0x" + jssha.sha256(input)
return hashString;
}
const hashResult = hash("StringIWantToHash")
// Output: 0x29c506d0d69a16e413d63921b7de79525c43715931d8d93127dbeb46eacda2f9
Run Code Online (Sandbox Code Playgroud)
我们可以在 C# 中使用UTF8 编码实现非常相似的效果:
public static string Hash(string input)
{
if (string.IsNullOrWhiteSpace(input)) return "";
using (SHA256 hasher = SHA256.Create())
{
// Convert the input string to a byte array and compute the hash.
byte[] data = hasher.ComputeHash(Encoding.UTF8.GetBytes(input)); // Note that UTF8 here
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("X2"));
}
// Return the hexadecimal string.
return $"0x{sBuilder.ToString().ToLower()}";
}
}
static void Main()
{
var hashResult = Hash("StringIWantToHash");
// Output: 0x29c506d0d69a16e413d63921b7de79525c43715931d8d93127dbeb46eacda2f9
}
Run Code Online (Sandbox Code Playgroud)
另外,我相信其他有助于计算 SHA256 哈希的 JS/React Native 库也使用 UTF8 编码,所以我认为您可以使用任何其他加密库。
在这种情况下,您需要在 JS 代码中手动表示 C# 编码。
当您使用 Unicode 编码时,如果字符串中的每个字节是纯拉丁字符,则在字符串中的每个字节之后都会变为“0”字节。对于其他符号(超过 255 个数字),Unicode 需要 2 个字节。
var input = "StringIWantToHash";
var encodedInput = Encoding.Unicode.GetBytes(input);
// Output: [83, 0, 116, 0, 114, 0, 105, 0, 110, 0, ...]
Run Code Online (Sandbox Code Playgroud)
所以我们需要在 JS 代码中表示这一点:
const jssha = require('js-sha256')
function hash(input)
{
var bytes = [];
for (var i = 0; i < input.length; i++)
{
const code = input.charCodeAt(i);
bytes = bytes.concat([code & 0xff, code / 256 >>> 0]);
}
const hashString = "0x" + jssha.sha256(bytes)
return hashString;
}
const hashResult = hash("StringIWantToHash")
// Output: 0x029dbc4b54b39bed6d684175b2d76cc5622c60fe91f0bde9865b977d0d9a531d
Run Code Online (Sandbox Code Playgroud)