基于C#中的唯一字符串生成短代码

时间:2011-07-24 22:21:04

标签: c# .net serial-number

我即将推出新的在线服务测试版。 Beta用户将被发送一个唯一的“访问代码”,允许他们注册该服务。

我认为我只会根据他们的电子邮件生成代码,而不是存储访问代码列表,因为这本身就是唯一的。

我最初的想法是将电子邮件与唯一字符串合并,然后Base64对其进行编码。但是,我正在寻找更短的代码,比如5位数。

3 个答案:

答案 0 :(得分:6)

如果访问代码本身需要是唯一的,则很难确保不会发生冲突。如果您能够容忍两个用户巧合地共享相同访问代码的情况,那么它就会变得非常容易。

如所建议的那样,将电子邮件地址的base-64编码与已知字符串连接在一起可能会引入安全漏洞。如果您使用与已知单词连接的电子邮件地址的base64输出,则用户可以对访问代码进行取消编码并派生用于生成代码的算法。

一种选择是使用已知密钥获取电子邮件地址的SHA-1-HMAC哈希(System.Cryptography.HMACSHA1)。散列的输出是20字节序列。然后,您可以确定性地截断哈希值。例如,在下文中,GetCodeForEmail("test@example.org")给出了代码'PE2WEG':

// define characters allowed in passcode.  set length so divisible into 256
static char[] ValidChars = {'2','3','4','5','6','7','8','9',
                   'A','B','C','D','E','F','G','H',
                   'J','K','L','M','N','P','Q',
                   'R','S','T','U','V','W','X','Y','Z'}; // len=32

const string hashkey = "password"; //key for HMAC function -- change!
const int codelength = 6; // lenth of passcode

string GetCodeForEmail(string address)
{
    byte[] hash;
    using (HMACSHA1 sha1 = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(hashkey)))
        hash = sha1.ComputeHash(UTF8Encoding.UTF8.GetBytes(address));
    int startpos = hash[hash.Length -1] % (hash.Length - codelength);
    StringBuilder passbuilder = new StringBuilder();
    for (int i = startpos; i < startpos + codelength; i++)
        passbuilder.Append(ValidChars[hash[i] % ValidChars.Length]);
    return passbuilder.ToString();
}

答案 1 :(得分:2)

您可以从他们的电子邮件中创建一个特殊的哈希值,这个哈希值少于6个字符,但它不会真正使其“独特”,在这么小的空间中总会发生冲突。我宁愿选择更长的密钥,也不要将预先生成的代码存储在表格中。

答案 2 :(得分:0)

所以,听起来你想要做的就是专门为电子邮件创建一个哈希函数,就像@can poyragzoglu指出的那样。一个非常简单的可能看起来像这样:

(伪代码) foreach char c in email: 总计+ = [大素数] * [unicode value]

然后运行总计%大5位数

正如他指出的那样,除非你有一个很好的哈希函数,否则这不会是唯一的。你很可能会发生碰撞。不确定这是否重要。

对我来说更容易的是,如果您已经知道有效的电子邮件,只需在注册后查看用户的电子邮件列表中的有效电子邮件?为什么要干扰代码呢?

如果你真的想要一个唯一的标识符,最简单的方法就是使用所谓的GUID。 C#本机支持this。您可以将其存储在Users表中。但是,对于用户来说,记住/输出的时间太长了,如果这是你想要做的事情,那么每个用户几乎肯定是唯一的。