using System;
using System.Collections.Generic;
using MediaBrowser.Model.Cryptography;
namespace Jellyfin.Plugin.WatchedTogether.Tests;
///
/// A crypto provider that accepts exactly the (stored hash, submitted password) pairs it is given.
///
///
/// Hand-written rather than mocked: takes a
/// ReadOnlySpan<char>, and a ref struct cannot be used as a generic type argument to
/// Moq's It.IsAny<T>.
///
public sealed class StubCryptoProvider : ICryptoProvider
{
private readonly IReadOnlyList<(string Hash, string Password)> _validPairs;
public StubCryptoProvider(IReadOnlyList<(string Hash, string Password)> validPairs)
{
_validPairs = validPairs;
}
public string DefaultHashMethod => "PBKDF2-SHA512";
public bool Verify(PasswordHash hash, ReadOnlySpan password)
{
var candidate = password.ToString();
// Identify the stored credential by its salt rather than by re-formatting the whole hash,
// which need not round-trip through Parse/ToString byte for byte.
var salt = Convert.ToHexString(hash.Salt);
foreach (var (validHash, validPassword) in _validPairs)
{
var expectedSalt = validHash.Split('$')[3];
if (string.Equals(salt, expectedSalt, StringComparison.OrdinalIgnoreCase)
&& candidate == validPassword)
{
return true;
}
}
return false;
}
public PasswordHash CreatePasswordHash(ReadOnlySpan password)
=> throw new NotSupportedException();
public byte[] GenerateSalt() => throw new NotSupportedException();
public byte[] GenerateSalt(int length) => throw new NotSupportedException();
}