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

【译】如何为应用程序选择 JOSE / JWT 加密算法_第1张图片

本文翻译自 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)

  • 功能:完整性、认证
  • JOSE 格式:JSON Web Signature(JWS)
  • 秘钥类型:密码
  • 算法:HMAC with SHA-2
    • HS256
    • HS384
    • HS512
  • 用例:
    • 存储在浏览器 Cookie 中的无状态会话
    • 电子邮件验证码
    • 会话 ID 能够区分过期 ID 和无效 ID
    • Token 的颁发者最终用户是==同一角色==
  • 备注
    • HMAC 不是数字签名!
    • 使用更长的密钥/哈希(例如 HS512 )以提高安全性
    • 长于哈希大小的密钥不能提供额外的安全性

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

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

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

{
  "sub"      : "user-12345",
  "email"    : "[email protected]",
  "login_ip" : "172.16.254.1", 
  "exp"      : 1471102267
}

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

2、数字签名

  • 功能:完整性、认证、不可抵赖性

  • JOSE 格式:JSON Web Signature(JWS)

  • 秘钥类型:公钥/私钥对

    • RSA
    • EC
    • OKP
  • 算法

    • RSA signature with PKCS #1 and SHA-2

      • RS256
      • RS384
      • RS512
    • RSA PSS signature with SHA-2

      • PS256
      • PS384
      • PS512
    • EC DSA signature with SHA-2

      • ES256
      • ES384
      • ES512
    • Edwards-curve DSA signature with SHA-2

      • Ed25519
      • Ed448
  • 用例

    • ID tokens (OpenID Connect)
    • Self-contained access tokens (OAuth 2.0)
    • 在域之间传递安全性断言和令牌
    • 需要必须由其他人验证数据的完整性和真实性的场景
  • 备注

    • 私钥一定要保密!
    • 推荐的 RSA 密钥大小为 2048 位
    • EdDSA 签名提供最佳性能

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

使用示例:
  • 由 OpenID 提供者发行的身份令牌,依赖方需要对其进行验证才能登录用户。
  • 由 OAuth 2.0 服务器发出的访问令牌,资源服务器 / Web API 必须在提供请求之前对其进行验证。
数字签名仅适用于公用/专用密钥:
  • 颁发者需要先生成 公钥/私钥对,然后才能对 JWT 或其他对象进行签名。
  • 签名是用私钥计算的,私钥必须始终保持安全,否则会有冒充的风险。
  • JWT 或 JWS 对象的签名需要使用公钥验证。接收者发现和下载公钥的方法是特定于应用程序的。 例如,OpenID Connect 服务器在 JWK 格式的 URL 上发布其公钥。
选择哪种数字签名算法?
  • 如果您需要广泛的支持,请选择 RS256。 该算法基于 RSA PKCS#1,它仍然是公钥/私钥密码术使用最广泛的标准。 任何足够好的 JWT 库都应支持它。 RSxxx 签名也花费很少的 CPU 时间进行验证(有助于确保在资源服务器上快速处理访问令牌)。 推荐的 RSA 密钥长度为 2048 位。

  • ESxxx 签名算法使用椭圆曲线(EC)加密。 它们需要较短的密钥,并且产生较小的签名(相当于 RSA 强度)。 但是,EC 签名有一个缺点:它们的验证速度很慢。

  • 新的 Edxxx 算法提供了最佳的签名/验证性能组合。 特别是通过 P-265 曲线签名,比2048 位 RSA 高 62 倍,比 EC DSA 高 14 倍。

我们有 RSA,EC 和 EdDSA 签名的 JWT 的示例。

3、认证加密

  • 功能:机密性、完整性、认证

  • JOSE 格式:JSON Web Encryption(JWE)

  • 秘钥类型:

    • Public / private key pair:
      • RSA
      • EC
      • OKP
    • Secret (shared) key
    • Password
  • 算法

    • 公钥/私钥加密

      • RSA
        • RSA OAEP
          • RSA-OAEP
          • RSA-OAEP-256
        • RSA PKCS #1
      • EC
        • ECDH-ES with EC or OKP key
          • ECDH-ES
          • ECDH-ES+A128KW
          • ECDH-ES+A192KW
          • ECDH-ES+A256KW
    • 秘密(共享)密钥加密

      • Direct AES encryption
        • dir
      • AES key wrap
        • A128KW
        • A192KW
        • A256KW
      • AES GCM key encryption
        • A128GCMKW
        • A192GCMKW
        • A256GCMKW
    • 基于密码加密

      • PBES2
        • PBES2-HS256+A128KW
        • PBES2-HS384+A192KW
        • PBES2-HS512+A256KW
  • 用例

    • 签名和加密的ID令牌(OpenID Connect)
    • 签名并加密的自包含访问令牌(OAuth 2.0)
    • 加密的文档和数据,具有完整性和真实性检查
  • 备注

    • 保持私钥和私钥的安全!
    • 推荐的 RSA 密钥大小为 2048 位

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

  • 如果您想自己加密数据,请使用密钥。 如果秘密密钥是与其他方共享的(通过某种带外方式),则他们也可以使用它来加密数据/解密密文。 请查看上表,了解可用的密钥加密算法。

  • 收件人提供的公共密钥(RSA,EC 或 OKP)。 例如,OpenID Connect 提供程序以可发现的 URL 以 JWK 格式发布其公共密钥。 接收者然后可以使用其匹配的私钥解密 JWT / 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 令牌加密为该公共密钥。

五、参考资料

  • How to select a JOSE / JWT cryptographic algorithm for your application

  • 基于JWE的API加密方案设计

(完)

你可能感兴趣的:(【译】如何为应用程序选择 JOSE / JWT 加密算法)