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

Ben*_*ter 3 .net c# serial-number

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

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

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

drf*_*drf 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();
}
Run Code Online (Sandbox Code Playgroud)

  • @drf然后从安全点来看可能没问题.但我宁愿使用类似`String.Format("{0:X} {1:X} {2:X}",hash [0],hash [1],hash [2])的结果. .它是如此简单:)你的解决方案导致更少的碰撞,但即使这样,它们也可以忽略不计.+1虽然准备好了实施. (2认同)
  • @EduardoXavier,因为其中一个哈希字节小于16,因此仅使用一个字符,格式"X"不添加前导零.这就是为什么我说'类似' - 在浏览器中编写代码总是那样:)尝试`String.Format("{0:X2} {1:X2} {2:X2}",hash [0],hash [1],哈希[2])`而不是.应该做的伎俩. (2认同)