HTTP | JWT

JWT(JSON Web Token)通常由标头 + 载荷 + 签名组成。

 

头部

 

包含 JWT 的元数据信息。

 


{
  "alg": "HS256",
  "typ": "JWT"
}

您可以找到更多标头,但上述标头始终存在。

 

载荷

 

载荷包含 JWT 的声明。标准请求头如下:

 


{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

 

签名

 

签名使用编码后的标头、编码后的载荷、密钥和加密算法创建。


eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5M
DIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

支持的算法

以下算法同时受客户端和服务器 JWT 组件支持。

 

 

需要 OpenSSL 库 才能签名和验证 JWT,但有一个例外。

 

ML-DSA,后量子签名

这三种 ML-DSA 算法是 RFC 9964 所定义的后量子 JOSE 算法, 也就是上面所说的那个例外:它们由 sgcCrypto 包以纯 Object Pascal 实现, 因此在没有任何 OpenSSL 库的情况下也能签名和验证。签名采用 FIPS 204 的 ML-DSA, 在纯模式下以空上下文对 JWS 签名输入进行签名,并以 base64url 形式放入令牌中。 签名器是确定性的,因此相同的密钥和相同的输入总是产生相同的签名。

 

枚举值为 jwtMLDSA44、 jwtMLDSA65 和 jwtMLDSA87,它们写入的 alg 头分别是 ML-DSA-44、 ML-DSA-65 和 ML-DSA-87。客户端使用 JWTOptions.Algorithms.MLDSA.PrivateKey (一个 PKCS#8 PEM 私钥)进行签名,服务器使用 JWTOptions.Algorithms.MLDSA.PublicKey (一个 SubjectPublicKeyInfo PEM 公钥)进行验证。密钥的参数集必须与该算法所指明的一致: 否则签名会引发异常,验证则返回 False。

 

签名体积很大。ML-DSA-44 的签名为 2420 字节,而 ES256 只有 64 字节, 因此令牌大约会增加 3.2 KB 的 base64url 内容,ML-DSA-87 则大约增加 6.2 KB。 在采用它之前,请先检查令牌所经过的每一个环节的头部大小限制。

 

密钥还可以以 AKP 形式的 JSON Web Key 携带,见 RFC 9964 第 3 节和第 4 节。 sgcMLDSA_ExportPublicJWK 和 sgcMLDSA_ExportPrivateJWK 负责写出,sgcMLDSA_ImportJWK 可以读取其中任意一种形式,而 sgcMLDSA_ImportJWKAsPEM 则直接把一个 JWK 转换成这两个组件所读取的 PEM 字符串。私有 JWK 在 priv 中保存 32 字节的种子, 这是第 4 节定义的唯一私钥形式,因此展开后的私钥无法写成 JWK。 这四个函数都声明在 sgcHTTP_JWT_MLDSA 中。

 

* ML-DSA 算法需要 sgcCrypto 包。没有它时这些枚举值依然存在, 因此用它们保存的窗体仍然可以加载,但签名会引发异常, 并且每一个 ML-DSA 令牌都会被拒绝。

组件

 

 

 

* JWT 组件至少需要 Indy 版本 10.6.0.5169 或 sgcWebSockets Enterprise 版。