jellyfin/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs

79 lines
2.6 KiB
C#
Raw Normal View History

2019-02-20 09:17:30 +00:00
using System;
using System.Collections.Generic;
using System.Globalization;
2019-02-20 09:17:30 +00:00
using System.Security.Cryptography;
using MediaBrowser.Model.Cryptography;
using static MediaBrowser.Model.Cryptography.Constants;
2019-02-20 09:17:30 +00:00
namespace Emby.Server.Implementations.Cryptography
{
2019-11-01 17:38:54 +00:00
/// <summary>
/// Class providing abstractions over cryptographic functions.
/// </summary>
2021-10-08 13:02:58 +00:00
public class CryptographyProvider : ICryptoProvider
2019-02-20 09:17:30 +00:00
{
2019-11-01 17:38:54 +00:00
/// <inheritdoc />
public string DefaultHashMethod => "PBKDF2-SHA512";
2019-05-21 17:28:34 +00:00
2019-11-01 17:38:54 +00:00
/// <inheritdoc />
public PasswordHash CreatePasswordHash(ReadOnlySpan<char> password)
2019-02-20 09:17:30 +00:00
{
byte[] salt = GenerateSalt();
return new PasswordHash(
DefaultHashMethod,
Rfc2898DeriveBytes.Pbkdf2(
password,
salt,
DefaultIterations,
HashAlgorithmName.SHA512,
DefaultOutputLength),
salt,
new Dictionary<string, string>
{
{ "iterations", DefaultIterations.ToString(CultureInfo.InvariantCulture) }
});
2019-02-20 09:17:30 +00:00
}
2019-11-01 17:38:54 +00:00
/// <inheritdoc />
public bool Verify(PasswordHash hash, ReadOnlySpan<char> password)
2019-02-20 09:17:30 +00:00
{
if (string.Equals(hash.Id, "PBKDF2", StringComparison.Ordinal))
{
return hash.Hash.SequenceEqual(
Rfc2898DeriveBytes.Pbkdf2(
password,
hash.Salt,
int.Parse(hash.Parameters["iterations"], CultureInfo.InvariantCulture),
HashAlgorithmName.SHA1,
32));
}
if (string.Equals(hash.Id, "PBKDF2-SHA512", StringComparison.Ordinal))
{
return hash.Hash.SequenceEqual(
Rfc2898DeriveBytes.Pbkdf2(
password,
hash.Salt,
int.Parse(hash.Parameters["iterations"], CultureInfo.InvariantCulture),
HashAlgorithmName.SHA512,
DefaultOutputLength));
}
throw new NotSupportedException($"Can't verify hash with id: {hash.Id}");
2019-02-20 09:17:30 +00:00
}
2019-11-01 17:38:54 +00:00
/// <inheritdoc />
2019-02-20 09:17:30 +00:00
public byte[] GenerateSalt()
=> GenerateSalt(DefaultSaltLength);
2019-11-01 17:38:54 +00:00
/// <inheritdoc />
public byte[] GenerateSalt(int length)
{
var salt = new byte[length];
using var rng = RandomNumberGenerator.Create();
rng.GetNonZeroBytes(salt);
return salt;
}
2019-02-20 09:17:30 +00:00
}
}