Could not load file or assembly 'System.Security.Cryptography.Algorithms, Version = 4.1.0.0

Carlos28 picture Carlos28 · Sep 5, 2017 · Viewed 22.4k times · Source

I'm trying to use System.Security.Cryptography.RNGCryptoServiceProvider class in my .NET Standard 1.4 library and according to this topic my code looks like this:

    private byte[] GenerateRandomNumber(int length)
    {
        using (var randomNumberGenerator = RandomNumberGenerator.Create())
        {
            var number = new byte[length];
            randomNumberGenerator.GetBytes(number);

            return number;
        }
    }

I have also installed from NuGet libraries:

  • System.Security.Cryptography.Algorithms v=4.3.0
  • System.Security.Cryptography.Primitives v=4.3.0

But trying fire it up gives me:

'Could not load file or package' System.Security.Cryptography.Algorithms, Version = 4.1.0.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a 'or one of its dependencies. The specified file could not be found. '

And on NuGet page there is no 4.1.0.0 version, only 4.1.0-rc2-24027 and after installing this version I get exact same exception.

What is wrong?

Edit: Switching from .NET Standard 1.4 to 1.6 didn't help

Edit2:

When I hit F12 on RandomNumberGenerator:

#region Assembly System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// C:\Users\x.y\.nuget\packages\system.security.cryptography.algorithms\4.3.0\ref\netstandard1.4\System.Security.Cryptography.Algorithms.dll
#endregion

namespace System.Security.Cryptography
{
    public abstract class RandomNumberGenerator : IDisposable
    {
        protected RandomNumberGenerator();

        public static RandomNumberGenerator Create();
        public void Dispose();
        public abstract void GetBytes(byte[] data);
        protected virtual void Dispose(bool disposing);
    }
}

So it wants 4.1.0 version (that not exists on NuGet) but path is set for 4.3.0

Answer

Martin Liversage picture Martin Liversage · Sep 5, 2017

In addition to having a .NET Standard library you also have an application (like a console application) or perhaps a test project. The platform for the application determines what specific assembly referenced by your .NET Standard library to load.

So your library references System.Security.Cryptography.Algorithms 4.3.0 however the actual version of the assembly to load for your platform may be 4.1.0 (that is the version you get on .NET Framework 4.6.1).

So you need to inform your application to redirect the desired version (4.3.0) to the actual version for your runtime (4.1.0). You can do that in the app.config file. Remember that this file is used by the application and not the library. Adding an app.config file to your library will not make a difference.

I tried to create a small project like the one you describe that in addition to a .NET Standard 1.4 library that references System.Security.Cryptography.Algorithms 4.3.0 has a NET Framework 4.62 console application and I had to include an app.config file with the following contents for this to work:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
  </startup>

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.1.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Security.Cryptography.Algorithms" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.1.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

Anecdotally, this seems to be less of a problem if you switch to .NET Standard 2.0.