IETF JOSE 工作组 [1] 已经开始对 JSON Web 签名(一种向 JSON 添加签名的方法)进行标准化。
初稿
我的名字在这里被提及,因为我将 OpenID 基金会 AB/C 工作组正在考虑的想法带到了 IETF[2]。
@ritou 说,“OAuth 2.0时代的签名请求是什么?“正如条目中提到的,Facebook 签名请求 非常类似于
最大的区别是signed_request
签名.正文
而在 JWS 中,
标头. 正文. 签名
这是有原因的。
为什么是“header.body.signature”?
有些人可能会认为我们应该效仿全球领导者 Facebook,但我们采用这种形式是有充分理由的。
为什么标题是分开的?
对于signed_request,签名参数包含在消息正文中。如果您要加密消息正文,则无法使用此方法,因为用于解密消息的参数也会被加密。因此,您需要将这些与加密相关的参数分离到标头部分中。
JWS 尝试与 JWE 有尽可能多的共同点,这就是为什么需要分离标头的原因。
为什么签名在最后?
外观上的另一个巨大差异是,在signed_request中,签名位于开头,而在JWS中,签名位于结尾。在JWS中,签名位于结尾,以便流式传输签名创建过程。这是因为,如果您尝试在开头添加签名,则所有数据都必须缓冲,直到签名过程完成,然后在签名完成后以“signature.body”的形式发送出去;而如果您将签名放在结尾,数据可以逐个发送,因此无需缓冲所有数据,这对服务器资源更“友好”。如果只签名非常小的数据片段(例如在signed_request中),则区别不大,但由于JWS可能会签名大量数据,因此已考虑到这一点。
共同特征
singed_request 和 JWS 有一些共同的特性,最典型的有:
- 不进行数据规范化
- 使用base64url进行序列化
- 使用 JSON 作为数据格式。
- 任何数据都可以签名
不进行数据规范化
XML 数字签名 (XML Digital Signature) 是一个标准,它非常灵活且通用。然而,有人认为它在不同实现之间的兼容性较差,因此不受许多开发者的青睐。造成这种情况的最大原因似乎是 XML 数据的规范化。为了避免这个问题,signed_request 和 JWS 均未执行任何规范化操作,而是直接使用原始数据。
使用base64url进行序列化
经常有人问我为什么使用 base64url 而不是 base64。答案是 base64url 包含一些非 Web 安全字符,例如“=”。JWS 会插入 HTTP 标头以及 GET 和 POST 参数中。在这种情况下,最好不要用“=”填充,而不是每次都转义“=”。
使用 JSON 作为数据格式
我们使用JSON而不是XML的原因是它更加紧凑,处理性能更好,最重要的是更受开发人员的欢迎。
任何数据都可以签名
虽然这是一种签署 JSON 的方法,但您只需将 base64url 编码的数据输入到其中一个 JSON 参数中即可签署任何数据。
谁使用 JWS?
我希望你能理解为什么会有这样的区别。但你可能会想:“如果Facebook不使用它,那还有什么意义呢?” 以下是我的答案:
首先,Facebook 并非决定不再使用它。他们只是对当前的signed_request感到满意,认为没有必要将JWS用于此目的。他们可能会将其用于其他用途。此外,如果JWS最终变得更加普及,那么“开发者友好型”的Facebook是否有可能增加对它的支持?
即使 Facebook 不使用它,预计许多其他公司也会使用它。目前,这些公司包括微软、谷歌、Salesforce、AOL 和 eBay。
我什么时候应该回应?
我认为 JWS 相对来说比较成熟。事实上,Google、eBay 和其他公司都已经实现了它。所以,如果你不介意一些改动,我认为现在就开始遵循它是个好主意 [3]。如果你有签名需求,请考虑使用 JWS。
[1] 与此同时,一种名为 JSON Web 加密的加密标准化工作已经开始。
[2] 由于它可用于通用目的,而不仅仅是 OpenID Connect 等身份标准,我们决定在 IETF 上对其进行标准化。其他以类似方式引入的规范包括 JSON Web Token 和 Simple Web Discovery。
[3] 与此同时,JWE 即将进行一些改进。具体来说,我们将添加完整性检查,并将其作为使用 CBC 模式时的必需操作。因此,在下一个版本发布之前,

对半结构化数据进行规范化是不是个坏主意?我想对它进行规范化,得到一个哈希值,以便快速比较 JSON 对象是否匹配,但是……