Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用C中的RS256(非对称)验证JWT#_C#_Jwt_Rsa_Public Key - Fatal编程技术网

C# 用C中的RS256(非对称)验证JWT#

C# 用C中的RS256(非对称)验证JWT#,c#,jwt,rsa,public-key,C#,Jwt,Rsa,Public Key,我有一些这样的代码,我认为它失败了,因为它使用了非对称的RS256,但有“SymmetricSecurityKey()”。这些代币是手工生成的 如何将其转换为使用非对称公钥 另外,我是C#的新手,我想以dotnet标准为目标,所以我也想知道我是否使用了错误的LIB?(取决于预览版) λcat程序.cs 使用制度; 使用System.IdentityModel.Tokens.Jwt; 使用系统文本; 使用System.Linq; 使用Microsoft.IdentityModel.Tokens;

我有一些这样的代码,我认为它失败了,因为它使用了非对称的RS256,但有“SymmetricSecurityKey()”。这些代币是手工生成的

  • 如何将其转换为使用非对称公钥
  • 另外,我是C#的新手,我想以dotnet标准为目标,所以我也想知道我是否使用了错误的LIB?(取决于预览版)
  • λcat程序.cs
    使用制度;
    使用System.IdentityModel.Tokens.Jwt;
    使用系统文本;
    使用System.Linq;
    使用Microsoft.IdentityModel.Tokens;
    使用System.Security.Cryptography;
    命名空间jwttest
    {
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    字符串jwt="2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.6.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2.2 LKA21H6XXUTXIY8OCARA8ZDNPUNV6AMNP3ECFAWIFYDVJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6GUYYV7TUPWBFEBLXTF2PZS6YC1ASFLQXENE8DJT9YJPVRZA”;
    var pubKey=”2.在中国的一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市,一个城市一个城市,一个城市一个城市,一个城市,一个城市一个城市一个城市,一个城市,一个城市,一个城市一个城市一个城市一个城市XSW4HV43QA+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQAB”;
    var rawKey=Encoding.ASCII.GetBytes(pubKey);
    var tokenHandler=new JwtSecurityTokenHandler();
    //var rsa=?
    ValidateToken(jwt,新的TokenValidationParameters{
    IssuerSigningKey=新对称安全密钥(rawKey)
    },
    out SecurityToken validatedToken);
    }
    }
    }
    C:\src\jwttest(cgt-test-5->origin)
    λ点网运行
    [2020-08-18T23:41:05.7108585-07:00信息]原始=系统字节[][392]
    未处理的异常。Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException:IDX10503:签名验证失败。尝试的密钥为:“System.Text.StringBuilder”。
    捕获的异常:
    “System.Text.StringBuilder”。
    token:'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'。
    位于System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(字符串令牌,令牌验证参数validationParameters)
    位于System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(字符串令牌、令牌验证参数validationParameters、SecurityToken和ValidateToken)
    在C:\src\jwttest\Program.cs中的jwttest.Program.Main(字符串[]args)处:第22行
    λcat jwttest.csproj
    Exe
    netcoreapp3.1
    λcat jwt.json
    {
    “alg”:“RS256”,
    “典型”:“JWT”
    }
    {
    “sub”:“1234567890”,
    “姓名”:“约翰·多伊”,
    “管理员”:是的,
    “iat”:1516239022
    }
    
    • 关于您的第一个问题:
      根据您发布的堆栈跟踪,您似乎正在使用.NET Core 3.1。这允许您轻松导入公共X.509/SPKI密钥,如下所示:

      var pubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQAB";
      
      RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
      rsa.ImportSubjectPublicKeyInfo(Convert.FromBase64String(pubKey), out _); // import the public X.509/SPKI DER encoded key
      
      string jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.POstGetfAytaZS82wHcjoTyoqhMyxXiWdR7Nn7A29DNSl0EiXLdwJ6xC6AfgZWF1bOsS_TuYI3OG85AmiExREkrS6tDfTQ2B3WXlrr-wp5AokiRbz3_oB4OxG-W9KcEEbDRcZc0nH3L7LzYptiy1PtAylQGxHTWZXtGz4ht0bAecBgmpdgXMguEIcoqPJ1n3pIWk_dUZegpqx0Lka21H6XxUTxiy8OcaarA8zdnPUnV6AmNP3ecFawIFYdvJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6gUY618iYv7tuPWBFfEbLxtF2pZS6YC1aSfLQxeNe8djT9YjpvRZA";
      
      var tokenHandler = new JwtSecurityTokenHandler();
      bool verified = false;
      try
      {
          tokenHandler.ValidateToken(jwt, new TokenValidationParameters
          {
              ValidateAudience = false,                       
              ValidateLifetime = false,
              ValidateIssuer = false,
              IssuerSigningKey = new RsaSecurityKey(rsa)
          },
          out _);
      
          verified = true;
      }
      catch 
      {
          verified = false;
      }
      
      Console.WriteLine("Verified: " + verified);
      
      从.NET Core 3.0开始提供

      编辑开始: 在早期版本的.NET Core(3.0之前)或.NET Framework中不可用,因此至少需要

      对于早期版本,例如.NET Standard 2.0,一种可能是更精确地使用其
      Org.BouncyCastle.OpenSsl.PemReader
      类,该类允许以X509/SPKI格式导入公钥(与您无关,也可以使用PKCS#1格式)。在中,您将找到一个示例,说明如何使用
      PemReader
      PemReader
      过程,顾名思义,PEM编码,即转换为DER编码(即删除页眉、页脚和换行符,以及按照
      ImportSubjectPublicKeyInfo()的要求对剩余部分进行Base64解码)
      不能执行。还要注意,
      PemReader
      要求在页眉后面至少有一个换行符(
      ----开始公钥------\n
      ),在页脚前面至少有一个换行符(
      \n----结束公钥------
      ),Base64编码正文中每64个字符后的换行符对于
      PemReader
      是可选的

      另一种可能性是提供方法的包
      opensslkey.DecodeX509PublicKey()
      ,该方法可以在编码中处理X509/SPKI密钥,类似于
      ImportSubjectPublicKeyInfo
      编辑结束

    • 关于第二个问题:
      有几个版本,例如.NET Core 3.0实现.NET标准2.1。您使用的包System.IdentityModel.Tokens.Jwt需要.NET标准2.0

      System.IdentityModel.Tokens.Jwt
      是一个支持JSON Web令牌(Jwt)的创建和验证的包。对于已发布的令牌,可以按如下方式实现验证:

      var pubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQAB";
      
      RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
      rsa.ImportSubjectPublicKeyInfo(Convert.FromBase64String(pubKey), out _); // import the public X.509/SPKI DER encoded key
      
      string jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.POstGetfAytaZS82wHcjoTyoqhMyxXiWdR7Nn7A29DNSl0EiXLdwJ6xC6AfgZWF1bOsS_TuYI3OG85AmiExREkrS6tDfTQ2B3WXlrr-wp5AokiRbz3_oB4OxG-W9KcEEbDRcZc0nH3L7LzYptiy1PtAylQGxHTWZXtGz4ht0bAecBgmpdgXMguEIcoqPJ1n3pIWk_dUZegpqx0Lka21H6XxUTxiy8OcaarA8zdnPUnV6AmNP3ecFawIFYdvJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6gUY618iYv7tuPWBFfEbLxtF2pZS6YC1aSfLQxeNe8djT9YjpvRZA";
      
      var tokenHandler = new JwtSecurityTokenHandler();
      bool verified = false;
      try
      {
          tokenHandler.ValidateToken(jwt, new TokenValidationParameters
          {
              ValidateAudience = false,                       
              ValidateLifetime = false,
              ValidateIssuer = false,
              IssuerSigningKey = new RsaSecurityKey(rsa)
          },
          out _);
      
          verified = true;
      }
      catch 
      {
          verified = false;
      }
      
      Console.WriteLine("Verified: " + verified);
      
      验证可以通过验证参数进行控制,即通过的第二个参数。由于发布的令牌不包含iss、aud和exp(这可以通过例如on进行验证),因此在我的示例中,它们被排除在验证之外

      在本教程中,您将找到更详细的解释,特别是在验证令牌一章中

      ValidateToken()
      基本上封装了JWT签名的验证过程。A是一种数据结构,由三部分组成:标题、有效负载和签名,各个部分采用Base64url编码,并用点分隔开来。
      签名是使用各种算法创建的,例如在您的情况下,这意味着数据(Base64url编码的报头和有效负载,包括分隔符)使用算法RSA和PKCS#1 v1.5 padding and digest SHA256进行签名。
      令牌的验证对应于签名的验证,其中