【译】如何为应用程序选择 JOSE / JWT 加密算法

2019-10-22  本文已影响0人  舌尖上的大胖

本文翻译自 How to select a JOSE / JWT cryptographic algorithm for your application

JOSE 即 JavaScript Object Signing and Encryption,已采用了一系列标准加密算法,包括新的 Edwards 曲线算法(2017年新增)。那么应该使用哪种算法来保护 JWT 或应用程序中的其他对象呢?本指南将提供一些基本准则,以便做出明智的选择。 但是,也请咨询该领域的文章,文献和专家,以仔细检查您的假设,并确保没有遗漏任何重要问题。

一、常见的数据安全关注点

我们保护数据(例如令牌)的需求通常来自一个或多个关注的问题:

选择合适的 JOSE 算法的第一步,是了解我们所关注的安全因素。

二、可用的 JOSE 算法类

JOSE 提供了三种截然不同的加密算法类,以解决四个安全问题,它们具有部分重叠的属性:

算法 完整性 真实性 不可抵赖性 保密性
HMAC
数字签名
认证加密

HMAC 算法:一种特殊的超高效哈希(HMAC),用于确保数据的完整性和真实性。 为了计算 HMAC,您需要一个密钥

数字签名:提供 HMAC 的特性,以及加密的不可否认性(使签名者以外的其他人可以检查签名的有效性)。 数字签名基于公钥/私钥密码术。 需要一对公钥/私钥(类型为 RSA,椭圆曲线(EC)或爱德华兹曲线八位密钥对(OKP))。

认证加密:在加密数据的同时,还确保其完整性和真实性(例如 HMAC)。 JOSE 通过公钥/私钥,秘密(共享)密钥和密码来提供加密。

1、基于哈希的消息认证码(HMAC)

对于令牌和其他需要向外发送或存储的信息,如果最终由颁发它的应用程序使用,那么 HMAC 算法(带有 JOSE alg 标识符 HS256,HS384 和 HS512)是理想的选择。

这里的主要关注点是确保:
1)当我们取回数据时数据的完整性,以及
2)数据实际上是由我们产生的。

示例 JWT 声明了无状态会话 Cookie:

{
  "sub"      : "user-12345",
  "email"    : "alice@wonderland.net",
  "login_ip" : "172.16.254.1", 
  "exp"      : 1471102267
}

一个常见的误解,是消息身份验证代码可以视为数字签名。 其实并不是! 这是因为验证的过程需要用到计算 HMAC 时使用的原始密钥,并且从本质上讲,该密钥不能与他人分享,因为不能让他人具备生成自己的 HMAC 的能力。 如果想要不可否认性,请使用 RSA,EC 或 EdDSA 签名

2、数字签名

数字签名适用于发行令牌、声明、断言和文档,且这些文档的完整性和真实性必须由其他各方进行验证的场景。

使用示例:
数字签名仅适用于公用/专用密钥:
选择哪种数字签名算法?

我们有 RSAECEdDSA 签名的 JWT 的示例。

3、认证加密

JOSE 通过以下方式提供加密:

JOSE 中的加密始终是经过身份验证的,这意味着密文的完整性受到保护,不会被篡改。 因此,经过身份验证的加密使 HMAC JWT 嵌套在 JSON Web 加密(JWE)中变得多余。 仅使用 JWE 加密。

JWE 加密是一个“两步”过程:

1、数据或内容始终使用 AES 密钥(称为内容加密密钥或 CEK)进行加密,并且每个 JWT / JWE 对象都使用不同的 CEK。 Nimbus 库将自动为您生成此 AES 密钥,并且其长度将取决于 enc(加密方法)标头参数(例如,"enc": "A128GCM" 将导致生成 128 位 AES 密钥)。 除了可以选择三种 AES 密钥长度(128、198 和 256)之外,JOSE 还支持两种内容加密模式:AxxxCBC-HSxxx 和 AxxxGCM。 通常,更广泛地支持 AxxxCBC-HSxxx 模式。

2、第二步是使用输入密钥(即您提供的秘密密钥,公共密钥或密码)对生成的 AES CEK 进行加密(也称为包装)。 这由 alg JWE 标头参数指定。 如果要跳过第二步,直接提供 AES CEK,请选择直接加密并指定 "alg": "dir" JWE 标头参数。

示例 JWE 标头,其中的内容在 GCM 模式下使用 128 位 AES 加密,而 AES CEK 本身使用公共 RSA 密钥加密(使用 RSA OAEP 加密):

{
  "alg" : "RSA-OAEP",
  "enc" : "A128GCM"
}

您可以查看使用 RSA 公钥加密 JWT 的示例

三、嵌套签名和加密

可以对签名的 JWT / JWS 对象进行附加加密,从而为数据提供完整性,真实性,不可否认性和机密性。

这是通过简单的嵌套实现的(请参见示例):

1、JWT 用专用的 RSA,EC 或 OKP 密钥签名。
2、然后,签名的 JWT 成为 JWE 对象的有效负载(纯文本),该JWE对象使用接收者的公钥(RSA,EC,OKP)或已在两方之间共享的秘密密钥进行加密。

处理嵌套的 JWT 向后工作:

1、使用适当的密钥(RSA,EC 或 OKP 的私钥或已建立的私钥)解密 JWE 对象。
2、然后将提取的有效负载(纯文本)解析为签名的 JWT,并使用发行者的公钥(RSA,EC 或 OKP)进行验证。

Nimbus JOSE + JWT 库提供了用于处理嵌套 JWT 的完整框架。

四、OpenID Connect 中的算法选择

通过以下规则,您可以了解在给定客户端注册后哪些 ID 令牌算法可行:
1、具有 client_secret 的客户端可以接收由 HMAC(其中 client_secret 充当 HMAC 秘密密钥)或签名(RSA,EC 或 EdDSA)保护的 ID 令牌。 为了验证 RSA,EC 或 EdDSA 签名的 ID 令牌,客户端仅需要(从其 JWK 设置 URL 中)检索 OpenID 提供程序的匹配公钥。

2、带有 client_secret 的客户端也可以接收加密的 ID 令牌,其中 client_secret 用于从中导出秘密 AES 密钥。

3、如果使用 HMAC,则要求的 client_secrets 必须足够长以适合所需的密钥长度。 例如,一个 256 位 client_secret 允许 HMAC 与 HS256 一起使用。

4、为了使客户端能够接收 RSAECDH 加密的 ID 令牌,它必须具备使用 OpenID 提供方注册的 RSA,EC 或 OKP 公钥。

5、OpenID Connect 还允许没有 client_secret 的客户端。 此类客户端需要向 OpenID 提供程序注册的 RSA,EC 或 OKP 公钥,并使用该密钥在令牌端点进行身份验证(通过 JWT)。 如上所述,可以将 ID 令牌加密为该公共密钥。

五、参考资料

(完)

上一篇 下一篇

猜你喜欢

热点阅读