"字母数字"哈希 - A-Z,0-9 [英] "Alphanumeric" hash - A-Z, 0-9

查看:183
本文介绍了"字母数字"哈希 - 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.

这篇关于&QUOT;字母数字&QUOT;哈希 - A-Z,0-9的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