2017-05-07 103 views
3

我创建一个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令牌的正确方法?或者,这个问题的解决方法是什么?

更新:简化代码,用于再现异常

回答

0

尝试使用:

new RsaSecurityKey(certificate.GetRSAPrivateKey().ExportParameters(true)); 

,而不是X509SecurityKey

似乎有在它不允许RSA密钥JIT的解缠实现中的错误。

+0

我报告过错误 - 请参阅[使用X509Certficate解密JWT令牌时发生IDX10659错误](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/615)。 – Bevan