Search code examples
c#asp.netdockerasp.net-corehash

.NET6 on Linux Docker after a certain time throw System.Security.Cryptography.CryptographicException: Error occurred during a cryptographic operation


We have an ASP.NET Core application running on .NET6 and inside a Linux Docker (mcr.microsoft.com/dotnet/aspnet:6.0).

We are not using Ms Identity as the auth framework but our own database tables. The password is stored with a salt hash and we use System.Security.Cryptography.ComputeHash() to validate it on user login.

After the application has about 1 month of uptime, this method call starts throwing a CryptographicException:

System.Security.Cryptography.CryptographicException: Error occurred during a cryptographic operation.
   at Internal.Cryptography.HashProviderDispenser.EvpHashProvider.FinalizeHashAndReset(Span`1 destination)
   at Internal.Cryptography.HashProvider.FinalizeHashAndReset()
   at System.Security.Cryptography.HashAlgorithm.CaptureHashCodeAndReinitialize()
   at MySystem.Security.Model.Hashing.VerifyHash(string data, string salt, string hash) in /src/MySystem/Security/Model/Hashing.cs:line 54

Call stack strangely doesn't point to ComputeHash(), but that's the method we call (we never call CaptureHashCodeAndReinitialize() directly).

We also have multiple instance of the service, and only one starts doing this at once, so it's not directly related to the uptime (but maybe the number of times it called the method?). The error also occurs for all users trying to login, so not related to stale cookies.

After restarting the docker, the errors stops and we are good again for another month.

We previously ran the same code on Windows Server and never encountered the issue.

I've see many different older threads about this errors, but most point to completely unrelated aspects. I've seen many talk about IIS, about browser cookies, about a machineKey entry in web.config of the old .NET Framework. None of that applies to my solution since we are using Linux Dockers and the Kestrel web server.

I can only think ONE special configuration that could be related but not directly. I have this code in my webhost configuration. This was done in order to support the "antiforgery token" in a distributed manner over multiple instances of the service using Redis as the persistance storage layer. But it is not directly related to the password hashing validation.

services.AddDataProtection()
    .PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(Settings.RedisAddress), "DataProtection-Keys")
    .SetApplicationName("ASP")
    .UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration()
    {
        EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
        ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
    });

Could the Linux Docker OS has some kind of backend service used for cryptography that fails to renew an expired key after a while?


Solution

  • A SHA512 instance is stateful, don't share it. Create a new instance when you calculate a new hash. That's probably your issue.