You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core API:无需共享公钥的非对称JWT密钥生成方案

可行方案:基于公钥哈希注册的客户端自签名JWT验证

完全可以实现这种需求,核心思路是让客户端自行生成非对称密钥对,服务端仅预存客户端公钥的唯一哈希标识而非公钥本身,验证时通过提取请求中的公钥并校验哈希合法性,再完成签名验证。具体方案如下:

核心流程

  • 客户端按指定规范生成非对称密钥对(比如RS256算法、2048位密钥)
  • 客户端计算自身公钥的SHA-256哈希,通过内部安全流程提交给服务端完成注册(服务端将哈希存入信任列表)
  • 客户端每次请求时,在JWT的x5c(X.509证书链)头部字段携带自己的公钥
  • 服务端先提取公钥计算哈希,匹配信任列表中的合法哈希,验证通过后再用该公钥校验JWT签名

.NET Core 实现要点

  1. 存储信任的公钥哈希
    可以用配置文件或数据库维护信任列表,示例配置:

    "TrustedClients": {
      "PubKeyHashes": [
        "a1b2c3d4e5f6...",
        "f6e5d4c3b2a1..."
      ]
    }
    
  2. 自定义JWT验证逻辑
    在认证中间件中添加哈希校验步骤,示例代码片段:

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = false, // 根据内部需求调整
                ValidateAudience = false,
                ValidateLifetime = true,
                SignatureValidator = (token, parameters) =>
                {
                    var jwtHandler = new JwtSecurityTokenHandler();
                    var jwtToken = jwtHandler.ReadJwtToken(token);
                    
                    // 从头部提取x5c字段中的公钥
                    var x5c = jwtToken.Header.TryGetValue("x5c", out var value) ? value as List<string> : null;
                    if (x5c == null || x5c.Count == 0)
                        throw new SecurityTokenInvalidSignatureException("Missing public key in header");
                    
                    // 解析公钥
                    var pubKeyBytes = Convert.FromBase64String(x5c[0]);
                    var pubKey = new X509Certificate2(pubKeyBytes).GetRSAPublicKey();
                    
                    // 计算公钥哈希
                    var pubKeyHash = SHA256.HashData(pubKey.ExportSubjectPublicKeyInfo());
                    var pubKeyHashHex = BitConverter.ToString(pubKeyHash).Replace("-", "").ToLower();
                    
                    // 校验哈希是否在信任列表
                    var trustedHashes = Configuration.GetSection("TrustedClients:PubKeyHashes").Get<List<string>>();
                    if (!trustedHashes.Contains(pubKeyHashHex))
                        throw new SecurityTokenInvalidSignatureException("Untrusted public key");
                    
                    // 验证签名
                    var validationParameters = new TokenValidationParameters
                    {
                        IssuerSigningKey = new RsaSecurityKey(pubKey),
                        ValidateIssuerSigningKey = true
                    };
                    jwtHandler.ValidateToken(token, validationParameters, out var validatedToken);
                    return validatedToken as JwtSecurityToken;
                }
            };
        });
    
  3. 客户端密钥生成规范
    给客户端明确以下要求:

    • 必须使用RS256算法生成非对称密钥对,密钥长度不低于2048位(推荐4096位)
    • 公钥需封装为X.509证书(或直接导出SPKI格式),转为Base64后放入JWT的x5c头部数组的第一个元素
    • 计算公钥哈希时,需导出公钥的SPKI格式字节流,再用SHA-256哈希,结果转为小写十六进制字符串提交注册

注意事项

  • 公钥哈希的注册必须通过内部安全审批流程,确保只有合法客户端能加入信任列表
  • 客户端需严格保管私钥,一旦泄露需立即生成新密钥对并重新注册哈希
  • 服务端可定期清理过期或停用的客户端哈希,减少验证开销

内容的提问来源于stack exchange,提问作者Ramki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 00:36:23