我创建一个Web服务,并且将使用由JWT加密X509Certficates相关客户端。当我使用对称密钥来加密和解密令牌时,一切正常。不过,我想基于生产X509Certficates使用加密,当我尝试其中的一个,我得到这些异常:IDX10659错误解密JWT令牌
当.NET Core上运行:
Microsoft.IdentityModel.Tokens.SecurityTokenKeyWrapException:
IDX10659: UnwrapKey failed, exception from crypto operation:
'Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException:
Key does not exist'
上运行在.NET Framework当4.7(注意内部异常的区别):
Microsoft.IdentityModel.Tokens.SecurityTokenKeyWrapException:
IDX10659: UnwrapKey failed, exception from crypto operation:
'System.Security.Cryptography.CryptographicException:
Error occurred while decoding OAEP padding.'
从SymmetricSecurityKey
切换到X509SecurityKey
只是改变提供的EncryptingCredentials
实例的价值,所以我期待一切只是工作。
这里是我的代码来生成令牌:
public string Generate(NodeEntitlements entitlements)
{
if (entitlements == null)
{
throw new ArgumentNullException(nameof(entitlements));
}
var claims = CreateClaims(entitlements);
var claimsIdentity = new ClaimsIdentity(claims);
var securityTokenDescriptor = new SecurityTokenDescriptor
{
Subject = claimsIdentity,
NotBefore = entitlements.NotBefore.UtcDateTime,
Expires = entitlements.NotAfter.UtcDateTime,
IssuedAt = DateTimeOffset.Now.UtcDateTime,
Issuer = "https://example.com",
Audience = "https://example.com",
SigningCredentials = SigningCredentials,
EncryptingCredentials = EncryptingCredentials
};
var handler = new JwtSecurityTokenHandler();
var token = handler.CreateToken(securityTokenDescriptor);
return handler.WriteToken(token);
}
这里是我的代码来验证同样的道理(我发表过评论,其中异常被抛出线):
public VerificationResult Verify(string tokenString)
{
var validationParameters = new TokenValidationParameters
{
ValidateAudience = true,
ValidAudience = "https://example.com",
ValidateIssuer = true,
ValidIssuer = "https://example.com",
ValidateLifetime = true,
RequireExpirationTime = true,
RequireSignedTokens = SigningKey != null,
ClockSkew = TimeSpan.FromSeconds(60),
IssuerSigningKey = SigningKey,
ValidateIssuerSigningKey = SigningKey != null,
TokenDecryptionKey = EncryptionKey
};
try
{
var handler = new JwtSecurityTokenHandler();
// Exception is thrown here
var principal =
handler.ValidateToken(tokenString, validationParameters, out var token);
var entitlementIdClaim = principal.FindFirst("id");
if (entitlementIdClaim == null)
{
return VerificationResult.IdentifierNotPresent;
}
return VerificationResult.Valid;
}
catch (SecurityTokenException ex)
{
Console.WriteLine(ex);
return VerificationResult.InvalidToken;
}
}
要根据证书创建EncryptingCredentials
:
public static EncryptingCredentials CreateCertificateEncryptionCredentials()
{
var certificate = FindCertificate();
var key = new X509SecurityKey(certificate);
var result = new EncryptingCredentials(
key, SecurityAlgorithms.RsaOAEP, SecurityAlgorithms.Aes256CbcHmacSha512);
return result;
}
这些方法是从第我从我的原始代码库中提取了一个minimal repro(GitHub链接);在这里发布的代码有点多,但大部分代码只是基础设施。 repro完全处于工作状态,并不使用ASP.NET中的任何内容。
我已经与多个不同X509Certficates转载的问题,在三个不同的机器上,在两个不同的用户账户,所以我想我已经消除了证书作为问题的根源。在每次测试中签名都能够正常工作,我认为这表明证书的公钥和私钥都可以正常访问。
为什么解密只会通过X509SecurityKey
而不是SymmetricSecurityKey
?
什么是使用X509Certficates加密/解密JWT令牌的正确方法?或者,这个问题的解决方法是什么?
更新:简化代码,用于再现异常
我报告过错误 - 请参阅[使用X509Certficate解密JWT令牌时发生IDX10659错误](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/615)。 – Bevan