Edit :
Microsoft has published documentation summarizing this :
It isn't obvious for the package Microsoft.Extensions.Logging.Console. Let's look at Microsoft.Extensions.Identity.Core :
https://www.nuget.org/packages/Microsoft.Extensions.Identity.Core/3.1.5
See the csproj :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>ASP.NET Core Identity is the membership system for building ASP.NET Core...</Description>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
...
</PropertyGroup>
...
</Project>
This package target .NET Standard 2.0 and .NET Core 3.1 (value of the Azure DevOps variable $(DefaultNetCoreTargetFramework)).
The compile result in release is :
- bin/release/netstandard2.0/Microsoft.Extensions.Logging.Console.dll
- bin/release/netcoreapp3.1/Microsoft.Extensions.Logging.Console.dll
Two distinct dll are generated, but with what difference?
See the file PasswordHasher.cs :
public class PasswordHasher<TUser> : IPasswordHasher<TUser> where TUser : class
{
...
#if NETSTANDARD2_0
// Compares two byte arrays for equality. The method is specifically written so that the loop is not optimized.
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
private static bool ByteArraysEqual(byte[] a, byte[] b)
{
if (a == null && b == null)
{
return true;
}
if (a == null || b == null || a.Length != b.Length)
{
return false;
}
var areSame = true;
for (var i = 0; i < a.Length; i++)
{
areSame &= (a[i] == b[i]);
}
return areSame;
}
#endif
private static bool VerifyHashedPasswordV3(byte[] hashedPassword, string password, out int iterCount)
{
...
// Hash the incoming password and verify it
byte[] actualSubkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, subkeyLength);
#if NETSTANDARD2_0
return ByteArraysEqual(actualSubkey, expectedSubkey);
#elif NETCOREAPP
return CryptographicOperations.FixedTimeEquals(actualSubkey, expectedSubkey);
#else
#error Update target frameworks
#endif
}
}
For .NET Core 3.1, the method CryptographicOperations.FixedTimeEquals is used. But this method don't exists in .NET Standard 2.0. Then a not optimized method ByteArraysEqual is added in Microsoft.Extensions.Identity.Core.dll to replace the absent method.
When you use the package NuGet Microsoft.Extensions.identity.Core to check a hash password in :
. .NET Core 3.1 projet, you use the platform specific method CryptographicOperations.FixedTimeEquals.
. .NET Standard 2.0 compatible project, you use the not optimised method ByteArraysEqual.
Questions were :
Why .NET Core 3.1 target dependencies is specify?
The .NET Standard 2.0 generated dll is compatible with .NET Core 3.1 and can be sufficient, but target a specific platform this allows to use specific platform component that be more optimized.
Can I use this package in .NET Core 2.* application?
Same question to .NET 4.7 and .NET 4.8?
Yes, you can use this package in .NET Core 2.* because is compatible with .NET Standard 2.0, but you don't have the more optimized version.
Same answer to .NET Framework 4.7 and .NET Framework 4.8