3

在 JavaScript 和 Python 中,一致地散列仅限于 JSON 可以表示的对象/字典的最佳方法是什么?在许多不同的语言中呢?

当然,在许多不同的语言中都有一致地实现的哈希函数接受一个字符串,但是要对一个对象进行哈希处理,您必须首先将其转换为字符串表示形式。

我想要一个哈希函数,它总是为任何语言的同一个字典返回相同的值,但是 JSON 规范不保证序列化表示中键的顺序。

json.dumps()JSON.stringify()行为相同吗?您将如何验证这一点?

如果没有,是否有一种包含多种语言库的序列化格式(我实际上对 Python 和 JavaScript 感兴趣,但也对所有语言感到好奇),不需要调用者进行任何额外的处理来产生一致的结果?

4

3 回答 3

4

我会把它分成两个问题。

  1. 如何在 JavaScript 和 Python 中获得相同的序列化字符串?
  2. 您应该使用哪个字节数组散列函数?它必须是在 JavaScript 和 Python 中具有相同实现的既定算法。

使用 (1) 获取两个字符串,然后使用 UTF8 编码,然后使用 (2) 获取哈希。

由于(2)很简单,我将只解决(1)。

确保您生成的两个 JSON 字符串相同的问题涉及多个方面。

  • 您需要使用未格式化的 JSON(没有多余的空格、制表符或换行符)。
  • null 值必须被同等对待。如果值为 null,则某些序列化程序默认会丢弃字典键值对。
  • 字典中键值对的顺序必须一致。
  • JSON数字序列化应该是一致的。例如,您不能将整数一个序列化为1 一侧和另一侧1.0。(不过,这可能不是什么大问题。)
  • 两者的字符串编码应该相同。JSON 允许序列化为 Unicode 文本,仅强制要求"\在 JSON 字符串中进行反斜杠转义。然而,大多数序列化程序做得比必要的更多,并且将几乎所有 Unicode 字符都减少到\uXXXX等价物。有关 JSON 字符串编码的详细信息,请参阅json.org。消除所有歧义的一种方法是仅在绝对必要时才逃避。

您需要确保所有这些都在 JavaScript 和 Python 之间匹配。我使用的大多数 JSON 序列化库都为上面列表中提到的所有内容提供了配置挂钩。不幸的是,我对 JavaScript 或 Python 库不是很熟悉。

于 2013-11-08T05:14:45.873 回答
0

JSON 是一种定义明确的语言,用于表示对象的状态。这些函数的行为并不相同,但它们的行为确实相同

例如:

json.dumps({'hello':'goodbye', 123: 456})

可能产生:

{"hello":"goodbye", "123": 456}

或者

{"123": 456, "hello":"goodbye"}

如果您传入indent参数,那么您将获得更多不同结果的可能性。

大多数语言如果还没有内置的方式来处理 JSON(例如 Python 和 JS),那么他们将拥有一个完全足够的 3rd 方实用程序(请参阅 Newtonsoft JSON library for .NET)

我知道的每种语言都会生成有效的 JSON,这意味着它可以被提供 JSON 解析器的其他语言解析。

于 2013-11-08T05:14:00.043 回答
0

我想我可以尝试一个实际的例子。

在javascript中我做了:

import stringify from 'json-stable-stringify'
import sha256 from 'simple-sha256'

hash_str = sha256(stringify({'hello':'goodbye', '123': 456}))
// hash_str = 72804f4e0847a477ee69eae4fbf404b03a6c220bacf8d5df34c964985acd473f

json-stable-stringify保证排序的 json。sha256允许 nodejs / 浏览器兼容性。

在 python 3.8 中,我做了:

import hashlib
import json

hash_str = hashlib.sha256(json.dumps({'hello':'goodbye', '123': 456}, sort_keys=True, separators=(',', ':')).encode("utf-8")).hexdigest()
# hash_str = 72804f4e0847a477ee69eae4fbf404b03a6c220bacf8d5df34c964985acd473f

我还没有进行广泛的测试,但是使用我尝试过的 json 对象,它已经成功匹配。

于 2021-04-13T13:10:12.150 回答