Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于C中的唯一字符串生成一个短代码#_C#_.net_Serial Number - Fatal编程技术网

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

C# 基于C中的唯一字符串生成一个短代码#,c#,.net,serial-number,C#,.net,Serial Number,我正要推出一项新在线服务的测试版。Beta版用户将被发送一个唯一的“访问代码”,允许他们注册该服务 与其存储访问代码列表,不如根据他们的电子邮件生成代码,因为这本身是唯一的 我最初的想法是将电子邮件与唯一的字符串组合,然后对其进行编码。然而,我一直在寻找短一点的代码,比如说5位数的代码。你可以从他们的电子邮件中创建一个特殊的哈希,它少于6个字符,但这并不能真正使它成为“唯一的”,在这么小的空间中总是会有冲突。我宁愿使用更长的键,或者将预先生成的代码存储在一个表中。所以,听上去您想在这里做的是像@

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

与其存储访问代码列表,不如根据他们的电子邮件生成代码,因为这本身是唯一的


我最初的想法是将电子邮件与唯一的字符串组合,然后对其进行编码。然而,我一直在寻找短一点的代码,比如说5位数的代码。

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

所以,听上去您想在这里做的是像@can poyragzoglu指出的那样,专门为电子邮件创建一个哈希函数。一个非常简单的示例可能如下所示:

(伪代码) 电子邮件中的foreach char c: 运行总计+=[大素数]*[unicode值]

然后运行总计%大的5位数

正如他所指出的,除非您有一个优秀的散列函数,否则这将不是唯一的。很可能会发生碰撞。不知道这是否重要

对我来说似乎更容易的是,如果你已经知道有效的电子邮件,那么在注册时只需对照你的有效电子邮件列表检查用户的电子邮件即可?为什么还要费心编写代码呢


如果您真的想要一个唯一的标识符,最简单的方法可能就是使用所谓的GUID。C#天生支持。您可以将其存储在用户表中。虽然,对于用户来说,记住/键入密码的时间太长,但如果您正试图这样做,那么几乎可以肯定每个密码都是唯一的。

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

按照建议,将电子邮件地址的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();
}
//定义密码中允许的字符。将长度设置为256
静态字符[]有效字符={'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
常量字符串hashkey=“密码”//HMAC功能的键--更改!
常量int代码长度=6;//密码长度
字符串GetCodeForEmail(字符串地址)
{
字节[]散列;
使用(HMACSHA1-sha1=new-HMACSHA1(ascienceoding.ASCII.GetBytes(hashkey)))
hash=sha1.ComputeHash(UTF8Encoding.UTF8.GetBytes(address));
int startpos=hash[hash.Length-1](hash.Length-code长度);
StringBuilder passbuilder=新的StringBuilder();
for(int i=startpos;i
@nw:那么OP应该存储生成的5个字符。我试图避免存储任何东西。如果我能生成一个代码,然后在注册时使用相同的算法来验证代码和电子邮件,那会更容易。我不认为冲突会成为问题。看看git。通常,SHA1散列的5位数字足以区分数千次提交。对于OP来说,是否会发生罕见的碰撞并不十分关键,至少从我的理解来看是这样+是的,如果有碰撞的话,很可能会很少。虽然我总是偏执,总是想着最坏的事情(尽管在电脑世界里这是件好事)。谢谢。是的,我能应付碰撞。主要的一点是,代码是从“批准”的电子邮件地址生成的。如果电子邮件地址未被批准,那么即使代码泄露,人们也无法注册。关于base64编码,您是对的-我可以先加密它,然后再对它进行base64编码,但是您的解决方案提供了一个很好的短代码。输出不是字符串,而是
字节[]
。它将包含160位或正好20个字节。您从何处获取64字节的长度?并且您还将结果字符串弄得一团糟。。。为什么不只取第一部分呢?所有这些带除法的数学在这里是完全不必要的。这是散列算法的任务——确保即使输入的一小部分发生了变化,整个散列也应该是不同的。随着更多的诡计,你只会用不相关的细节来增加想法的负担,并增加出现问题的可能性。一般来说,非常聪明地使用安全算法是个坏主意…@drf那么从安全角度来看,这可能是可以的。但是我宁愿使用类似于
String.Format(“{0:X}{1:X}{2:X}”、hash[0]、hash[1]、hash[2])
。它非常简单:)你的解决方案会减少碰撞的频率,但即使这样,它们也可以忽略不计+1,但对于准备就绪的实现。@EduardoXavier,这是因为其中一个哈希字节小于16,因此只占用一个字符,格式“X”不添加前导零。这就是为什么我说“类似的东西”——在浏览器中编写代码总是这样:)改为尝试
String.Format({0:X2}{1:X2}{2:X2})、hash[0]、hash[1]、hash[2])
。我们应该做到这一点。