Why does my implementation of crypto.sublte.digest result in equivalent hex hashes for equal length strings?

时间:2015-07-08 15:49:05

标签: javascript hash cryptography sha256 webcryptoapi

The following code was adapted from these two sources:

http://qnimate.com/hashing-using-web-cryptography-api/

https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest

(function () {
    "use strict";

    var crypto = window.crypto || window.msCrypto;

    if (typeof crypto.subtle === "undefined") {
        return;
    }

    function convertStringToArrayBuffer (str) {
        var strLength = str.length, buffer = new ArrayBuffer(strLength), i = 0;
        while (i < strLength) {
            buffer[i] = str.charCodeAt(i);
            i += 1;
        }
        return buffer;
    }

    function convertBufferToHex (buffer) {
        var data = new DataView(buffer), i = 0, 
            dataLength = data.byteLength, cData = null,
            hexValue = '';

        while (i < dataLength) {
            cData = data.getUint8(i).toString(16);
            if (cData.length < 2) {
                cData = '0' + cData;
            }

            hexValue += cData;
            i += 1;
        }
        return hexValue;
    }

    function digest (str) {
        var buf = convertStringToArrayBuffer(str);

        return crypto.subtle.digest("SHA-256", buf).then(function (hash) {
            return convertBufferToHex(hash);
        });
    }

    window.sha256 = {
        "convertStringToArrayBuffer": convertStringToArrayBuffer,
        "convertBufferToHex": convertBufferToHex,
        "digest": digest
    };
}());

Using sha256.digest("this string").then(function (x) { console.log(x) } ); and sha256.digest("that strong").then(function (x) { console.log(x) } ); produce the same hex string when run in a Chrome or Firefox console.

In fact any two strings with the same length will have the same hex representation.

Everything I've read says that having two equivalent hashes is rare. Which means I'm doing something wrong here. I have no idea what that something is.

1 个答案:

答案 0 :(得分:2)

好的,我终于明白了。

根据MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer,您无法直接为ArrayBuffer指定值。

相反,你必须使用类似Uint8Array,Uint16Array,DataView等的东西来为ArrayBuffer赋值。

所以我改变了

function convertStringToArrayBuffer (str) {
    var strLength = str.length, buffer = new ArrayBuffer(strLength), i = 0;
    while (i < strLength) {
        buffer[i] = str.charCodeAt(i);
        i += 1;
    }
    return buffer;
}

function convertStringToArrayBuffer (str) {
    var strLength = str.length, buffer = new Uint8Array(strLength), i = 0;
    while (i < strLength) {
        buffer[i] = str.charCodeAt(i);
        i += 1;
    }
    return buffer;
}
瞧,瞧! :d

等长字符串不再具有匹配的哈希值。