节点加密 sha256 不适用于空格

Node crypto sha256 not working with whitespace

我是不是做错了什么或者这是一个错误?

使用时

var checkSum = crypto.createHash("sha256").update(scriptInnerHTML, "utf-8").digest("base64")

为此脚本标签生成 sha256:

<script>

    console.warn("works");
    var some code ... 
</script>

并像这样在 Content-Security-Policy 中使用它:

<meta http-equiv="Content-Security-Policy" content="script-src 'sha256-8O+YTKIDgMhMvSanTZx1Om5XY2ERB+kIxN8AcO2r6Ok='">

一切正常,但是这个除了没有警告日志外完全相同,但不起作用。请注意代码前的几行换行符和一个制表符。

<script>


    var some code ... 
</script>

如果后面有文本,Node 似乎会以不同的方式解释制表符(或者更确切地说是换行符+制表符)。奇怪!

在 Safari 和 Chrome 中都进行了测试,因此这应该不是浏览器问题。

更新: 我当然会为每个输入重新生成哈希。

示例:

(脚本标签在底部)

工作哈希('sha256-5++3ItSu+9maCZiuuXH60RG7EugmibMmhxhwpsynAn0='):http://aggressive.se/test/works.html

无效哈希('sha256-hIRDHGUSaEmjNiVhNabY+8l4GNQdj/PXD4XHA21gdRM='):http://aggressive.se/test/fail.html

已解决: 问题是由于 JSDom 中的 serialize() 函数,我用它在节点中生成 HTML。在计算哈希后调用 dom.serialize() ,它删除了一个不必要的选项卡,该选项卡更改了源(以一种很难注意到的方式)。

但如你所知,问题不是由节点或加密模块引起的。 (希望有人对此有用)

我不确定您是如何获得 scriptInnerHTML 变量的,但是如果我访问 fail.html 示例中感兴趣的脚本的 innerHTML 属性,我得到这个十六进制转储:

00000000  0a 0a 0a 09 76 61 72 20  6c 61 79 6f 75 74 20 3d  |....var layout =|
00000010  20 6e 65 77 20 41 67 67  72 65 73 73 69 76 65 4c  | new AggressiveL|
00000020  61 79 6f 75 74 28 29 3b  0a 09 41 67 67 72 65 73  |ayout();..Aggres|
00000030  73 69 76 65 4c 61 79 6f  75 74 2e 70 72 6f 74 6f  |siveLayout.proto|
00000040  74 79 70 65 2e 73 65 74  75 70 46 75 6e 63 74 69  |type.setupFuncti|
00000050  6f 6e 20 3d 20 66 75 6e  63 74 69 6f 6e 28 29 0a  |on = function().|
00000060  09 7b 0a 09 09 76 61 72  20 65 6c 65 6d 65 6e 74  |.{...var element|
00000070  20 3d 20 64 6f 63 75 6d  65 6e 74 2e 63 72 65 61  | = document.crea|
00000080  74 65 45 6c 65 6d 65 6e  74 28 22 64 69 76 22 29  |teElement("div")|
00000090  3b 0a 09 09 65 6c 65 6d  65 6e 74 2e 69 6e 6e 65  |;...element.inne|
000000a0  72 48 54 4d 4c 20 3d 20  22 49 74 20 77 6f 72 6b  |rHTML = "It work|
000000b0  73 22 3b 0a 09 09 74 68  69 73 2e 65 6c 65 6d 65  |s";...this.eleme|
000000c0  6e 74 73 2e 72 6f 6f 74  45 6c 65 6d 65 6e 74 2e  |nts.rootElement.|
000000d0  61 70 70 65 6e 64 43 68  69 6c 64 28 65 6c 65 6d  |appendChild(elem|
000000e0  65 6e 74 29 0a 09 7d 0a                           |ent)..}.|

对应的hash为bR9Os+NBLWNZ3/wFVRhBilP05u9OeSj0ABRo+T8QF+g=。如果我在 html 文件中使用这个散列,它似乎可以工作...

JSDOM的例子:

const fs = require('fs');
const crypto = require('crypto');
const { JSDOM } = require('jsdom');

const dom = new JSDOM(fs.readFileSync('./fail.html'));
const data = dom.window.document.querySelector('head > script:last-child').innerHTML;

console.log(crypto.createHash('sha256').update(data, 'utf-8').digest('base64'));
//bR9Os+NBLWNZ3/wFVRhBilP05u9OeSj0ABRo+T8QF+g=