Для ядра CotParameters DotNet требуется Windows Cryptographic API (CAPI) ТОЛЬКО при запуске модульного теста - PullRequest
0 голосов
/ 01 декабря 2018

У меня есть код подписи RSA256, работающий в основном приложении aspnet на Mac, просто отлично.

В моих модульных тестах я получаю сообщение об ошибке.

'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 голосов
/ 01 февраля 2019

Можете ли вы обновить Microsoft.IdentityModel.Protocols.OpenIdConnect до версии 5.4.0 и посмотреть, решит ли это вашу проблему?

<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="5.4.0" />
0 голосов
/ 06 декабря 2018

Кажется, что проблема в зависимости от <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"/>

...