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

C#中RSA公私钥生成JWT签名验证失败求助

RSA签名JWT在JWT.IO验证失败的解决方法

你用C#生成RSA签名的JWT后,用公钥在JWT.IO验证时显示签名无效,核心问题是你生成PEM格式公钥的方式错误——直接把XML格式的公钥转Base64并添加PEM头尾,得到的不是JWT.IO可识别的标准PEM密钥格式。

问题根源

RSACryptoServiceProvider.ToXmlString(false)生成的是XML结构的公钥,而JWT.IO需要的是PKCS#1或PKCS#8标准格式的PEM公钥。直接对XML字符串做Base64编码,本质是把XML文本转成了Base64,并非真正的密钥原始字节编码,自然无法通过签名验证。

修复方案

1. 正确生成标准PEM格式密钥

从RSA对象中直接导出密钥的原始字节(而非XML字符串),再转换成符合规范的PEM格式:

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;

class JwtRsaDemo
{
    static void Main()
    {
        // 指定密钥长度,推荐2048位及以上
        using (RSA rsa = RSA.Create(2048))
        {
            // 导出私钥为PKCS#8格式字节,转换为标准PEM
            byte[] privateKeyBytes = rsa.ExportPkcs8PrivateKey();
            string privateKeyPem = ConvertToPem(privateKeyBytes, "PRIVATE KEY");

            // 导出公钥为SubjectPublicKeyInfo格式字节,转换为标准PEM
            byte[] publicKeyBytes = rsa.ExportSubjectPublicKeyInfo();
            string publicKeyPem = ConvertToPem(publicKeyBytes, "PUBLIC KEY");

            // 生成JWT
            var signingKey = new RsaSecurityKey(rsa);
            var credentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha256);

            var jwtToken = new JwtSecurityToken(
                issuer: "iss",
                audience: "aud",
                claims: new List<Claim> { new Claim("user_id", "123") },
                expires: DateTime.UtcNow.AddMinutes(30), // 用UtcNow避免时区差异导致的验证问题
                signingCredentials: credentials
            );

            string token = new JwtSecurityTokenHandler().WriteToken(jwtToken);

            Console.WriteLine("生成的Token:");
            Console.WriteLine(token);
            Console.WriteLine("\n公钥PEM:");
            Console.WriteLine(publicKeyPem);
        }
    }

    // 辅助方法:将密钥字节转换为带换行的标准PEM格式
    static string ConvertToPem(byte[] keyBytes, string keyType)
    {
        string base64 = Convert.ToBase64String(keyBytes, Base64FormattingOptions.InsertLineBreaks);
        return $"-----BEGIN {keyType}-----\n{base64}\n-----END {keyType}-----";
    }
}

2. 验证步骤

  • 把代码生成的publicKeyPem完整复制到JWT.IO的「Public Key」输入框(包含头尾的-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----)
  • 确认JWT.IO的「Algorithm」选择RS256(与代码中SecurityAlgorithms.RsaSha256对应)
  • 避免使用DateTime.Now生成过期时间,改用DateTime.UtcNow防止时区问题导致的验证失败

额外提示

  • .NET Core/.NET 5+中推荐用RSA.Create()替代RSACryptoServiceProvider,API更符合现代规范
  • 密钥长度不要低于2048位,1024位已被认为不安全

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 18:40:56