如何encryption散列JSON对象?

下面的问题比起来看起来要复杂得多。

假设我有一个任意的JSON对象,可以包含任何数量的数据,包括其他嵌套的JSON对象。 我想要的是JSON数据的encryption散列/摘要,而不考虑实际的JSON格式本身(例如:忽略JSON令牌之间的换行符和间距差异)。

最后一部分是一个需求,因为JSON将由许多不同平台上的各种(de)序列化器生成/读取。 我知道至less有一个用于Java的JSON库,它在反序列化过程中读取数据时完全消除了格式化。 因此,它将打破哈希。

上面的任意数据子句也使事情复杂化,因为它阻止了我按照给定的顺序接收已知的字段,并在hasing之前将它们连接起来(大致思考Java的非encryptionhashCode()方法是如何工作的)。

最后,将整个JSONstring散列为一个字节块(在反序列化之前)也是不可取的,因为在计算散列时应该忽略JSON中的字段。

我不确定这个问题有很好的解决方法,但是我欢迎任何方法或想法=)

在允许灵活性的任何数据格式计算散列值时,这个问题是常见的。 为了解决这个问题,你需要规范化表示。

例如,Twitter和其他服务用于身份validation的OAuth1.0a协议需要安全散列请求消息。 为了计算哈希,OAuth1.0a说,你需要先将字段按字母顺序排列,用换行符分隔,删除字段名(众所周知),并使用空行作为空值。 签名或散列是根据该规范化的结果计算的。

XML DSIG的工作原理是一样的 – 在签名之前,您需要对XML进行规范化。 有一个提议的W3标准覆盖这个 ,因为这是一个签名的基本要求。 有人把它叫做c14n。

我不知道json的标准化标准。 这是值得研究的。

如果没有一个,你肯定可以为你的特定应用程序使用build立一个约定。 合理的开始可能是:

  • 按字母顺序排列名称的属性
  • 在所有名字上使用双引号
  • 所有string值都使用双引号
  • 名称和冒号之间,冒号和值之间没有空格或一个空格
  • 值和下面的逗号之间没有空格
  • 所有其他的空白空间折叠到一个空间或没有任何东西 – select一个
  • 排除您不想签名的任何属性(例如,拥有签名本身的属性)
  • 用您select的algorithm签名结果

您可能还想考虑如何在JSON对象中传递该签名 – 可能会build立一个众所周知的属性名称,如“nichols-hmac”或其他,它会获得散列的base64编码版本。 这个属性必须被哈希algorithm明确排除。 然后,JSON的任何接收者将能够检查散列。

规范化的表示forms不需要是在应用程序中传递的表示forms。 只需要给定一个任意的JSON对象就可以轻松生成。

而不是发明自己的JSON规范化/规范化,你可能想要使用bencode 。 在语义上,它与JSON(数字,string,列表和字典的组合)相同,但具有密码散列所必需的明确编码的属性。

bencode被用作torrent文件格式,每个bittorrent客户端都包含一个实现。

JSON-LD可以做normalization。

你将不得不定义你的上下文。

这与导致S / MIME签名和XML签名问题的问题相同。 也就是说,要签名的数据有多个等价的表示。

例如在JSON中:

 { "Name1": "Value1", "Name2": "Value2" } 

 { "Name1": "Value\u0031", "Name2": "Value\u0032" } 

或者根据您的应用程序,这甚至可能是相同的:

 { "Name1": "Value\u0031", "Name2": "Value\u0032", "Optional": null } 

规范化可以解决这个问题,但这是一个你根本不需要的问题。

如果你能控制规范,简单的解决scheme是将对象包装在某种容器中,以防止它被转换成“等价”但不同的表示。

即通过不签署“逻辑”对象,而是通过签名特定的序列化表示来避免这个问题。

例如,JSON对象 – > UTF-8文本 – >字节。 将字节标记为字节 ,然后将其作为字节传输例如通过base64编码。 由于您正在对字节进行签名,所以像空格之类的差异是签名的一部分。

而不是试图做到这一点:

 { "JSONContent": { "Name1": "Value1", "Name2": "Value2" }, "Signature": "asdflkajsdrliuejadceaageaetge=" } 

只要这样做:

 { "Base64JSONContent": "eyAgIk5hbWUxIjogIlZhbHVlMSIsICJOYW1lMiI6ICJWYWx1ZTIiIH0s", "Signature": "asdflkajsdrliuejadceaageaetge=" } 

即不签名的JSON,签署编码的 JSON 的字节

是的,这意味着签名不再透明。

我会按给定的顺序做所有的字段(例如按字母顺序)。 为什么随意的数据有所作为? 你可以迭代属性(alareflection)。

或者,我会考虑将原始jsonstring转换成一些定义良好的规范forms(删除所有superflous格式) – 哈希。