Hash “alfanumérico” - A-Z, 0-9
Estou procurando uma função que gere um "hash alfanumérico". Dada uma string de origem, ela produz uma string de resultado determinada que pode conter qualquer letra a-z ou dígito 0-9 e não pode ser submetida a engenharia reversa para produzir a fonte. Isso será usado para gerar senhas para um sistema baseado em dados secretos, portanto, seqüências de caracteres entre 8 e 12 caracteres são ideais e um hash seguro também seria ideal.
Eu estou pensando que eu posso usar um hash bitwise normal, XOR-fold para 64 bits (se eu usar, por exemplo, SHA256) e, em seguida, tomar o resultado 5 bits de cada vez (produzindo um número 0-31) e procurar o código de caractere a ser usado em uma coleta ordenada indexada. Existem 26 letras e 10 dígitos, o que significa que terei que deixar alguns fora (provavelmente removendo caracteres que poderiam ser confundidos com outros se escritos à mão). 64 bits, 5 bits por vez, produzirão uma sequência de 12 caracteres com 4 bits restantes.
No entanto, estou preocupado com duas coisas: primeiro, introduzindo o preconceito tomando um número de bits sem potência de 2; e segundo, o que fazer com os bits restantes. Eu os uso como estão sabendo que haverá apenas 16 possibilidades, eu os deixo de fora (e perco dados possivelmente introduzindo viés), ou eu incorporo mais um bit para fazer uma string de 13 caracteres (e onde deve ser o último bit vem de onde)?
EDITAR: Aqui está a minha atual tentativa; ele pega um enumerável de bytes (como a matriz de bytes produzida pela maioria dos algoritmos hash) e retorna uma string:
/// <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();
}