using System.Text;
namespace Bit.Core.Utilities;
public static class EnumerationProtectionHelpers
{
///
/// Use this method to get a consistent int result based on the inputString that is in the range.
/// The same inputString will always return the same index result based on range input.
///
/// Key used to derive the HMAC hash. Use a different key for each usage for optimal security
/// The string to derive an index result
/// The range of possible index values
/// An int between 0 and range - 1
public static int GetIndexForInputHash(byte[] hmacKey, string inputString, int range)
{
if (hmacKey == null || range <= 0 || hmacKey.Length == 0)
{
return 0;
}
else
{
// Compute the HMAC hash of the salt
var hmacMessage = Encoding.UTF8.GetBytes(inputString.Trim().ToLowerInvariant());
using var hmac = new System.Security.Cryptography.HMACSHA256(hmacKey);
var hmacHash = hmac.ComputeHash(hmacMessage);
// Convert the hash to a number
var hashHex = BitConverter.ToString(hmacHash).Replace("-", string.Empty).ToLowerInvariant();
var hashFirst8Bytes = hashHex[..16];
var hashNumber = long.Parse(hashFirst8Bytes, System.Globalization.NumberStyles.HexNumber);
// Find the default KDF value for this hash number
var hashIndex = (int)(Math.Abs(hashNumber) % range);
return hashIndex;
}
}
}