如何使用 Web Crypto API 创建哈希?

How to create a hash using Web Crypto API?

我正在尝试在客户端创建 SHA-1 哈希。我正在尝试使用 Web Crypto API 来执行此操作,但是当我将输出与各种在线工具提供的内容进行比较时,结果完全不同。我认为问题出在 ArrayBuffer 到 Hex 的转换中。这是我的代码:

function generateHash() {
            var value = "mypassword";
            var crypto = window.crypto;
            var buffer = new ArrayBuffer(value);
            var hash_bytes = crypto.subtle.digest("SHA-1", buffer);
            hash_bytes.then(value => document.write([...new Uint8Array(value)].map(x => x.toString(16).padStart(2, '0')).join('')));
        }

document.write 的输出应该是:

91dfd9ddb4198affc5c194cd8ce6d338fde470e2

但不是,我得到了一个完全不同的不同长度的散列(应该是 40)。我可以就这个问题提出一些建议吗?谢谢

问题似乎更多是从字符串到 ArrayBuffer 的输入转换。例如。使用 str2ab() 代码有效:

generateHash();

function generateHash() {
    var value = "mypassword";
    var crypto = window.crypto;
    var buffer = str2ab(value); // Fix
    var hash_bytes = crypto.subtle.digest("SHA-1", buffer);
    hash_bytes.then(value => document.write([...new Uint8Array(value)].map(x => x.toString(16).padStart(2, '0')).join('')));
}

// 
function str2ab(str) {
    const buf = new ArrayBuffer(str.length);
    const bufView = new Uint8Array(buf);
    for (let i = 0, strLen = str.length; i < strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}

预期输出:

91dfd9ddb4198affc5c194cd8ce6d338fde470e2

使用调试器,看起来 var buffer = new ArrayBuffer(value); 导致 buffer 成为一个空的 ArrayBuffer。 value 中存储的文本字符串必须采用 utf-8 编码才能正确转换为字节,然后可以将其作为输入传递给 crypto.subtle.digest() 函数。

尝试更改:

var buffer = new ArrayBuffer(value);

至:

var buffer = new TextEncoder("utf-8").encode(value);

这将创建一个 Uint8Array(如 crypto.subtle.digest() 所预期的那样),其中包含对 'value' 中的文本字符串进行 utf-8 编码的字节。这应该可以解决问题并产生您期望的结果。