"Alphanumerischer" Hash - A-Z, 0-9
Ich suche nach einer Funktion, die einen "alphanumerischen Hash" generiert. Wenn eine Quellzeichenfolge angegeben wird, wird eine bestimmte Ergebniszeichenfolge erstellt, die einen Buchstaben von a bis z oder eine Ziffer von 0 bis 9 enthalten kann und nicht rückentwickelt werden kann, um die Quelle zu erstellen. Dies wird verwendet, um Kennwörter für ein System zu generieren, das auf geheimen Daten basiert. Daher sind Zeichenfolgen zwischen 8 und 12 ideal und ein sicherer Hash wäre ebenfalls ideal.
Ich denke, ich kann einen normalen bitweisen Hash verwenden, ihn durch XOR auf 64 Bit falten (wenn ich zum Beispiel SHA256 verwende) und dann das Ergebnis 5 Bit auf einmal nehmen (eine Zahl von 0-31 erzeugen) und nachschlagen Der zu verwendende Zeichencode aus einer indizierten geordneten Sammlung. Es gibt 26 Buchstaben und 10 Ziffern, was bedeutet, dass ich ein paar weglassen muss (wahrscheinlich um Zeichen zu entfernen, die bei Handschrift mit anderen verwechselt werden könnten). 64 Bits, jeweils 5 Bits, erzeugen eine 12-stellige Zeichenfolge mit 4 verbleibenden Bits.
Ich mache mir jedoch Sorgen um zwei Dinge: Erstens das Einführen einer Verzerrung durch Verwenden einer Anzahl von Bits, die nicht der Potenz von 2 entspricht; und zweitens, was mit den übrig gebliebenen Bits zu tun ist. Verwende ich sie in dem Wissen, dass es nur 16 Möglichkeiten gibt, lasse ich sie aus (und verliere Daten, die möglicherweise eine Verzerrung verursachen), oder baue ich ein weiteres Bit ein, um eine Zeichenfolge mit 13 Zeichen zu erstellen (und wo sollte das letzte Bit sein?)? komme aus)?
BEARBEITEN: Hier ist mein aktueller Versuch; Es benötigt eine Anzahl von Bytes (wie das von den meisten Hash-Algorithmen erzeugte Byte-Array) und gibt eine Zeichenfolge zurück:
/// <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();
}