【问题标题】:Swapping SymmetricSecurityKey for AsymmetricSecurityKey for JWT为 JWT 的 AsymmetricSecurityKey 交换 SymmetricSecurityKey
【发布时间】:2021-05-25 03:25:41
【问题描述】:

渗透测试建议我们将 JWT 实现更改为使用非对称签名而不是对称签名,该方法运行良好。

创建对称令牌的当前(完美工作)代码如下:(灵感最初来自How to encrypt JWT security token?

private string CreateToken(string Username)
        {
            //Set issued at date
            DateTime issuedAt = DateTime.UtcNow;
            //set the time when it expires
            DateTime expires = DateTime.UtcNow.AddHours(1);

            
            JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

            //create a identity and add claims to the user which we want to log in
            ClaimsIdentity claimsIdentity = new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.Name, Username)
            });

            DateTime now = DateTime.UtcNow;
            SymmetricSecurityKey securityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(SecurityConstants.ConstSecurityEncryptionKey));
            SigningCredentials signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);

            //create the jwt
            JwtSecurityToken token = tokenHandler.CreateJwtSecurityToken(issuer: "issuer",
                                                                         audience: "audience",
                                                                         subject: claimsIdentity,
                                                                         notBefore: issuedAt,
                                                                         expires: expires,
                                                                         signingCredentials: signingCredentials);

            return tokenHandler.WriteToken(token);

        }
    }

检查任何 API 调用请求的代码如下所示:

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            HttpStatusCode StatusCode;
            string token;

            //determine whether a jwt exists or not
            if (!TryRetrieveToken(request, out token))
            {
                StatusCode = HttpStatusCode.Unauthorized;
                //allow requests with no token - whether a action method needs an authentication can be set with the claimsauthorization attribute
                return base.SendAsync(request, cancellationToken);
            }

            try
            {
                DateTime now = DateTime.UtcNow;
                SymmetricSecurityKey SecurityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(SecurityConstants.ConstSecurityEncryptionKey));

                SecurityToken securityToken;
                JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
                TokenValidationParameters validationParameters = new TokenValidationParameters()
                {
                    ValidAudience = "audience",
                    ValidIssuer = "issuer",
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    LifetimeValidator = this.LifetimeValidator,
                    IssuerSigningKey = SecurityKey
                };

                //extract and assign the user of the jwt
                Thread.CurrentPrincipal = handler.ValidateToken(token, validationParameters, out securityToken);
                HttpContext.Current.User = handler.ValidateToken(token, validationParameters, out securityToken);

                return base.SendAsync(request, cancellationToken);
            }
            catch (SecurityTokenValidationException e)
            {
                StatusCode = HttpStatusCode.Forbidden;
            }
            catch (Exception ex)
            {
                StatusCode = HttpStatusCode.Forbidden;
            }
            return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(StatusCode) { });
        }

我已经尝试了很多在线示例并阅读了很多帖子,但还没有任何工作,每个都有很多不同的问题。可能我已经关闭了以下一些示例:RS256 vs HS256: What's the difference?

下面是一个似乎在创建代码时有效的示例,但在将令牌与传入的 API 调用进行比较时,这将不起作用。

                RSA _rsaa;
                _rsaa = new RSACryptoServiceProvider(2048);
                var r = _rsaa.ExportParameters(true);
                SigningCredentials signingCredentials3a = new SigningCredentials(new RsaSecurityKey(_rsaa), SecurityAlgorithms.RsaSha256Signature);

最后,下面的选项感觉正确,但得到的是“错误版本的提供程序”。由于字符串中保存的加密密钥内容而出错。

            byte[] Key256Bytes = Encoding.ASCII.GetBytes(Key256);

                rsa.ImportCspBlob(Key256Bytes);
                SigningCredentials signingCredentials5 = new SigningCredentials(new RsaSecurityKey(rsa), SecurityAlgorithms.RsaSha256Signature);

我很难让各种选项发挥作用。

【问题讨论】:

    标签: c# cryptography jwt rsa


    【解决方案1】:

    找到解决方案,将上述转换为非对称加密,交换:

    SymmetricSecurityKey securityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(SecurityConstants.ConstSecurityEncryptionKey));
    SigningCredentials signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
    

    var rsa = new RSACryptoServiceProvider(); 
    rsa.ImportCspBlob(Convert.FromBase64String(SecurityConstants.ConstAsyncSecurityEncryptionKey));                
    SigningCredentials signingCredentials = new SigningCredentials(new RsaSecurityKey(rsa), SecurityAlgorithms.RsaSha512Signature);
    

    加密密钥是通过以下方式生成的。

    var rsa = new RSACryptoServiceProvider(2048);
    var key = Convert.ToBase64String(rsa.ExportCspBlob(true));
    

    那么在检查传入的JWT时:

    SymmetricSecurityKey SecurityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(SecurityConstants.ConstSecurityEncryptionKey));
    

    var rsa = new RSACryptoServiceProvider();      
    rsa.ImportCspBlob(Convert.FromBase64String(SecurityConstants.ConstAsyncSecurityEncryptionKey));
    RsaSecurityKey SecurityKey = new RsaSecurityKey(rsa);
    

    希望将来能对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 2018-09-28
      • 2012-11-20
      • 1970-01-01
      • 1970-01-01
      • 2018-09-16
      • 1970-01-01
      • 1970-01-01
      • 2021-03-30
      • 2019-02-02
      相关资源
      最近更新 更多