Буквенно-цифровой хеш - A-Z, 0-9
Я ищу функцию, которая будет генерировать "буквенно-цифровой хэш". Учитывая исходную строку, она создает определенную результирующую строку, которая может содержать любую букву a-z или цифру 0-9 и не может быть подвергнута обратной обработке для получения источника. Это будет использоваться для генерации паролей для системы на основе секретных данных, поэтому идеально подходят строки длиной от 8 до 12 символов, а также безопасный хэш.
Я думаю, что могу использовать обычный побитовый хеш, XOR-сгибать его до 64 бит (если я использую, например, SHA256), а затем брать результат по 5 бит за раз (производя число 0-31) и искать код символа для использования из индексированной упорядоченной коллекции. Имеется 26 букв и 10 цифр, означающих, что мне придется пропустить несколько символов (возможно, удаляя символы, которые могут быть ошибочно приняты за другие, если они написаны от руки). 64 бита, по 5 бит за раз, создадут 12-символьную строку с оставшимися 4 битами.
Однако меня волнуют две вещи: во-первых, введение смещения путем взятия числа битов, не равных 2; и во-вторых, что делать с оставшимися битами. Использую ли я их как есть, зная, что будет только 16 возможностей, оставлю ли я их без (и потеряю данные, возможно, приводя к смещению), или добавлю еще один бит, чтобы создать строку из 13 символов (и где должен быть последний бит родом из)?
EDIT: Вот мой текущий удар по нему; он принимает множество байтов (например, байтовый массив, созданный большинством хеш-алгоритмов) и возвращает строку:
/// <summary>
/// Converts an IEnumerable of bytes to a string representation which can have any lowercase letter a-z except for l, o, q and z, and any digit 0-9.
/// Uses 5 bits of the byte array at a time to generate numbers from 0 to 31, which are then translated to letters or numbers.
/// </summary>
/// <param name="toConvert">the byte array to convert.</param>
/// <returns>A string containing the alphanumeric case-insensitive representation of the bytes in the array.</returns>
public static string ToInsensitiveAlphaNumericString(this IEnumerable<byte> toConvert)
{
var chars = new[]
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'p', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};
var enumerator = toConvert.GetEnumerator();
enumerator.MoveNext();
int buffer = enumerator.Current;
short bufferLength = 8;
const int valueLength = 5;
var builder = new StringBuilder();
while (true)
{
var value = buffer >> (bufferLength - valueLength);
builder.Append(chars[value]);
buffer = buffer - (value << (bufferLength - valueLength));
bufferLength -= valueLength;
if(bufferLength < valueLength )
{
if (enumerator.MoveNext())
{
buffer = (buffer << 8) + enumerator.Current;
bufferLength += 8;
}
else
{
//here's the main question; to include, or not to include?
if (bufferLength > 0)
builder.Append(chars[buffer]);
break;
}
}
}
return builder.ToString();
}