繁体   English   中英

SHA256相同字符串的不同值

[英]SHA256 different values for same String

我正在生成以下字符串的SHA256

{
    "billerid": "MAHA00000MUM01",
    "authenticators": 
    [
        {
            "parameter_name": "CA Number",
            "value": "210000336768"
        }
    ],
    "customer": 
    {
        "firstname": "ABC",
        "lastname": "XYZ",
        "mobile": "9344895862",
        "mobile_alt": "9859585525",
        "email": "abc@billdesk.com",
        "email_alt": "abc2@billdesk.com",
        "pan": "BZABC1234L",
        "aadhaar": "123123123123"
    },
    "metadata": 
    {
        "agent": 
        {
            "agentid": "DC01DC31MOB528199558"
        },
        "device": 
        {
            "init_channel": "Mobile",
            "ip": "124.124.1.1",
            "imei": "490154203237518",
            "os": "Android",
            "app": "AGENTAPP"
        }
    },
    "risk":
    [
        {
          "score_provider": "DC31",
          "score_value": "030",
          "score_type": "TXNRISK"
        },
        {
          "score_provider": "BBPS",
          "score_value": "030",
          "score_type": "TXNRISK"
        }
    ]
}

我从不同来源获得不同的SHA256输出。 该网站: https ://www.freeformatter.com/sha256-generator.html#ad-output计算上述字符串的SHA256:053353867b8171a8949065500d7313c69fe7517c9d69eaff11164c35fcb14457

该网站( https://emn178.github.io/online-tools/sha256.html )给出SHA256为eae5c26759881d48a194a6b82a9d542485d6b6ce96297275c136b1fa6712f253

我正在Javascript中使用CryptoJs库来计算SHA256,这也将为eae5c26759881d48a194a6b82a9d542485d6b6ce96297275c136b1fa6712f253提供此结果。

我希望计算的SHA256为:053353867b8171a8949065500d7313c69fe7517c9d69eaff11164c35fcb14457

为什么这些在不同位置的SHA256计算不同?

您遇到的问题是由于编码差异。 编码相同字符串可能产生不同结果的原因有几个:

  • 不同的行尾(Windows为CR / LF,Linux为LF,经典MacOS为CR);
  • 空格的其他差异(制表符或空格,行尾的空格);
  • 不同的字符编码(Windows-1252,UTF-8和UTF-16或语言实现中的内部字符表示);
  • 元信息的存在(字节顺序标记的存在);
  • 处理编码中特殊字符的不同方式(一个字符后跟一个组合代字号和一个带有组合代字号的字符,请参见Unicode等价 );

可能还会出现看不见的错误,它们可能会产生不同的结果:

  • 存在无法打印的字符/控制代码(字符串末尾的空值0x00可能是最好的示例);

除了任何(结构化)文本可能存在的所有这些差异之外,JSON数据结构也可以具有等效的值。 最好的例子可能是数字前的前导+字符。 这完全是虚假的,但仍会导致不同的文本表示形式,但数字的值相同。


如果字符串的编码不同,则哈希算法的二进制输入也不同,对于普通的密码哈希,您将得到的结果相差约50%。 产生相同输入的方法称为规范化 (或C14N,因为规范化的C和N之间有14个字符)。

对于XML,很早以前就已经定义了规范形式 对于JSON并非如此,即使JSON的规范化要容易得多。 毕竟,JSON具有较少复杂的规则集。 有尝试规范化JSON的尝试,例如, 此RFC草案明确提到了加密哈希:

例如,当将加密哈希应用于JSON文档时,单个物理表示形式将允许哈希通过消除JSON内容编码方式的差异来表示文档的逻辑内容。

顺便说一下, 该RFC草案看起来更加详尽。


现在,您可以遵循RFC草案之一。 如果要保留换行符,则可以使用这些定义良好的规则序列化JSON,并将其用作哈希函数的输入,同时保持JSON本身不变。 这样, 格式不同 JSON仍会生成相同的哈希。

[Input JSON] -> (parse) -> (canonicalize & serialize) -> (hash) -> [hash value]
[Input JSON'] -> (parse) -> (canonicalize & serialize) -> (hash) -> [hash value']

如果“ Input JSON和“ Input JSON'在结构/语义上相同,则哈希输出将是相同的,因为规范化将消除差异。


请注意,JSON Web签名(JWS)侧解决了此问题。 签名毕竟在内部使用哈希。 签名位于包含的有效负载上,并且仅使用该有效负载的编码。 只要中间系统不重新编码JSON,就可以了。 签名不必相同,它们只需要验证数据即可。

不幸的是,哈希不是这种情况。 但是,实际上,您可以将JSON定义为文件并使用相同的推理。 缺点当然是, 如果得到差异,则必须执行二进制比较以找到差异,然后追溯引入更改的位置。 语义相同的工作系统可能会破坏哈希(例如,当替换或更新JSON库时)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM