如何在json对象上隐密散布?
-
10-10-2019 - |
题
以下问题比最初看起来更复杂。
假设我有一个任意的JSON对象,一个对象可能包含任何数量的数据,包括其他嵌套JSON对象。我想要的是JSON数据的加密哈希/摘要,而无需考虑实际的JSON格式(例如:忽略Newlines和JSON令牌之间的差异)。
最后一部分是一个要求,因为JSON将由许多不同平台上的多种(DE)序列化生成/阅读。我知道至少有一个用于Java的JSON库,可以在读取数据期间完全删除格式化。因此,它将打破哈希。
上面的任意数据子句也使事物复杂化,因为它阻止了我在给定顺序中采用已知字段并在建立之前将其连接起来(大致思考Java的非晶型hashcode()方法如何工作)。
最后,将整个JSON字符串作为一个字节(在进行挑选之前)的一部分也不是可取的,因为在计算哈希时,JSON中有一些字段应被忽略。
我不确定是否有一个很好的解决方案,但我欢迎任何方法或想法=)
解决方案
当允许灵活性的任何数据格式计算哈希时,这个问题是一个常见的问题。要解决这个问题,您需要 规范化 表示。
例如,Twitter和其他服务用于身份验证的OAUTH1.0A协议需要安全的邮件。要计算哈希,OAuth1.0A说您需要首先将字段标准化字段,用新线分开,删除字段名称(众所周知),然后使用空白行进行空值。根据规范化的结果计算签名或哈希。
XML DSIG以相同的方式工作 - 您需要在签名之前对XML进行规范化。有一个 建议的W3标准涵盖此, ,因为这是签名的基本要求。有人称其为C14N。
我不知道JSON的规范化标准。值得研究。
如果没有一个,您当然可以为您的特定应用程序使用限制。合理的开始可能是:
- 词典按名称对属性进行分类
- 所有名称都使用的双引号
- 在所有字符串值上使用的双引号
- 名称与结肠之间以及结肠和价值之间没有空间或一个空间
- 值和以下逗号之间没有空间
- 所有其他白空间都崩溃到一个空间或什么都没有 - 选择一个空间
- 排除您不想签名的任何属性(一个例子是,保存签名本身的属性)
- 用您选择的算法签署结果
您可能还想考虑如何在JSON对象中传递该签名 - 可能会建立一个众所周知的属性名称,例如“ Nichols-Hmac”或其他内容,这些名称获得了Hash的Base64编码版本。该属性必须被哈希算法明确排除。然后,JSON的任何接收器都可以检查哈希。
规范化表示不需要是您在应用程序中传递的表示。只需考虑一个任意的JSON对象,它只需要轻松地产生。
其他提示
而不是发明自己的JSON归一化/规范化,您可能需要使用 Bencode. 。从语义上讲,它与JSON(数字,字符串,列表和dicts的组成)相同,但具有密码散布所必需的明确编码的属性。
Bencode用作洪流文件格式,每个Bittorrent客户端都包含一个实现。
这是相同的问题,与S/MIME签名和XML签名有关。也就是说,要签署的数据有多个等效表示。
例如在JSON中:
{ "Name1": "Value1", "Name2": "Value2" }
VS.
{
"Name1": "Value\u0031",
"Name2": "Value\u0032"
}
或取决于您的申请,这甚至可能是等效的:
{
"Name1": "Value\u0031",
"Name2": "Value\u0032",
"Optional": null
}
规范化可以解决这个问题,但这是您根本不需要的问题。
简单的解决方案,如果您对规范有控制权,则将对象包裹在某种容器中,以保护其免于被转换为“等效”但不同的表示。
IE不签署“逻辑”对象,而是签署其特定的序列化表示形式来避免问题。
例如,JSON对象 - > UTF -8文本 - >字节。签名字节 作为字节, ,然后传输它们 作为字节 例如,通过base64编码。由于您正在签署字节,因此诸如Whitespace之类的差异是签名的一部分。
而不是尝试这样做:
{
"JSONContent": { "Name1": "Value1", "Name2": "Value2" },
"Signature": "asdflkajsdrliuejadceaageaetge="
}
只要这样做:
{
"Base64JSONContent": "eyAgIk5hbWUxIjogIlZhbHVlMSIsICJOYW1lMiI6ICJWYWx1ZTIiIH0s",
"Signature": "asdflkajsdrliuejadceaageaetge="
}
即不要签署JSON,签名 编码的字节 JSON。
是的,这意味着签名不再是透明的。
json-ld 可以做正常的。
您将必须定义您的上下文。
RFC 7638:JSON Web键(JWK)Thumbprint包括一种规范化。尽管RFC7638预计会员集有限,但我们将能够为任何成员应用相同的计算。
我将按给定顺序(例如,按字母顺序排列)进行所有字段。为什么任意数据有所作为?您可以在属性(ALA反射)上迭代。
另外,我将考虑将原始的JSON字符串转换为一些定义明确的规范形式(删除所有多余的格式),然后将其放置。
我们遇到了Hashing JSON编码有效载荷的简单问题。在我们的情况下,我们使用以下方法:
- 将数据转换为JSON对象;
- 在base64中编码JSON有效载荷
- 消息摘要(HMAC)生成的base64有效载荷。
- 传输基本64有效载荷。
使用此解决方案的优点:
- Base64将为给定有效载荷产生相同的输出。
- 由于所得的签名将直接从基本64编码的有效载荷派生,并且由于端点之间将交换Base64-Payload,因此我们将确定将维护签名和有效负载。
- 该解决方案解决了由于特殊字符的编码差异而引起的问题。
缺点
- 有效载荷的编码/解码可能会增加开销
- 基本64编码的数据通常比原始有效载荷大30+%。