Node.js 节点加密sha256不使用空格

Node.js 节点加密sha256不使用空格,node.js,cryptography,content-security-policy,jsdom,Node.js,Cryptography,Content Security Policy,Jsdom,我是做错了什么还是这是一个错误 使用时 var checkSum = crypto.createHash("sha256").update(scriptInnerHTML, "utf-8").digest("base64") 要为此脚本标记生成sha256,请执行以下操作: <script> console.warn("works"); var some code ... </script> 控制台。警告(“工作”); 一些代码。。。 并在内容

我是做错了什么还是这是一个错误

使用时

var checkSum = crypto.createHash("sha256").update(scriptInnerHTML, "utf-8").digest("base64")
要为此脚本标记生成sha256,请执行以下操作:

<script>

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

控制台。警告(“工作”);
一些代码。。。
并在内容安全策略中使用它,如下所示:

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

事情按照它应该的方式进行,但是这一个,除了没有警告日志之外,是完全相同的,不起作用。注意代码前面的两行新行和一个选项卡

<script>


    var some code ... 
</script>

一些代码。。。
如果后面有文本,节点对制表符(或者更确切地说是换行+制表符)的解释似乎有所不同。奇怪

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

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

示例:

(脚本标记位于底部)

工作哈希('sha256-5++3ItSu+9MacziuuuuxH60RG7EUGMibmmhxHwpsynan0='):

不工作哈希('sha256-hIRDHGUSaEmjNiVhNabY+8l4GNQdj/PXD4XHA21gdRM='):

已解决: 问题是由于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)..}.|
其对应的散列为
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=

你能把不起作用的例子贴在什么地方吗?这很可能是因为一些无关的空白字符,但很难在这里的帖子中发现。。。或者,你可以用一个来代替散列。对不起,我不明白。您从散列输入中删除了一个警告日志行,然后您会惊讶地发现它没有与包含警告行的散列进行比较?还是我看到了鬼?@MaartenBodewes抱歉-写得不好。哈希函数将为每个输入重新运行。@ewcz已用示例更新。谢谢!我使用JSDom来获取innerHTML,但为了更加确保,我还使用用于生成哈希的字符串来设置innerHTML。但也许JSDom正在使用空格进行神奇的转换,从而产生了这个bug…@Olof_t我在
JSDom
中包含了一个示例,它似乎给出了正确的哈希值。对于选择器,我使用了
head>script:last child
,即获取
head
中的最后一个
script
元素。问题在于调用dom.serialize()时,它删除了一个不必要的选项卡,这会更改源代码,从而导致哈希不匹配。无论如何:两百谢谢你帮了我这个忙!