使用 x509 证书签署 JWT 令牌时遇到问题

Posted

技术标签:

【中文标题】使用 x509 证书签署 JWT 令牌时遇到问题【英文标题】:Trouble signing a JWT token with an x509 Certificate 【发布时间】:2018-12-02 13:22:52 【问题描述】:

我在使用我创建的证书签署 JWT 令牌时遇到问题。我了解签名(公钥/私钥)如何工作的基本原理,但是类和工具集非常混乱。我已经对这个示例代码大惊小怪了很长一段时间,现在我完全陷入了困境。当我运行附加的示例代码时,我最终会遇到以下错误(在tokenHandler.CreateToken() 调用中):

System.NotSupportedException: 'IDX10634: 无法创建 签名提供者。算法:'[PII 是隐藏的]',SecurityKey:'[PII 是 不支持隐藏]'。'

我提供了我在 CertificatePfxFileBase64Encoded 变量 base64 编码中创建的证书。这是一个 .pfx 文件,其中嵌入了私钥,没有密码。它是一个二进制文件,所以我必须进行 base64 编码才能在此处共享。我试图很好地理解这些课程是如何工作的,但我无法克服这个障碍。有任何想法吗?下面的例子应该是完全独立的,你只需要收集参考。

using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;

namespace SecurityStuff

    public class Testing
    
        static string CertificatePfxFileBase64Encoded = @"
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
B1gJ8j4mJ7HmXhEABAjfmw/u2zlmsAICCAA=";

        public static string CreateTokenWithX509SigningCredentials()
        
            var signingCert = new X509Certificate2(Convert.FromBase64String(CertificatePfxFileBase64Encoded));

            var privateKey = new X509SecurityKey(signingCert);
            var algo = privateKey.PrivateKey.SignatureAlgorithm;
            var signingCredentials = new SigningCredentials(privateKey, algo);

            var now = DateTime.Now;
            var tokenDescriptor = new SecurityTokenDescriptor
            
                Subject = new ClaimsIdentity(new Claim[]
                        
                        new Claim(ClaimTypes.Name, "John"),
                        new Claim(ClaimTypes.Role, "Sales"),
                        ),
                Issuer = "self",
                IssuedAt = now,
                NotBefore = now,
                Expires = now.AddMinutes(50),
                //SigningCredentials = new X509SigningCredentials(signingCert),     //For some reason this class no longer exists
                SigningCredentials = signingCredentials,
            ;

            var tokenHandler = new JwtSecurityTokenHandler();
            SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);
            string tokenString = tokenHandler.WriteToken(token);

            return tokenString;
        
    

==== 编辑 ====

我认为展示我如何制作签名证书可能会有所帮助,因为问题可能出在那儿。下面是我用来生成我的证书 CertificatePfxFileBase64Encoded 的命令行。我使用应用程序openSSL 生成它。

openssl req -new -newkey rsa:2048 -nodes -keyout CA_PrivateKey.key -out CA_SigningRequest.csr 

openssl x509 -req -days 2000 -in CA_SigningRequest.csr -signkey CA_PrivateKey.key -out CA_Certificate.crt 

openssl pkcs12 -export -out CA_Certificate.pfx -inkey CA_Private.key -in CA_Certificate.crt 

【问题讨论】:

【参考方案1】:

以下代码从 .pfx 文件生成 JWT 令牌。

public static string GenerateToken(int expireMinutes)

    X509Certificate2 signingCert = new X509Certificate2("PFXFilePath", "password");
    X509SecurityKey privateKey = new X509SecurityKey(signingCert);
    var now = DateTime.UtcNow;
    var tokenHandler = new JwtSecurityTokenHandler();
    var tokenDescriptor = new SecurityTokenDescriptor
    
        Expires = now.AddMinutes(Convert.ToInt32(expireMinutes)),
        SigningCredentials = new SigningCredentials(privateKey, SecurityAlgorithms.RsaSha256Signature)
    ;
    JwtSecurityToken stoken = (JwtSecurityToken)tokenHandler.CreateToken(tokenDescriptor);
    string token = tokenHandler.WriteToken(stoken);
    return token;

【讨论】:

以上是关于使用 x509 证书签署 JWT 令牌时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 SymmetricSecurityKey 签署 jwt 时如何指定孩子?

错误:x509:证书由未知机构签署,种类为群集

如何在 AspNetCore 中仅使用公钥验证使用 x509 签名的 JWT 令牌

https://registry.gitlab.com/v2/: x509: 未知权威签署的证书

使用 X509 证书签署 BizTalk WCF 响应

通过签署 CSR 创建 x509 v3 用户证书