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

如何仅用Modulus和Exponent生成Azure AD B2C公钥以验证ID Token签名?

解决Azure AD B2C的RSA公钥生成与JWT签名验证问题

我明白你现在的困扰——手里只有Azure AD B2C返回的n(模数)和e(指数),不知道怎么转成可用的RSA公钥,还要用C#实现,同时想在jwt.io上测试签名。下面我一步步给你讲清楚怎么做:

一、把n和e转换成PEM格式的公钥(用于jwt.io测试)

Azure AD B2C返回的n和e是Base64Url编码的,不是普通的Base64,所以首先要解码它们。然后我们可以用C#的System.Security.Cryptography类库来生成标准的PEM公钥,这样jwt.io就能直接识别。

具体代码实现

using System;
using System.Security.Cryptography;
using System.Text;

public static string GenerateRsaPublicKey(string base64UrlModulus, string base64UrlExponent)
{
    // 解码Base64Url格式的模数和指数
    byte[] modulus = Base64UrlDecode(base64UrlModulus);
    byte[] exponent = Base64UrlDecode(base64UrlExponent);

    // 创建RSAParameters对象并赋值
    var rsaParams = new RSAParameters
    {
        Modulus = modulus,
        Exponent = exponent
    };

    // 导入参数并导出PEM格式公钥
    using (var rsa = RSA.Create())
    {
        rsa.ImportParameters(rsaParams);
        var xmlPublicKey = rsa.ToXmlString(includePrivateParameters: false);
        
        // 将XML格式转换为标准PEM格式
        var base64Content = xmlPublicKey
            .Replace("<RSAKeyValue>", "")
            .Replace("</RSAKeyValue>", "")
            .Replace("<Modulus>", "")
            .Replace("</Modulus>", "")
            .Replace("<Exponent>", "")
            .Replace("</Exponent>", "");
        
        // 按PEM标准分割为每行64字符
        var pemBuilder = new StringBuilder();
        pemBuilder.AppendLine("-----BEGIN PUBLIC KEY-----");
        for (int i = 0; i < base64Content.Length; i += 64)
        {
            pemBuilder.AppendLine(base64Content.Substring(i, Math.Min(64, base64Content.Length - i)));
        }
        pemBuilder.AppendLine("-----END PUBLIC KEY-----");
        
        return pemBuilder.ToString();
    }
}

// 实现Base64Url解码(处理'-'和'_'替换为'+'和'/',补全'=')
private static byte[] Base64UrlDecode(string input)
{
    input = input.Replace('-', '+').Replace('_', '/');
    switch (input.Length % 4)
    {
        case 2: input += "=="; break;
        case 3: input += "="; break;
    }
    return Convert.FromBase64String(input);
}

调用这个方法时,把你拿到的n和e值传进去,就能得到标准的PEM公钥,直接复制到jwt.io的「Public Key」区域就能测试签名了。

二、用C#验证Azure AD B2C的id_token签名

既然你已经有验证库的思路,我推荐用微软官方的Microsoft.IdentityModel.Tokens库(NuGet可以直接安装),它能自动处理密钥获取和签名验证,不用手动生成公钥也能搞定,更适合生产环境:

示例代码

using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Threading.Tasks;

public static async Task<bool> ValidateIdTokenAsync(string idToken, string metadataEndpoint, string clientId)
{
    var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
        metadataEndpoint,
        new OpenIdConnectConfigurationRetriever());

    var config = await configurationManager.GetConfigurationAsync();

    var validationParameters = new TokenValidationParameters
    {
        ValidAudience = clientId, // 你的Azure AD B2C应用的Client ID
        ValidIssuer = config.Issuer, // 从元数据自动获取的Issuer URI
        IssuerSigningKeys = config.SigningKeys,
        ValidateLifetime = true,
        ValidateAudience = true,
        ValidateIssuer = true
    };

    try
    {
        var handler = new JwtSecurityTokenHandler();
        handler.ValidateToken(idToken, validationParameters, out var validatedToken);
        return true;
    }
    catch (Exception ex)
    {
        // 验证失败,处理异常(比如日志记录)
        Console.WriteLine($"验证失败:{ex.Message}");
        return false;
    }
}

这个方法会自动从元数据端点获取对应kid的密钥(包括n和e),然后完成签名验证,比手动生成公钥更可靠,避免自己处理编码错误。

三、jwt.io测试小贴士

  1. 把你的id_token粘贴到jwt.io的「Encoded」区域
  2. 把刚才用C#生成的PEM公钥粘贴到「Public Key」区域
  3. 确认「Signature Verified」显示为绿色,就说明签名有效了

如果遇到问题,检查一下kid是否匹配——确保你用的密钥和id_token头里的kid一致,Azure AD B2C可能会有多个密钥,要选对应kid的那组n和e。

内容的提问来源于stack exchange,提问作者Lukas Méndez Duus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:42:45