NodeJS中crypto-js生成的MD5哈希与bash md5sum结果不一致问题
问题原因
- 你执行的两个操作本质是对完全不同的内容计算哈希,结果必然不一致:
- bash的
md5sum计算的是file.json的原始文件二进制内容的哈希,包含所有缩进、换行、空格、文件末尾换行符、原始的键顺序等格式细节 - JS代码中先通过
require把JSON解析为JS对象,再用JSON.stringify序列化得到的字符串,和原文件内容差异极大:JSON.stringify默认会去掉原文件的自定义缩进、调整部分键的顺序、忽略多余的逗号,输出结果和原文件内容没有必然一致性
- bash的
- 你之前尝试的修改编码、直接对JS对象算哈希都没有解决核心的「输入内容不一致」问题,所以不会生效
解决方法
场景1:需要计算JSON文件本身的哈希(和md5sum结果对齐)
不要解析JSON,直接读取文件原始内容计算哈希,推荐使用Node内置crypto模块实现:
const fs = require('fs'); const crypto = require('crypto'); // 直接读取文件原始二进制内容计算哈希 const fileRaw = fs.readFileSync('/path/to/file.json'); const md5 = crypto.createHash('md5').update(fileRaw).digest('hex'); console.log(md5);
如果必须使用crypto-js,代码如下:
const Crypto = require("crypto-js"); const fs = require('fs'); const fileRawStr = fs.readFileSync('/path/to/file.json', 'utf8'); const md5 = Crypto.MD5(fileRawStr).toString(); console.log(md5);
场景2:需要计算JSON逻辑内容的哈希(只要键值对一致就算相同,忽略格式差异)
需要在JS和bash两端统一序列化规则,保证相同逻辑的JSON内容序列化后的字符串完全一致:
- JS端序列化时固定键顺序、缩进规则:
const Crypto = require("crypto-js"); const jsonFile = require('path/to/file.json'); // 按字母序排序键,固定缩进为2空格,保证序列化结果稳定 const stableJsonStr = JSON.stringify(jsonFile, Object.keys(jsonFile).sort(), 2); const md5 = Crypto.MD5(stableJsonStr).toString(); console.log(md5);
- bash端用jq做相同规则的格式化后再计算哈希:
cat /path/to/file.json | jq --sort-keys '.' | md5sum
内容的提问来源于stack exchange,提问作者Ress。
相关产品推荐
相关产品推荐

