安全序列化对象的通用算法

General algorithm to securely serialize objects

我需要序列化一个(可能很复杂 *)对象,以便我可以计算该对象的 MAC**。

如果您的消息是字符串,您可以简单地执行 tag := MAC(key, string) 并且如果 s1 != s2 然后 MAC(key, s1) != MAC(key, s2) 的概率非常高,而且在计算上很难找到 s1,s2 这样的MAC(k,s1) == MAC(k,s2).

现在我的问题是,如果您需要 MAC 一个可以包含对象数组和嵌套对象的非常复杂的对象而不是字符串,会发生什么情况:

JSON
最初我虽然只是使用 JSON 序列化可以做到这一点,但事实证明 JSON 序列化器不关心顺序所以例如: {b:2,a:1} 可以序列化为 {"b":2,"a":1}{"a":2,"b":1}.

URL参数
您可以在对键进行排序后将对象转换为 url 查询参数列表,因此例如 {c:1,b:2} 可以序列化为 b=2&c=1。问题是随着对象变得越来越复杂,序列化变得难以理解。示例:{c:1, b:{d:2}}
1.首先我们序列化嵌套对象:{c:1, b:{d=2}} 2.然后url对=符号进行编码:{c:1, b:{d%3D2}} 3.最终序列化为:b=d%3D2&c=1

如您所见,序列化很快变得不可读,虽然我还没有证明这一点,但我也觉得它不是很安全(即可以找到两条消息 MAC相同的值)

任何人都可以告诉我一个很好的序列化对象的安全***算法吗?

[*]:对象可以有嵌套对象和嵌套对象数组。不允许循环引用。例子: {a:'a', b:'b', c:{d:{e:{f:[1,2,3,4,5]}}, g:[{h:'h'},{i:'i'}]}}

[**]:此 MAC 将通过网络发送。我不知道服务器支持什么languages/frameworks,所以像Java对象序列化这样的特定语言解决方案是不可能的。

[***]:在此上下文中安全意味着给定消息 abserialize(a) = serialize(b) 意味着 a = b

编辑:我刚刚通过this link 发现了SignedObject。是否有与语言无关的等价物?

您正在寻找的是 规范表示,或者用于数据存储本身,或者用于应用 MAC 算法之前的预处理。一种广为人知的格式是用于 XML 签名的规范化。 XML 签名的草案 2.0 版本似乎也包括 HMAC。请注意,创建 XML 签名的安全验证充满了危险 - 不要让自己受骗而相信已签名的文档本身。

至于 JSON,似乎有一个规范的 JSON 草案,但我看不到它的状态或是否有任何兼容的实现。 Here 是出现相同问题的 Q/A(用于散列而不是 MAC)。所以似乎没有完全标准化的方法。

在二进制中有 ASN.1 DER 编码,但您可能不想深入了解它,因为它非常复杂。


当然,您始终可以定义自己的二进制或文本表示,只要有一个 语义相同的数据集表示即可。在文本表示的情况下,您仍然需要定义特定的字符编码(建议使用 UTF-8)以将表示转换为字节,因为 HMAC 仅采用二进制输入。