aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/Cryptography/CryptographyProvider.cs')
-rw-r--r--Emby.Server.Implementations/Cryptography/CryptographyProvider.cs88
1 files changed, 71 insertions, 17 deletions
diff --git a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs
index 09fdbc856..673810c49 100644
--- a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs
+++ b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs
@@ -1,40 +1,94 @@
using System;
-using System.IO;
+using System.Collections.Generic;
using System.Security.Cryptography;
-using System.Text;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Model.Cryptography;
+using static MediaBrowser.Common.Cryptography.Constants;
namespace Emby.Server.Implementations.Cryptography
{
+ /// <summary>
+ /// Class providing abstractions over cryptographic functions.
+ /// </summary>
public class CryptographyProvider : ICryptoProvider
{
- public Guid GetMD5(string str)
- {
- return new Guid(ComputeMD5(Encoding.Unicode.GetBytes(str)));
- }
+ // FIXME: When we get DotNet Standard 2.1 we need to revisit how we do the crypto
+ // Currently supported hash methods from https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptoconfig?view=netcore-2.1
+ // there might be a better way to autogenerate this list as dotnet updates, but I couldn't find one
+ // Please note the default method of PBKDF2 is not included, it cannot be used to generate hashes cleanly as it is actually a pbkdf with sha1
+ private static readonly HashSet<string> _supportedHashMethods = new HashSet<string>()
+ {
+ "MD5",
+ "System.Security.Cryptography.MD5",
+ "SHA",
+ "SHA1",
+ "System.Security.Cryptography.SHA1",
+ "SHA256",
+ "SHA-256",
+ "System.Security.Cryptography.SHA256",
+ "SHA384",
+ "SHA-384",
+ "System.Security.Cryptography.SHA384",
+ "SHA512",
+ "SHA-512",
+ "System.Security.Cryptography.SHA512"
+ };
+
+ /// <inheritdoc />
+ public string DefaultHashMethod => "PBKDF2";
- public byte[] ComputeSHA1(byte[] bytes)
+ /// <inheritdoc />
+ public IEnumerable<string> GetSupportedHashMethods()
+ => _supportedHashMethods;
+
+ private byte[] PBKDF2(string method, byte[] bytes, byte[] salt, int iterations)
{
- using (var provider = SHA1.Create())
+ // downgrading for now as we need this library to be dotnetstandard compliant
+ // with this downgrade we'll add a check to make sure we're on the downgrade method at the moment
+ if (method != DefaultHashMethod)
{
- return provider.ComputeHash(bytes);
+ throw new CryptographicException($"Cannot currently use PBKDF2 with requested hash method: {method}");
}
+
+ using var r = new Rfc2898DeriveBytes(bytes, salt, iterations);
+ return r.GetBytes(32);
}
- public byte[] ComputeMD5(Stream str)
+ /// <inheritdoc />
+ public byte[] ComputeHash(string hashMethod, byte[] bytes, byte[] salt)
{
- using (var provider = MD5.Create())
+ if (hashMethod == DefaultHashMethod)
{
- return provider.ComputeHash(str);
+ return PBKDF2(hashMethod, bytes, salt, DefaultIterations);
}
- }
- public byte[] ComputeMD5(byte[] bytes)
- {
- using (var provider = MD5.Create())
+ if (!_supportedHashMethods.Contains(hashMethod))
{
- return provider.ComputeHash(bytes);
+ throw new CryptographicException($"Requested hash method is not supported: {hashMethod}");
}
+
+ using var h = HashAlgorithm.Create(hashMethod) ?? throw new ResourceNotFoundException($"Unknown hash method: {hashMethod}.");
+ if (salt.Length == 0)
+ {
+ return h.ComputeHash(bytes);
+ }
+
+ byte[] salted = new byte[bytes.Length + salt.Length];
+ Array.Copy(bytes, salted, bytes.Length);
+ Array.Copy(salt, 0, salted, bytes.Length, salt.Length);
+ return h.ComputeHash(salted);
}
+
+ /// <inheritdoc />
+ public byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt)
+ => PBKDF2(DefaultHashMethod, bytes, salt, DefaultIterations);
+
+ /// <inheritdoc />
+ public byte[] GenerateSalt()
+ => GenerateSalt(DefaultSaltLength);
+
+ /// <inheritdoc />
+ public byte[] GenerateSalt(int length)
+ => RandomNumberGenerator.GetBytes(length);
}
}