Hash "alfanumérico" - A-Z, 0-9
Estoy buscando una función que genere un "hash alfanumérico". Dada una cadena de origen, produce una cadena de resultado determinada que puede contener cualquier letra a-z o dígito 0-9, y no se puede realizar ingeniería inversa para producir la fuente. Esto se utilizará para generar contraseñas para un sistema basado en datos secretos, por lo que las cadenas de entre 8 y 12 caracteres son ideales y un hash seguro también sería ideal.
Estoy pensando que puedo usar un hash bit a bit normal, plegarlo XOR a 64 bits (si uso, por ejemplo, SHA256) y luego tomar el resultado de 5 bits a la vez (produciendo un número 0-31) y buscar El código de carácter a utilizar de una colección ordenada indexada. Hay 26 letras y 10 dígitos, lo que significa que tendré que omitir algunas (probablemente, eliminar caracteres que podrían confundirse con otros si están escritos a mano). 64 bits, 5 bits a la vez, producirán una cadena de 12 caracteres con 4 bits restantes.
Sin embargo, me preocupan dos cosas: primero, introducir el sesgo al tomar un número de bits de no poder de 2; y segundo, qué hacer con los bits sobrantes. ¿Los uso como está sabiendo que solo habrá 16 posibilidades, los dejo (y pierdo datos posiblemente introduciendo sesgo), o incorporo un bit más para formar una cadena de 13 caracteres (y dónde debería estar el último bit?) viene de)?
EDITAR: Aquí está mi puñalada actual; toma una cantidad de bytes (como la matriz de bytes producida por la mayoría de los algoritmos hash) y devuelve una cadena:
/// <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();
}