程序印象

JSON Web Token

2018/06/20 Share

JSON Web Token (JWT) 介绍

定义 RFC7519,对于 JWT Token 的签名和验证,可以使用在线资源 https://jwt.io/,该网站也列出了各种语言层面支持的Libraries。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#base64UrlEncode(header) + "." + base64UrlEncode(payload) + "." + base64UrlEncode(signature)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

# => header
{
"alg": "HS256",
"typ": "JWT" # JWT or JWE
}
# body => claims
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
# signature
IJDŽIHNJ(]Olj~:N%VB˰倀

一个 JWT Token 包含3个部分的内容,各个部分之间采用 “.” 分割,每个部分采用 。

  1. Header,用于指示加密的算法和Token的类型
  2. Playload,数据主体
  3. Signature,数据的签名,用于验证数据部分的完整性

JOSE: JSON Object Signing and Encryption Library

JWT 协议中定义的公共 Claim 名称:

  1. “iss” (Issuer)
  2. “sub” (Subject)
  3. “aud” (Audience)
  4. “exp” (Expiration Time)
  5. “nbf” (Not Before)
  6. “iat” (Issued At)
  7. “jti” (JWT ID)

常用签名算法

  • HMAC 是当前最常见的签名算法,通过使用 Hash-X 函数和密钥生成摘要,用于验证数据完整性和消息认证,加密强度取决于底层哈希函数的密码强度,哈希输出的大小以及密钥的大小和质量。HMAC 使用两次散列计算。 密钥首先用于派生两个密钥 - 内部密钥和外部密钥。 算法的第一遍产生一个从消息和内部密钥导出的内部哈希。 第二遍产生从内部哈希结果和外部密钥导出的最终 HMAC 代码。 因此该算法对长度扩展攻击提供了更好的免疫性。

    以下定义来自于 RFC 2104

    H 表示 Hash 算法,比如 SHA-256

    K 表示密钥

    K’ 从 K 衍生出来的密钥(短于分块大小则补0,长于则使用Hash)

    ⊕ 表示 XOR

    opad 表示 外圈的填充, 一个块大小的常量 0x5c5x…5c5c

    ipad 表示内圈的填充,一个块大小的常量 0x3636…3636

    || 表示连接

以下内容主要来自于: What is the difference between the RSA, DSA, and ECDSA keys that ssh uses?

  • RSA (Rivest–Shamir–Adleman)) 是第一个公钥密码系统,广泛用于安全数据传输。它的安全性依赖于整数因子分解,所以不需要安全的RNG。与 DSA 相比,RSA 在签名验证方面速度更快,但生成速度更慢公钥加密标准(Public Key Cryptography Standards, PKCS)参见 公钥密码学标准
  • RSA-PSSRSA Probabilistic Signature Scheme)PSS 概率签名方案是由Mihir Bellare和Phillip Rogaway设计的加密签名方案。RSA-PSS是对其工作的改编,并且作为 PKCS #1 v2.1 的一部分进行了标准化。 通常,RSA-PSS应该用作 RSA-PKCS #1 v1.5的替代品。
  • DSA (Digital Signature Algorithm) 是数字签名的联邦信息处理标准。它的安全性依赖于离散的对数问题。与RSA相比,DSA 生成签名的速度更快,但验证速度更慢。如果使用错误的数字发生器,安全性可能被破坏。从 OpenSSH 7.0 开始,默认情况下,SSH不再支持DSA密钥(ssh-dss)。 按照SSH标准(RFC 4251及其后续版本),用于无处不在的DSA密钥(A DSA key used to work everywhere, as per the SSH standard (RFC 4251 and subsequent).)。
  • ECDSA (Elliptical curve Digital Signature Algorithm) 是 DSA(数字签名算法)的椭圆曲线实现。椭圆曲线密码术能够提供与RSA相同级别的安全级别,而且密钥更小。它没有避免 DSA 对坏 RNG 敏感的缺点。在 OpenSSH v5.7 中引入)在计算上比 DSA 轻量,但除非您的计算机处理能力非常低,否则这种差异并不明显。
  • EdDSA (Edwards-curve Digital Signature Algorithm) 是一种基于Twisted Edwards曲线使用 Schnorr 签名变体的数字签名方案。签名创建在 EdDSA 中是确定性的,并且其安全性基于某些离散对数问题的难处理性,所以它比DSA 和ECDSA 更安全,DSA 和 ECDSA 对每个签名都要求高质量的随机性。

算法选择

如果 Ed25519 能够比较好的支持的话(比如多语言)等,则选择 Ed15519,因为无论是从加密算法安全性和性能上都比较好。

如果不支持 Ed 25519,则可以选择 RSA 2048 或者 4096

Ed25519 在当前比较主流的 JWT 库中基本都没有提供支持,需要自己扩展。

Go

go语言中 ed25519 已经支持,参见库 golang.org/x/crypto/ed25519

