Cha*_*yer 10 c# rsa public-key jwt
我有一些这样的代码,我认为它失败了,因为它使用非对称 RS256 但具有“SymmetricSecurityKey()”。令牌是从https://jwt.io/手工生成的
\n\xce\xbb cat Program.cs\n\xef\xbb\xbfusing System;\nusing System.IdentityModel.Tokens.Jwt;\nusing System.Text;\nusing System.Linq;\nusing Microsoft.IdentityModel.Tokens;\nusing System.Security.Cryptography;\n\nnamespace jwttest\n{\n class Program\n {\n static void Main(string[] args)\n {\n string jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.POstGetfAytaZS82wHcjoTyoqhMyxXiWdR7Nn7A29DNSl0EiXLdwJ6xC6AfgZWF1bOsS_TuYI3OG85AmiExREkrS6tDfTQ2B3WXlrr-wp5AokiRbz3_oB4OxG-W9KcEEbDRcZc0nH3L7LzYptiy1PtAylQGxHTWZXtGz4ht0bAecBgmpdgXMguEIcoqPJ1n3pIWk_dUZegpqx0Lka21H6XxUTxiy8OcaarA8zdnPUnV6AmNP3ecFawIFYdvJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6gUY618iYv7tuPWBFfEbLxtF2pZS6YC1aSfLQxeNe8djT9YjpvRZA";\n var pubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQAB";\n var rawKey = Encoding.ASCII.GetBytes(pubKey);\n\n var tokenHandler = new JwtSecurityTokenHandler();\n // var rsa = ?\n tokenHandler.ValidateToken(jwt, new TokenValidationParameters {\n IssuerSigningKey = new SymmetricSecurityKey(rawKey)\n },\n out SecurityToken validatedToken);\n }\n }\n}\n\nC:\\src\\jwttest (cgt-test-5 -> origin)\n\xce\xbb dotnet run\n[2020-08-18T23:41:05.7108585-07:00 Info] raw=System.Byte[] [392]\nUnhandled exception. Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: IDX10503: Signature validation failed. Keys tried: \'System.Text.StringBuilder\'.\nExceptions caught:\n \'System.Text.StringBuilder\'.\ntoken: \'System.IdentityModel.Tokens.Jwt.JwtSecurityToken\'.\n at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)\n at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)\n at jwttest.Program.Main(String[] args) in C:\\src\\jwttest\\Program.cs:line 22\n\n\xce\xbb cat jwttest.csproj\n<Project Sdk="Microsoft.NET.Sdk">\n\n <PropertyGroup>\n <OutputType>Exe</OutputType>\n <TargetFramework>netcoreapp3.1</TargetFramework>\n </PropertyGroup>\n <ItemGroup>\n <!-- Using preview release because it only depends on dotnet standard. Prior versions need framework. -->\n <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.7.2-preview-10803222715" />\n </ItemGroup>\n</Project>\n\n\xce\xbb cat jwt.json\n{\n "alg": "RS256",\n "typ": "JWT"\n}\n{\n "sub": "1234567890",\n "name": "John Doe",\n "admin": true,\n "iat": 1516239022\n}\nRun Code Online (Sandbox Code Playgroud)\n
Top*_*aco 14
关于你的第一个问题:
根据你发布的堆栈跟踪,你似乎正在使用 .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
Run Code Online (Sandbox Code Playgroud)
ImportSubjectPublicKeyInfo()自 .NET Core 3.0 起可用。
编辑开始:在早期版本的.NET Core(3.0之前)或.NET Framework中ImportSubjectPublicKeyInfo()不可用,因此至少需要.NET Standard 2.1 。
对于早期版本,例如.NET Standard 2.0,一种可能性是使用BouncyCastle,更准确地说是它的Org.BouncyCastle.OpenSsl.PemReader类,它允许导入 X509/SPKI 格式的公钥(并且与您无关,也可以采用 PKCS#1 格式)。在此答案中,您将找到如何使用 的示例PemReader。PemReader顾名思义,处理 PEM 编码,即ImportSubjectPublicKeyInfo() 不得按照要求进行到 DER 编码的转换(即删除页眉、页脚和换行符,以及剩余部分的 Base64 解码) 。另请注意,PemReader预计在页眉 ( ) 之后至少有一个换行符-----BEGIN PUBLIC KEY-----\n,在页脚 ( ) 之前至少有一个\n-----END PUBLIC KEY-----换行符,Base64 编码正文中每 64 个字符之后的换行符对于 是可选的PemReader。
另一种可能性是opensslkey包提供了该方法opensslkey.DecodeX509PublicKey(),它可以处理 DER 编码中的 X509/SPKI 密钥,类似于ImportSubjectPublicKeyInfo。编辑结束
关于你的第二个问题:.NET标准
有几个版本,例如.NET Core 3.0实现了.NET Standard 2.1。您正在使用的包System.IdentityModel.Tokens.Jwt 6.7.2-preview-10803222715需要 .NET Standard 2.0。
System.IdentityModel.Tokens.Jwt是一个支持 JSON Web 令牌 (JWT) 创建和验证的包。对于发布的令牌,验证可以按如下方式实现:
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);
Run Code Online (Sandbox Code Playgroud)
验证可以通过验证参数来控制,即通过 的第二个参数ValidateToken()。由于发布的令牌不包含声明 iss、aud和exp (这可以在https://jwt.io/上进行验证),因此在我的示例中它们被排除在验证之外。
在教程“在 ASP.NET Core 中创建和验证 JWT 令牌”中,您会找到更详细的说明,特别是在“验证令牌”一章中。
ValidateToken()本质上封装了JWT签名的验证过程。JWT是一种数据结构,由三部分组成:标头、有效负载和签名,各个部分均经过 Base64url 编码并通过点分隔。
签名是使用各种算法创建的,例如在您的情况下RS256,这意味着数据(Base64url 编码的标头和包括分隔符的有效负载)使用带有 PKCS#1 v1.5 填充和摘要 SHA256 的 RSA 算法进行签名。
令牌的验证对应于签名的验证,这也可以仅使用加密 API 来完成(即无需System.IdentityModel.Tokens.Jwt的参与),因为它是在链接问题的接受答案中完成的@zaitsman 的评论。
| 归档时间: |
|
| 查看次数: |
11231 次 |
| 最近记录: |