"字母数字"哈希 - A-Z,0-9 [英] "Alphanumeric" hash - A-Z, 0-9
问题描述
我正在寻找一个将生成字母数字散列的函数。给定一个源字符串,它会生成一个确定的结果字符串,该字符串可以包含任何字母a-z或数字0-9,并且不能进行反向工程以生成源。这将用于为基于秘密数据的系统生成密码,因此8到12个字符之间的字符串是理想的,并且安全散列也是理想的。
I'我认为我可以使用正常的按位散列,XOR将它折叠为64位(如果我使用例如SHA256),然后每次取得5位结果(产生数字0-31)并查找字符从索引的有序集合中使用的代码。有26个字母和10个数字,这意味着我将不得不留下几个字符(可能会删除可能被别人误认为是手写的字符)。 64位,一次5位,将产生一个12位字符串,剩下4位。
然而,我担心两件事情:首先,介绍通过采用非2的幂数来实现偏置;其次,如何处理剩余的部分。如果我知道只有16种可能性,我是否将它们关闭(并丢失了可能引入偏见的数据),或者是否再加入一个13位字符串(以及最后一位应该放在哪里)来自)?
编辑:这是我当前的刺伤;它需要一个可枚举的字节(比如大多数散列算法产生的字节数组),并返回一个字符串:
///< ;总结>
///将一个IEnumerable字节转换为字符串表示形式,除l,o,q和z外,还可以包含任何小写字母a-z以及任何数字0-9。
///一次使用字节数组的5个位来产生从0到31的数字,然后将其转换为字母或数字。
///< / summary>
///< param name =toConvert>要转换的字节数组。< / param>
///< returns>一个字符串,包含数组中字节的字母数字不区分大小写表示。< / 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', '','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
{
//这是主要问题;包括,还是不包括?
if(bufferLength> 0)
builder.Append(chars [buffer]);
休息;
}
}
}
return builder.ToString();
}
生成SHA256和然后 Base36 编码结果?没有遗漏位,没有偏见...
这样,你就拥有一个经过验证的算法的加密强度(记住盐和使用多个哈希迭代)以及字母数字您需要的代表。
I'm looking for a function that will generate an "alphanumeric hash". Given a source string, it produces a determinate result string that can contain any letter a-z or digit 0-9, and cannot be reverse-engineered to produce the source. This will be used to generate passwords for a system based on secret data, so strings between 8 and 12 characters are ideal and a secure hash would also be ideal.
I'm thinking I can use a normal bitwise hash, XOR-fold it to 64 bits (if I use, for instance, SHA256) and then take the result 5 bits at a time (producing a number 0-31) and look up the character code to use from an indexed ordered collection. There are 26 letters and 10 digits meaning I'll have to leave a few out (probably removing characters that could be mistaken for others if handwritten). 64 bits, 5 bits at a time, will produce a 12-character string with 4 bits left over.
However, I'm worried about two things: first, introducing bias by taking a non-power-of-2 number of bits; and second, what to do with the leftover bits. Do I use them as-is knowing there will only be 16 possibilities, do I leave them off (and lose data possibly introducing bias), or do I incorporate one more bit to make a 13-character string (and where should the last bit come from)?
EDIT: Here's my current stab at it; it takes an enumerable of bytes (like the byte array produced by most hash algorithms) and returns a 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();
}
How about generating your SHA256 and then Base36 encoding the result? No left over bits, no bias...
That way you have the cryptographic strength of a proven algorithm (remember to salt and use multiple hash iterations) along with the alphanumeric representation that you need.
这篇关于"字母数字"哈希 - A-Z,0-9的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!