如何在 JS 中使用 SHA256 散列字符串? [英] How can I hash a string with SHA256 in JS?

查看:162
本文介绍了如何在 JS 中使用 SHA256 散列字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说明

我希望在 Javascript 中使用 SHA256 在本地散列一个字符串.我一直在环顾四周,认为会有某种官方库或函数,但我发现的只是大量不同的项目,每个项目都有不同的脚本,我不太确定可以信任的脚本(因为我不是专家,绝对没有资格评估它们)或如何实现它们.我需要文本输出,而不是十六进制,抱歉,如果我在发布原始问题时没有解释这一点.

代码

这是我迄今为止尝试过的:

异步函数 sha256(message) {//编码为 UTF-8const msgBuffer = new TextEncoder('utf-8').encode(message);//散列消息const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);//将 ArrayBuffer 转换为 Arrayconst hashArray = Array.from(new Uint8Array(hashBuffer));//将字节转换为十六进制字符串const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');控制台日志(hashHex);返回 hashHex;}sha256(密码输入);

控制台输出:

<块引用>

未捕获(承诺)类型错误:无法读取未定义的属性摘要"

我是 JavaScript 新手,我愿意接受所有建议,所以是的.

更新

尽管您的大部分建议都有效,但对于那些希望使用 Web Crypto API 的人来说,答案就在第 5 行.我需要将 crypto.subtle.digest 更改为 window.crypto.subtle.digest

解决方案

你好 :D 这是一个很好的功能.如果你是学者,你想看看这篇文章:https://www.movable-type.co.uk/scripts/sha256.html

纯javascript,无需依赖:

var sha256 = function sha256(ascii) {函数 rightRotate(value, amount) {return (value>>>amount) |(值<<(32 - 数量));};var mathPow = Math.pow;var maxWord = mathPow(2, 32);var lengthProperty = '长度'变量 i, j;//用作整个文件的计数器变量结果 = ''var 词 = [];var asciiBitLength = ascii[lengthProperty]*8;//* 缓存结果是可选的 - 从这一行的前面删除/添加斜线以进行切换//初始哈希值:前 8 个素数平方根的小数部分的前 32 位//(我们实际上计算了前 64 个,但忽略了额外的值)var 哈希 = sha256.h = sha256.h ||[];//舍入常量:前 64 个素数的立方根的小数部分的前 32 位var k = sha256.k = sha256.k ||[];var primeCounter = k[lengthProperty];/*/var hash = [], k = [];var primeCounter = 0;//*/var isComposite = {};for (varCandidate = 2; primeCounter < 64;Candidate++) {如果 (!isComposite[候选人]) {for (i = 0; i <313; i += 候选) {isComposite[i] = 候选人;}hash[primeCounter] = (mathPow(candidate, .5)*maxWord)|0;k[primeCounter++] = (mathPow(candidate, 1/3)*maxWord)|0;}}ascii += '\x80'//附加Ƈ'位(加零填充)while (ascii[lengthProperty]%64 - 56) ascii += '\x00'//更多的零填充for (i = 0; i >>3))//s0+ w[i - 7]+ (rightRotate(w2, 17) ^ rightRotate(w2, 19) ^ (w2>>>10))//s1)|0);//这只使用一次,所以*可以*移到下面,但它只节省了 4 个字节并且使事情变得不可读var temp2 = (rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22))//S0+ ((a&hash[1])^(a&hash[2])^(hash[1]&hash[2]));//少校hash = [(temp1 + temp2)|0].concat(hash);//我们不费心修剪多余的,只要我们在执行 slice() 时截断它们就无害hash[4] = (hash[4] + temp1)|0;}for (i = 0; i <8; i++) {hash[i] = (hash[i] + oldHash[i])|0;}}for (i = 0; i <8; i++) {对于 (j = 3; j + 1; j--) {var b = (hash[i]>>(j*8))&255;结果 += ((b <16) ? 0 : '') + b.toString(16);}}返回结果;};

来源: https://geraintluff.github.io/sha256/

Description

I'm looking to hash a string locally with SHA256 in Javascript. I've been looking around thinking there would be some sort of official library or function, but all I found were loads of different projects, each with different scripts, and I'm not so sure scripts to trust (as I'm not an expert and definitely not qualified to evaluate them) or how to implement them. EDIT: I need the output in text, not hexes, sorry if I didn't explain that when posting the original question.

Code

Here's what I've tried so far:

async function sha256(message) {
  // encode as UTF-8
  const msgBuffer = new TextEncoder('utf-8').encode(message);

  // hash the message
  const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);

  // convert ArrayBuffer to Array
  const hashArray = Array.from(new Uint8Array(hashBuffer));

  // convert bytes to hex string
  const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
  console.log(hashHex);
  return hashHex;
}
sha256(passwordInput); 

