CryptographyProvider.cs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Security.Cryptography;
  5. using MediaBrowser.Model.Cryptography;
  6. using static MediaBrowser.Model.Cryptography.Constants;
  7. namespace Emby.Server.Implementations.Cryptography
  8. {
  9. /// <summary>
  10. /// Class providing abstractions over cryptographic functions.
  11. /// </summary>
  12. public class CryptographyProvider : ICryptoProvider
  13. {
  14. /// <inheritdoc />
  15. public string DefaultHashMethod => "PBKDF2-SHA512";
  16. /// <inheritdoc />
  17. public PasswordHash CreatePasswordHash(ReadOnlySpan<char> password)
  18. {
  19. byte[] salt = GenerateSalt();
  20. return new PasswordHash(
  21. DefaultHashMethod,
  22. Rfc2898DeriveBytes.Pbkdf2(
  23. password,
  24. salt,
  25. DefaultIterations,
  26. HashAlgorithmName.SHA512,
  27. DefaultOutputLength),
  28. salt,
  29. new Dictionary<string, string>
  30. {
  31. { "iterations", DefaultIterations.ToString(CultureInfo.InvariantCulture) }
  32. });
  33. }
  34. /// <inheritdoc />
  35. public bool Verify(PasswordHash hash, ReadOnlySpan<char> password)
  36. {
  37. if (string.Equals(hash.Id, "PBKDF2", StringComparison.Ordinal))
  38. {
  39. return hash.Hash.SequenceEqual(
  40. Rfc2898DeriveBytes.Pbkdf2(
  41. password,
  42. hash.Salt,
  43. int.Parse(hash.Parameters["iterations"], CultureInfo.InvariantCulture),
  44. HashAlgorithmName.SHA1,
  45. 32));
  46. }
  47. if (string.Equals(hash.Id, "PBKDF2-SHA512", StringComparison.Ordinal))
  48. {
  49. return hash.Hash.SequenceEqual(
  50. Rfc2898DeriveBytes.Pbkdf2(
  51. password,
  52. hash.Salt,
  53. int.Parse(hash.Parameters["iterations"], CultureInfo.InvariantCulture),
  54. HashAlgorithmName.SHA512,
  55. DefaultOutputLength));
  56. }
  57. throw new NotSupportedException($"Can't verify hash with id: {hash.Id}");
  58. }
  59. /// <inheritdoc />
  60. public byte[] GenerateSalt()
  61. => GenerateSalt(DefaultSaltLength);
  62. /// <inheritdoc />
  63. public byte[] GenerateSalt(int length)
  64. {
  65. var salt = new byte[length];
  66. using var rng = RandomNumberGenerator.Create();
  67. rng.GetNonZeroBytes(salt);
  68. return salt;
  69. }
  70. }
  71. }