热门 jwt 相关库:暂时都不支持 ed25519

  • dgrijalva/jwt-go 支持 HMAC SHA, RSA, RSA-PSS, ECDSA, 当前版本 4.0.0, 比较活跃 Star 3678
  • SermoDigital/jose 支持 HMAC SHA, RSA, RSA-PSS, ECDSA 当前版本 1.1.0 中等活跃 Star 604
  • square/go-jose 支持 HMAC SHA, RSA, RSA-PSS, ECDSA 当前版本 2.1.6 比较活跃 Star 884

Node

对于 ed25519 Node的实现参见 dazoe/ed25519 活跃度不高

  • jsonwebtoken 支持 HMAC SHA, RSA, RSA-PSS, ECDSA 当前版本 8.3.0 比较活跃 Star 7860

Java

对于 ed25519, java支持的库有 str4d/ed25519-java k3d3/ed25519-java ed25519 ed25519-java 等,活跃度都不高

  • auth0/java-jwt 支持 HMAC SHA, RSA, RSA-PSS, ECDSA Star 1869
  • jwtk/jjwt 支持 HMAC SHA, RSA, RSA-PSS, ECDSA Star 3267

相关知识

两种基本方式: Diffie-HellmanElliptic Curve Diffie-Hellman,以下章节主要参考:DH密钥交换和ECDH原理

Diffie-Hellman 密钥交换算法

  1. Diffie-Hellman交换过程中涉及到的所有参与者定义一个组,在这个组中定义一个大质数p,底数g。
  2. Diffie-Hellman密钥交换是一个两部分的过程,Alice和Bob都需要一个私有的数字a,b。

具体交换过程:

  1. AliceBob 协定使用 p=23 以及 g=5
  2. Alice 选择一个秘密整数 a = 6, 计算 A = g^a^ mod p 并发送给 Bob。

A = 5^6^ mod 23 = 8

  1. Bob 选择一个秘密整数 b=15, 计算 B = g^b^ mod p 并发送给 Alice。

B = 5^15^ mod 23 = 19

  1. Alice 计算 K = B^a^ mod p

K = 19^6^ mod 23 = 2

  1. Bob 计算 K = A^b^ mod p

K = 8^15^ mod 23 = 2

ECDH 密钥交换

一般公认 ECDH 密钥交换算法更加快速高效。

ECDH 密钥交换算法是将 ECC 算法和 DH 结合使用,用于密钥磋商。交换双方可以在不共享任何秘密的情况下协商出一个密钥。ECC 是建立在基于椭圆曲线的离散对数问题上的密码体制,给定椭圆曲线上的一个点P,一个整数k,求解 Q=kP 很容易;给定一个点P、Q,知道Q=kP,求整数 k 确是一个难题。ECDH即建立在此数学难题之上。密钥磋商过程:

假设密钥交换双方为Alice、Bob,其有共享曲线参数(椭圆曲线E、阶N、基点G)。

  1. Alice生成随机整数a,计算 A=a*G。 #生成Alice公钥
  2. Bob生成随机整数b,计算 B=b*G。 #生产Bob公钥
  3. Alice将A传递给Bob。A的传递可以公开,即攻击者可以获取A。

​ 由于椭圆曲线的离散对数问题是难题,所以攻击者不可以通过A、G计算出a。

  1. Bob将B传递给Alice。同理,B的传递可以公开。
  2. Bob收到Alice传递的A,计算Q =b*A #Bob通过自己的私钥和Alice的公钥得到对称密钥Q
  3. Alice收到Bob传递的B,计算Q`=a*B #Alice通过自己的私钥和Bob的公钥得到对称密钥Q’

    Alice、Bob双方即得Q=bA=b(aG)=(ba)G=(ab)G=a(bG)=aB=Q’ (交换律和结合律),即双方得到一致的密钥Q。

参考

  1. SSH Keys 加密算法 ed25519 和 rsa 的比较及生成教程
  2. SermoDigital/jose: A comprehensive set of JWT, JWS, and JWE libraries.
  3. YubiHSM2 ALGORITHMS
  4. HMAC vs ECDSA for JWT
  5. Possible Attacks on Themis Cryptosystems
  6. cossacklabs/themis Human friendly crypto library for storage and messaging for mobile apps, servers and front-ends. 2018.2.6 Crypto library for storage and messaging for Swift, Obj-C, Android/Java, С++, JS, Python, Ruby, PHP, Go. 当前版本 0.10.0 可以持续关注
  7. What is the difference between the RSA, DSA, and ECDSA keys that ssh uses?
  8. Secure Secure Shell 通过对于当前常见的密钥交换和加密算法,给出了如何加固 SSH 的具体建议
  9. ECDH椭圆双曲线(比DH快10倍的密钥交换)算法简介和封装
  10. Elliptic Curve Cryptography: ECDH and ECDSA
  11. ECDSA, EdDSA and ed25519 relationship / compatibility
CATALOG
  1. 1. JSON Web Token (JWT) 介绍
  2. 2. 常用签名算法
  3. 3. 算法选择
    1. 3.1. Go
    2. 3.2. Node
    3. 3.3. Java
  4. 4. 相关知识
    1. 4.1. Diffie-Hellman 密钥交换算法
  5. 5. ECDH 密钥交换
  6. 6. 参考