运行单元测试时,DotNet Core'CspParameters'仅需要Windows加密API(CAPI)

时间:2018-11-30 21:33:06

标签: macos security asp.net-core .net-core asp.net-identity

我在Mac上的aspnet核心应用程序中运行RSA256签名代码就很好了。

在我的单元测试中,我得到了错误。

'CspParameters' requires Windows Cryptographic API (CAPI) ONLY when running a unit test

我是否需要模拟或在单元测试中提供某些aspnet'ish才能使其正常工作?

public class SessionIdSecureDataFormat : ISessionIdSecureDataFormat
{
    private readonly IEnumerable<SecurityKey> _issuerSigningKeys;
    private readonly SecurityKey _privateKey;
    private readonly string _issuer;
    private readonly string _audience;

    public SessionIdSecureDataFormat(IEnumerable<SecurityKey> issuerSigningKeys, SecurityKey privateKey,
        string issuer, string audience)
    {
        _issuerSigningKeys = issuerSigningKeys;
        _privateKey = privateKey;
        _issuer = issuer;
        _audience = audience;
    }

    public string Protect(string data)
    {
        if (data == null)
        {
            return null;
        }

        var securityTokenDescriptor = new SecurityTokenDescriptor
        {
            SigningCredentials = new SigningCredentials(_privateKey, "RS256"),
            Issuer = _issuer,
            Audience = _audience,
        };
        var handler = new JwtSecurityTokenHandler();
        var jwt = handler.CreateJwtSecurityToken(securityTokenDescriptor);
        jwt.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Jti, data));
        return handler.WriteToken(jwt);
    }

    public string Protect(string data, string purpose)
    {
        return this.Protect(data);
    }

    public string Unprotect(string protectedText)
    {
        if (protectedText == null)
        {
            return null;
        }

        var handler = new JwtSecurityTokenHandler();
        var validationContext = new TokenValidationParameters
        {
            RequireExpirationTime = false,
            ValidateIssuerSigningKey = true,
            ValidateLifetime = true,
            IssuerSigningKeys = _issuerSigningKeys,
            ValidIssuer = _issuer,
            ValidAudience = _audience
        };
        handler.ValidateToken(protectedText, validationContext, out var jwt);
        return jwt.Id;
    }

    public string Unprotect(string protectedText, string purpose)
    {
        //TODO - It's not clear if we are supposed to check if the purpose matches our declared purpose. No documentation.
        return this.Unprotect(protectedText);
    }
}

Protect失败的单元测试设置。

public class SessionJwtDataProtectorTests
{
        private readonly byte[] _encodedJwt;
        private readonly byte[] _sessionIdOriginal;
        private readonly SessionJwtDataProtector _sessionJwtDataProtector;
        private readonly Mock<IServiceProvider> _provider = new Mock<IServiceProvider>();

        public SessionJwtDataProtectorTests()
        {
            var sessionIdSecureDataFormat = CreateSessionIdSecureDataFormat();
            _provider.Setup(p => p.GetService(typeof(ISessionJwtDataProtector)))
                .Returns(new SessionJwtDataProtector(_provider.Object, sessionIdSecureDataFormat));
            _sessionJwtDataProtector = new SessionJwtDataProtector(_provider.Object, sessionIdSecureDataFormat);
            var sessionId = Guid.NewGuid().ToString();
            _sessionIdOriginal = Encoding.UTF8.GetBytes(sessionId);
            _encodedJwt = _sessionJwtDataProtector.Protect(_sessionIdOriginal);
        }

    private static SessionIdSecureDataFormat CreateSessionIdSecureDataFormat()
    {
        var issuerKeys = new List<RsaSecurityKey>();
        foreach (var pemKey in StaticSessionPemKeys.ISSUER_KEYS)
        {
            RSA rsa = RSAHelper.PublicKeyFromPemString(pemKey.Pem);
            issuerKeys.Add(new RsaSecurityKey(rsa) {KeyId = pemKey.KeyId});
        }

        RSA privateKeyProvider = RSAHelper.PrivateKeyFromPemString(StaticSessionPemKeys.PRIVATE_KEY.Pem);
        var privateKey = new RsaSecurityKey(privateKeyProvider)
            {KeyId = StaticSessionPemKeys.PRIVATE_KEY.KeyId};
        return new SessionIdSecureDataFormat(issuerKeys, privateKey, "ABC", "ABC");
    }
}

2 个答案:

答案 0 :(得分:0)

问题似乎在于对 <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.3.0" />

请参阅 https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/1038

我通过删除此引用而改为引用来解决此问题 <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.1"/>

答案 1 :(得分:0)

可以在升级的 Microsoft.IdentityModel.Protocols.OpenIdConnect 的到5.4.0版本,看看是否能解决您的问题?

<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="5.4.0" />