我想为草稿纸创建密码和序列号,我已经生成了唯一的10位数字,现在我想将这个10位数字转换为16位数字(最后用校验位)。问题是执行此操作的功能应该是可逆的,因此通过查看16位数字我可以检查它是否有效。(如果它不是由我生成它应该是无效的)。 这就是我生成10位唯一随机码的方法:
Guid PinGuid;
byte[] Arr;
UInt32 PINnum = 0;
while (PINnum.ToString().Length != 10)
{
PinGuid = Guid.NewGuid();
Arr = PinGuid.ToByteArray();
PINnum = BitConverter.ToUInt32(Arr, 0);
}
return PINnum.ToString();
如果你能给我一个如何做的提示,我将不胜感激。
答案 0 :(得分:3)
首先,我会避免使用GUID,因为有些前缀是为特殊应用程序保留的。这意味着GUID的这些区域可能无法在创建时统一分配,因此您可能无法获得与计划相同的10位随机性。
此外,由于你的循环等待GUID变得合适,你可以更有效地完成它。
10 digits = 10**10
Log_2(10) = approx 3322/1000
因此,对于10位数字,您需要大约33位。由于您希望您的数字正好是10位数,因此您可以使用前导零填充小于10 ^ 10的数字,或者您只能生成介于10 ^ 9和10 ^ 10 - 1之间的数字。
如果采用后一种情况,你的空间需要9 * 10 ^ 9个数字 - 给你1个数字,然后是9个零,最多9个,然后是9个9。
然后,您希望将此数字空间转换为更大的空间,将其扩展5倍,并将另外一位数作为校验位。
选择一个校验位功能作为你喜欢的任何东西。你可以简单地对原始的10位数进行求和(mod 10),或者选择更复杂的东西。
据推测,您不希望人们能够生成有效的实例。因此,如果您真的认真对待您的安全性,那么在部署之前,您应该修改从网络获得的任何建议。
我会按照以下方式做点什么:
通过
生成一个统一的10位数,没有前导零randomTenDigits = 10 ** 9 + rand(9 * 10 ** 9)
使用加密方案(如AES 256甚至RSA或El-Gamal,因为它们的速度较慢,因为输入长度很小,所以不会那么重要)使用密钥加密这个10位数字只有你和其他人你信任意识到。也许你可以将10位数字连接10次,然后将结果与你选择的其他秘密连接起来,然后最后加密这个10位数字所属的扩展秘密。
选择生成的密文的5位数(约17位),并将这些数字附加到10位数字上。
通过您想要的任何方法生成1位数的校验位。
正如您将注意到,此方案的真正安全性不是来自校验位,而是来自您可以用来验证16位数字的密钥。您将用于验证它的测试是:当与我拥有的其他秘密连接时,给定的10位数字,使用我知道的秘密密钥加密到给出的给定的5位数字。
由于攻击者伪造你的一个号码的难度取决于
的难度但是,如果数字是不可协商的,并且基本空间的10位数字也是不可协商的,那么这样做可能是最安全的。您可以设置系统以阻止人们强制使用它,但您应该考虑如果有人通过供应商获取您的硬件,会怎样。我相信设计安全性比设计安全更容易,可以检测人们试图强行查询你的系统。
然而,如果严肃的面团在线(如数百万),你所使用的安全应该是一流的。相当于您用来保护PIN码到百万美元银行账户的安全性。您越安全,您就可以在信誉和信任的基础上继续开展业务。
所以沿着这些方向我建议增加你的秘密的大小,使某人只是尝试所有组合并伪造一个有效的组合是不可行的,特别是考虑如何设计你的系统使其难以打破有很多技能和动力(钱)的人。你真的不能太小心。
答案 1 :(得分:0)
我会保持简单。将PINnum.ToString()放入缓冲区。以5个间隔放置填充数字。前四个可能是随机垃圾,最后一个可能是一个校验位,或者您可以使每个填充符为其部分的校验位。这是一个例子。
buf = PINnum.ToString();
int chkdgit =创建你的checkdigit的函数
随机rnd = new Random(); int i = rnd.Next(1001,9999);
fillbuf = i.toString(); return buf [0] + buf [1] + fillbuf [0] + buf [2] .... chkdgit.toString();
这是一种相当简单的方法,但如果你的安全需求不是1级,那就足够了