2011-07-24 77 views
2

我即将推出新的在线服务的测试版。测试版用户将被发送一个唯一的“访问代码”,允许他们注册该服务。基于C#中的唯一字符串生成短代码

并非存储的接入码列表,我以为我会只是基于他们的电子邮件代码,因为这本身就是独一无二的。

我最初的想法是把一封带有唯一的字符串相结合,然后Base64编码。但是,我正在查找比较短的代码,例如5位数字。

+1

为什么不只是5个随机字符? –

+0

@nw:那么OP应该存储那些生成的5个字符。 –

+0

我试图避免存储任何东西。如果我可以生成代码,然后在注册时使用相同的算法验证代码和电子邮件,那将会更容易。 –

回答

5

如果访问码本身必须是唯一的,则很难确保碰撞。如果您可以容忍两个用户巧合地共享相同访问代码的情况,那么它变得更加容易。

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

一种方法是将电子邮件地址的SHA-1-HMAC散列(System.Cryptography.HMACSHA1)与一个已知的密钥进行比较。散列的输出是一个20字节的序列。然后您可以确定性地截断哈希。例如,在下面,GetCodeForEmail("[email protected]")给出'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(); 
} 
+0

谢谢。是的,我可以应付碰撞。重点是代码是从“批准的”电子邮件地址生成的。如果电子邮件地址未被批准,那么即使代码被泄露,人们也无法注册。关于base64编码,你是对的 - 我可以先对它进行加密,然后用base64进行编码,但是你的解决方案提供了一个很好的短代码。 –

+0

输出不是字符串,它是'byte []'。它将包含160位或正好20个字节。你从哪里获得64字节的长度? –

+0

而且你还弄乱了结果字符串......为什么不先拿第一位?所有这些与分部的数学在这里完全没有必要。这是散列算法的一项任务 - 确保即使输入的一小部分发生改变,_entire_ hash也应该不同。另外,你只会因为不相关的细节和增加问题的可能性而增加想法的负担。通常安全算法非常聪明是个不错的主意...... –

2

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

+2

我不认为碰撞会成为一个问题。看看git。通常5位数的SHA1哈希足以区分数千个提交。对于OP来说,如果发生罕见的碰撞,这并不是非常重要,至少从我的理解来看。 +1的想法。 –

+0

是的,如果有的话,碰撞很可能会很少。虽然我总是偏执狂,想想最糟糕的事情(尽管它在计算机世界中是件好事)。 –

0

所以,它听起来像你想在这里做的是创建一个特定的哈希函数发送的电子邮件@can poyragzoglu指出。一个很简单的一个可能是这个样子:

(伪代码) 的foreach炭下,在电子邮件: 运行总计+ = [大素] * [Unicode值]

那么就运行总计%大5数字编号

正如他指出的那样,除非您拥有出色的散列函数,否则这不会是唯一的。你可能会碰撞。不知道这是否重要。

什么似乎更容易对我来说,如果你已经知道有效的电子邮件,只需要检查用户的电子邮件对您在注册时有效问卷的名单?为什么要用代码呢?

如果你真的想要一个唯一的标识符不过,要做到这一点最简单的方法可能是只使用什么叫做GUID。 C#本地支持this。您可以将其存储在您的用户表中。尽管如此,用户永远不会记住/输出时间太长,如果这就是你想要做的事情,那么对于每个用户来说,这几乎肯定是独一无二的。