我必须在不同平台和服务实现之间交换 JSON 对象,并通过数字签名验证其完整性。所以平台 A 会创建这样一个对象并创建数字签名。然后将所述签名包含到对象中并发送到平台 B。JSON 对象可以包含任意属性和数据。
例如在 PHP 中:
function signObject($jsonObjectToSign, $privateKey) {
$jsonObjectToSign->signature = "";
$msgToSign = json_encode($jsonObjectToSign);
openssl_sign($msgToSign, $jsonObjectToSign->signature, $privateKey, OPENSSL_SLGO_SHA1);
return $jsonObjectToSign;
}
问题是,例如在 Java 中,无法判断 JSON 对象的属性是否与您添加它们的顺序相同(通过 JSONObject.put())。所以,如果我做一个
$json = json_encode('{"a":1, "b":2}');
在 PHP 中,如上所述签署此对象,将其传输到基于 java 的服务器,解码 json 对象,然后尝试验证签名,我可能会得到对象属性的不同顺序。
所以我需要的是一种从 JSONObject 创建 String 的可靠方法,与使用的语言或平台无关。
上面的示例对象需要始终输出 {"a":1, "b":2}
而从不输出 {"b":2, "a":1}
。不幸的是,这是常见的情况,例如在 Java 中。
是否有任何以安全方式签署 JSON 对象的“最佳实践”?
但让我用另一种方式来描述这个问题:
假设我想用 Java(或任何其他语言)执行此操作:
JSONObject j = new JSONObject();
j.put("a", 1);
j.put("b", 2);
现在,我需要一个序列化函数,它始终为该对象输出相同的字符串表示形式,无论该对象是如何创建的以及使用何种语言创建的。
最佳答案
JSON 对象的签名和加密在 JOSE 规范套件中指定,其中 JOSE 代表 Javascript 对象签名和加密,请参阅 http://jose.readthedocs.org/en/latest/ JOSE 使用通过 JSON 对象的 base64url 编码表示计算的分离签名。签名不是 JSON 对象本身的一部分,因此不需要重新排序来验证它。
关于java - 签署 JSON 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31790802/