diff options
| author | Cody Robibero <cody@robibe.ro> | 2021-11-13 16:56:25 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-11-13 16:56:25 -0700 |
| commit | 34df1a030bdefad3b5b1ca0553a85f59d046326f (patch) | |
| tree | d9d123a0c1e65e58033a48e4b4c4932ad3c60780 /MediaBrowser.Common | |
| parent | 761a4e8415b2fc1023679c24ddd66fabf237abec (diff) | |
| parent | 5265b3eee794762b4de39a68b5bfbf767faaac36 (diff) | |
Merge pull request #6818 from Bond-009/password
Diffstat (limited to 'MediaBrowser.Common')
| -rw-r--r-- | MediaBrowser.Common/Cryptography/Constants.cs | 18 | ||||
| -rw-r--r-- | MediaBrowser.Common/Cryptography/CryptoExtensions.cs | 35 | ||||
| -rw-r--r-- | MediaBrowser.Common/Cryptography/PasswordHash.cs | 219 |
3 files changed, 0 insertions, 272 deletions
diff --git a/MediaBrowser.Common/Cryptography/Constants.cs b/MediaBrowser.Common/Cryptography/Constants.cs deleted file mode 100644 index 354114232..000000000 --- a/MediaBrowser.Common/Cryptography/Constants.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace MediaBrowser.Common.Cryptography -{ - /// <summary> - /// Class containing global constants for Jellyfin Cryptography. - /// </summary> - public static class Constants - { - /// <summary> - /// The default length for new salts. - /// </summary> - public const int DefaultSaltLength = 64; - - /// <summary> - /// The default amount of iterations for hashing passwords. - /// </summary> - public const int DefaultIterations = 1000; - } -} diff --git a/MediaBrowser.Common/Cryptography/CryptoExtensions.cs b/MediaBrowser.Common/Cryptography/CryptoExtensions.cs deleted file mode 100644 index 157b0ed10..000000000 --- a/MediaBrowser.Common/Cryptography/CryptoExtensions.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using System.Text; -using MediaBrowser.Model.Cryptography; -using static MediaBrowser.Common.Cryptography.Constants; - -namespace MediaBrowser.Common.Cryptography -{ - /// <summary> - /// Class containing extension methods for working with Jellyfin cryptography objects. - /// </summary> - public static class CryptoExtensions - { - /// <summary> - /// Creates a new <see cref="PasswordHash" /> instance. - /// </summary> - /// <param name="cryptoProvider">The <see cref="ICryptoProvider" /> instance used.</param> - /// <param name="password">The password that will be hashed.</param> - /// <returns>A <see cref="PasswordHash" /> instance with the hash method, hash, salt and number of iterations.</returns> - public static PasswordHash CreatePasswordHash(this ICryptoProvider cryptoProvider, string password) - { - byte[] salt = cryptoProvider.GenerateSalt(); - return new PasswordHash( - cryptoProvider.DefaultHashMethod, - cryptoProvider.ComputeHashWithDefaultMethod( - Encoding.UTF8.GetBytes(password), - salt), - salt, - new Dictionary<string, string> - { - { "iterations", DefaultIterations.ToString(CultureInfo.InvariantCulture) } - }); - } - } -} diff --git a/MediaBrowser.Common/Cryptography/PasswordHash.cs b/MediaBrowser.Common/Cryptography/PasswordHash.cs deleted file mode 100644 index 0e2065302..000000000 --- a/MediaBrowser.Common/Cryptography/PasswordHash.cs +++ /dev/null @@ -1,219 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Collections.Generic; -using System.Text; - -namespace MediaBrowser.Common.Cryptography -{ - // Defined from this hash storage spec - // https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md - // $<id>[$<param>=<value>(,<param>=<value>)*][$<salt>[$<hash>]] - // with one slight amendment to ease the transition, we're writing out the bytes in hex - // rather than making them a BASE64 string with stripped padding - public class PasswordHash - { - private readonly Dictionary<string, string> _parameters; - private readonly byte[] _salt; - private readonly byte[] _hash; - - public PasswordHash(string id, byte[] hash) - : this(id, hash, Array.Empty<byte>()) - { - } - - public PasswordHash(string id, byte[] hash, byte[] salt) - : this(id, hash, salt, new Dictionary<string, string>()) - { - } - - public PasswordHash(string id, byte[] hash, byte[] salt, Dictionary<string, string> parameters) - { - if (id == null) - { - throw new ArgumentNullException(nameof(id)); - } - - if (id.Length == 0) - { - throw new ArgumentException("String can't be empty", nameof(id)); - } - - Id = id; - _hash = hash; - _salt = salt; - _parameters = parameters; - } - - /// <summary> - /// Gets the symbolic name for the function used. - /// </summary> - /// <value>Returns the symbolic name for the function used.</value> - public string Id { get; } - - /// <summary> - /// Gets the additional parameters used by the hash function. - /// </summary> - public IReadOnlyDictionary<string, string> Parameters => _parameters; - - /// <summary> - /// Gets the salt used for hashing the password. - /// </summary> - /// <value>Returns the salt used for hashing the password.</value> - public ReadOnlySpan<byte> Salt => _salt; - - /// <summary> - /// Gets the hashed password. - /// </summary> - /// <value>Return the hashed password.</value> - public ReadOnlySpan<byte> Hash => _hash; - - public static PasswordHash Parse(ReadOnlySpan<char> hashString) - { - if (hashString.IsEmpty) - { - throw new ArgumentException("String can't be empty", nameof(hashString)); - } - - if (hashString[0] != '$') - { - throw new FormatException("Hash string must start with a $"); - } - - // Ignore first $ - hashString = hashString[1..]; - - int nextSegment = hashString.IndexOf('$'); - if (hashString.IsEmpty || nextSegment == 0) - { - throw new FormatException("Hash string must contain a valid id"); - } - else if (nextSegment == -1) - { - return new PasswordHash(hashString.ToString(), Array.Empty<byte>()); - } - - ReadOnlySpan<char> id = hashString[..nextSegment]; - hashString = hashString[(nextSegment + 1)..]; - Dictionary<string, string>? parameters = null; - - nextSegment = hashString.IndexOf('$'); - - // Optional parameters - ReadOnlySpan<char> parametersSpan = nextSegment == -1 ? hashString : hashString[..nextSegment]; - if (parametersSpan.Contains('=')) - { - while (!parametersSpan.IsEmpty) - { - ReadOnlySpan<char> parameter; - int index = parametersSpan.IndexOf(','); - if (index == -1) - { - parameter = parametersSpan; - parametersSpan = ReadOnlySpan<char>.Empty; - } - else - { - parameter = parametersSpan[..index]; - parametersSpan = parametersSpan[(index + 1)..]; - } - - int splitIndex = parameter.IndexOf('='); - if (splitIndex == -1 || splitIndex == 0 || splitIndex == parameter.Length - 1) - { - throw new FormatException("Malformed parameter in password hash string"); - } - - (parameters ??= new Dictionary<string, string>()).Add( - parameter[..splitIndex].ToString(), - parameter[(splitIndex + 1)..].ToString()); - } - - if (nextSegment == -1) - { - // parameters can't be null here - return new PasswordHash(id.ToString(), Array.Empty<byte>(), Array.Empty<byte>(), parameters!); - } - - hashString = hashString[(nextSegment + 1)..]; - nextSegment = hashString.IndexOf('$'); - } - - if (nextSegment == 0) - { - throw new FormatException("Hash string contains an empty segment"); - } - - byte[] hash; - byte[] salt; - - if (nextSegment == -1) - { - salt = Array.Empty<byte>(); - hash = Convert.FromHexString(hashString); - } - else - { - salt = Convert.FromHexString(hashString[..nextSegment]); - hashString = hashString[(nextSegment + 1)..]; - nextSegment = hashString.IndexOf('$'); - if (nextSegment != -1) - { - throw new FormatException("Hash string contains too many segments"); - } - - if (hashString.IsEmpty) - { - throw new FormatException("Hash segment is empty"); - } - - hash = Convert.FromHexString(hashString); - } - - return new PasswordHash(id.ToString(), hash, salt, parameters ?? new Dictionary<string, string>()); - } - - private void SerializeParameters(StringBuilder stringBuilder) - { - if (_parameters.Count == 0) - { - return; - } - - stringBuilder.Append('$'); - foreach (var pair in _parameters) - { - stringBuilder.Append(pair.Key) - .Append('=') - .Append(pair.Value) - .Append(','); - } - - // Remove last ',' - stringBuilder.Length -= 1; - } - - /// <inheritdoc /> - public override string ToString() - { - var str = new StringBuilder() - .Append('$') - .Append(Id); - SerializeParameters(str); - - if (_salt.Length != 0) - { - str.Append('$') - .Append(Convert.ToHexString(_salt)); - } - - if (_hash.Length != 0) - { - str.Append('$') - .Append(Convert.ToHexString(_hash)); - } - - return str.ToString(); - } - } -} |
