--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Diagnostics;
+using System.Security.Cryptography;
+
+namespace Internal.Cryptography
+{
+ internal partial class Pbkdf2Implementation
+ {
+ public static unsafe void Fill(
+ ReadOnlySpan<byte> password,
+ ReadOnlySpan<byte> salt,
+ int iterations,
+ HashAlgorithmName hashAlgorithmName,
+ Span<byte> destination)
+ {
+ Debug.Assert(!destination.IsEmpty);
+ Debug.Assert(hashAlgorithmName.Name is not null);
+ // Fall back to managed implementation since Android doesn't support the full Pbkdf2 APIs
+ // until API level 26.
+ using (Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(
+ password.ToArray(),
+ salt.ToArray(),
+ iterations,
+ hashAlgorithmName,
+ clearPassword: true,
+ requireMinimumSaltLength: false))
+ {
+ byte[] result = deriveBytes.GetBytes(destination.Length);
+ result.AsSpan().CopyTo(destination);
+ }
+ }
+ }
+}
<Compile Include="Internal\Cryptography\DesImplementation.Unix.cs" />
<Compile Include="Internal\Cryptography\HashProviderDispenser.Unix.cs" />
<Compile Include="Internal\Cryptography\OpenSslCipher.cs" />
- <Compile Condition="'$(TargetsBrowser)' != 'true'" Include="Internal\Cryptography\RandomNumberGeneratorImplementation.Unix.cs" />
- <Compile Condition="'$(TargetsBrowser)' != 'true'" Include="Internal\Cryptography\Pbkdf2Implementation.Unix.cs" />
+ <Compile Include="Internal\Cryptography\RandomNumberGeneratorImplementation.Unix.cs" />
<Compile Include="Internal\Cryptography\TripleDesImplementation.Unix.cs" />
</ItemGroup>
<ItemGroup Condition="'$(UseAppleCrypto)' == 'true'">
Link="Common\System\Security\Cryptography\RSAOpenSsl.cs" />
<Compile Include="Internal\Cryptography\RC2Implementation.Unix.cs" />
<Compile Include="System\Security\Cryptography\ECDiffieHellman.Create.OpenSsl.cs" />
+ <Compile Include="Internal\Cryptography\Pbkdf2Implementation.Unix.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Security.Cryptography.Native\Interop.Dsa.cs"
Link="Common\Interop\Unix\System.Security.Cryptography.Native\Interop.Dsa.cs" />
<Compile Include="$(CommonPath)System\Security\Cryptography\DSAOpenSsl.cs"
<Compile Include="System\Security\Cryptography\ECDiffieHellman.Create.Android.cs" />
<Compile Include="System\Security\Cryptography\ECDsa.Create.Android.cs" />
<Compile Include="System\Security\Cryptography\RSA.Create.Android.cs" />
+ <Compile Include="Internal\Cryptography\Pbkdf2Implementation.Android.cs" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetsBrowser)' == 'true'">
<Compile Include="$(CommonPath)Internal\Cryptography\HashProvider.cs"
}
public Rfc2898DeriveBytes(byte[] password, byte[] salt, int iterations, HashAlgorithmName hashAlgorithm)
- :this(password, salt, iterations, hashAlgorithm, clearPassword: false)
+ :this(password, salt, iterations, hashAlgorithm, clearPassword: false, requireMinimumSaltLength: true)
{
}
}
public Rfc2898DeriveBytes(string password, byte[] salt, int iterations, HashAlgorithmName hashAlgorithm)
- : this(Encoding.UTF8.GetBytes(password), salt, iterations, hashAlgorithm, clearPassword: true)
+ : this(Encoding.UTF8.GetBytes(password), salt, iterations, hashAlgorithm, clearPassword: true, requireMinimumSaltLength: true)
{
}
Initialize();
}
- private Rfc2898DeriveBytes(byte[] password, byte[] salt, int iterations, HashAlgorithmName hashAlgorithm, bool clearPassword)
+ internal Rfc2898DeriveBytes(byte[] password, byte[] salt, int iterations, HashAlgorithmName hashAlgorithm, bool clearPassword, bool requireMinimumSaltLength)
{
if (salt is null)
throw new ArgumentNullException(nameof(salt));
- if (salt.Length < MinimumSaltSize)
+ if (requireMinimumSaltLength && salt.Length < MinimumSaltSize)
throw new ArgumentException(SR.Cryptography_PasswordDerivedBytes_FewBytesSalt, nameof(salt));
if (iterations <= 0)
throw new ArgumentOutOfRangeException(nameof(iterations), SR.ArgumentOutOfRange_NeedPosNum);