Console Output:

Uncaught (in promise) TypeError: Cannot read property 'digest' of undefined

I'm new to javascript and I'm open to all suggestions, so yeah.

Update

Although most of your suggestions work, for those of you who are looking to use the Web Crypto API, the answer was on line #5. I needed to change crypto.subtle.digest to window.crypto.subtle.digest

解决方案

Hellow there :D it's quite a function. If you are a scholar, you would like to check this article: https://www.movable-type.co.uk/scripts/sha256.html

Pure javascript, no dependencies needed:

var sha256 = function sha256(ascii) {
    function rightRotate(value, amount) {
        return (value>>>amount) | (value<<(32 - amount));
    };
    
    var mathPow = Math.pow;
    var maxWord = mathPow(2, 32);
    var lengthProperty = 'length'
    var i, j; // Used as a counter across the whole file
    var result = ''

    var words = [];
    var asciiBitLength = ascii[lengthProperty]*8;
    
    //* caching results is optional - remove/add slash from front of this line to toggle
    // Initial hash value: first 32 bits of the fractional parts of the square roots of the first 8 primes
    // (we actually calculate the first 64, but extra values are just ignored)
    var hash = sha256.h = sha256.h || [];
    // Round constants: first 32 bits of the fractional parts of the cube roots of the first 64 primes
    var k = sha256.k = sha256.k || [];
    var primeCounter = k[lengthProperty];
    /*/
    var hash = [], k = [];
    var primeCounter = 0;
    //*/

    var isComposite = {};
    for (var candidate = 2; primeCounter < 64; candidate++) {
        if (!isComposite[candidate]) {
            for (i = 0; i < 313; i += candidate) {
                isComposite[i] = candidate;
            }
            hash[primeCounter] = (mathPow(candidate, .5)*maxWord)|0;
            k[primeCounter++] = (mathPow(candidate, 1/3)*maxWord)|0;
        }
    }
    
    ascii += '\x80' // Append Ƈ' bit (plus zero padding)
    while (ascii[lengthProperty]%64 - 56) ascii += '\x00' // More zero padding
    for (i = 0; i < ascii[lengthProperty]; i++) {
        j = ascii.charCodeAt(i);
        if (j>>8) return; // ASCII check: only accept characters in range 0-255
        words[i>>2] |= j << ((3 - i)%4)*8;
    }
    words[words[lengthProperty]] = ((asciiBitLength/maxWord)|0);
    words[words[lengthProperty]] = (asciiBitLength)
    
    // process each chunk
    for (j = 0; j < words[lengthProperty];) {
        var w = words.slice(j, j += 16); // The message is expanded into 64 words as part of the iteration
        var oldHash = hash;
        // This is now the undefinedworking hash", often labelled as variables a...g
        // (we have to truncate as well, otherwise extra entries at the end accumulate
        hash = hash.slice(0, 8);
        
        for (i = 0; i < 64; i++) {
            var i2 = i + j;
            // Expand the message into 64 words
            // Used below if 
            var w15 = w[i - 15], w2 = w[i - 2];

            // Iterate
            var a = hash[0], e = hash[4];
            var temp1 = hash[7]
                + (rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25)) // S1
                + ((e&hash[5])^((~e)&hash[6])) // ch
                + k[i]
                // Expand the message schedule if needed
                + (w[i] = (i < 16) ? w[i] : (
                        w[i - 16]
                        + (rightRotate(w15, 7) ^ rightRotate(w15, 18) ^ (w15>>>3)) // s0
                        + w[i - 7]
                        + (rightRotate(w2, 17) ^ rightRotate(w2, 19) ^ (w2>>>10)) // s1
                    )|0
                );
            // This is only used once, so *could* be moved below, but it only saves 4 bytes and makes things unreadble
            var temp2 = (rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22)) // S0
                + ((a&hash[1])^(a&hash[2])^(hash[1]&hash[2])); // maj
            
            hash = [(temp1 + temp2)|0].concat(hash); // We don't bother trimming off the extra ones, they're harmless as long as we're truncating when we do the slice()
            hash[4] = (hash[4] + temp1)|0;
        }
        
        for (i = 0; i < 8; i++) {
            hash[i] = (hash[i] + oldHash[i])|0;
        }
    }
    
    for (i = 0; i < 8; i++) {
        for (j = 3; j + 1; j--) {
            var b = (hash[i]>>(j*8))&255;
            result += ((b < 16) ? 0 : '') + b.toString(16);
        }
    }
    return result;
};

Source: https://geraintluff.github.io/sha256/

这篇关于如何在 JS 中使用 SHA256 散列字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