在C#.NET中生成密码重置链接

在C#.NET中生成密码重置链接,.net,.net,我今天一定是被谷歌屏蔽了,因为我找不到一个常见问题的答案。我正在我的网站上编写密码重置部分,我想通过电子邮件向用户发送一个包含128个熵字符后缀的URL,该URL将用于确认新密码的生成。我环顾四周,不推荐使用Random函数,因为它不够随机,所以我正在考虑使用RNGCryptoServiceProvider生成密钥。但是,我似乎无法使用它来生成合适的128字符字符串 我已经开始尝试了 byte[] linkBytes = new byte[128]; System.Securit

我今天一定是被谷歌屏蔽了,因为我找不到一个常见问题的答案。我正在我的网站上编写密码重置部分,我想通过电子邮件向用户发送一个包含128个熵字符后缀的URL,该URL将用于确认新密码的生成。我环顾四周,不推荐使用Random函数,因为它不够随机,所以我正在考虑使用RNGCryptoServiceProvider生成密钥。但是,我似乎无法使用它来生成合适的128字符字符串

我已经开始尝试了

byte[] linkBytes = new byte[128];
        System.Security.Cryptography.RNGCryptoServiceProvider rngCrypto = new System.Security.Cryptography.RNGCryptoServiceProvider();
        rngCrypto.GetBytes(linkBytes);
        string text128 = Convert.ToBase64String(linkBytes);
        string text128Enc = Uri.EscapeDataString(text128);
我可以使用Uri转义对任何URL字符进行不受约束的编码,然后在目标位置对它们进行解码,但这会生成172个字符,而不是128个字符,而且我必须稍微小心(据我所知),或者由于IIS中URL长度的限制,字符串长度

我做错了什么,或者是否有其他方法可以使用RNGCrypto生成128个字符?我看到一些代码在包含a-zA-Z0-9的字符串上使用每个字节结果的62模(如下所示)

但很明显,除非字节中的数字范围限制为62的倍数,否则这将扭曲字符的分布,因此该方法似乎并不理想


感谢MH

只需生成96个随机字节。然后Base64对其进行编码以获得128个字符的字符串

byte[] linkBytes = new byte[96];
var rngCrypto = new System.Security.Cryptography.RNGCryptoServiceProvider();
rngCrypto.GetBytes(linkBytes);
var text128 = Convert.ToBase64String(linkBytes);
var text128Enc = Uri.EscapeDataString(text128);
base 64编码使用4个字节对原始数据的每3个字节进行编码。如果进行计算,(128/4)*3=96,则得到生成128个字符的base64编码字符串所需的字节数

注意
您提到需要生成128个字符的熵。我只是想指出,通常,需求是用熵的位数来表示的。如果您的意思是128个字符,那么您还必须具体说明集合中要包含哪些字符


否则,您可能需要指定需要128字节的熵(或1024位)。如果是这样的话,那么上面的示例代码就不够了,也没有办法用128个可读字符对128字节(1024位)的熵进行Base64编码。

在这种情况下,这无关紧要。只要值足够长,
Random
的熵就足够了。即使你只使用10个随机数的字符串,恶意用户猜出数字的概率也是1000000000分之一。将其更改为10个随机字母(a-z),即141167095653376中的一个。不太可能

byte[] linkBytes = new byte[96];
var rngCrypto = new System.Security.Cryptography.RNGCryptoServiceProvider();
rngCrypto.GetBytes(linkBytes);
var text128 = Convert.ToBase64String(linkBytes);
var text128Enc = Uri.EscapeDataString(text128);

只有当您直接将随机数作为加密设备中的密钥使用时,随机数的熵才是一个问题,而“重置密码”链接肯定不是。您无法将128字节的熵放入128个URL安全字符中,因为一个字节可以比URL安全字符容纳更多的值


您需要使用较少的熵来创建较短的URL,或者使用较长的URL来存储完整的128字节。

172个字符并不太长。我想试试数学,但我读到了一些提到的内容,但没有详细说明,额外的数据来自某个地方,所以我想如果我使用了可预测的字符,我会稀释随机性。看起来他们是在胡说八道,然后-我想知道额外的东西是从哪里来的,他们不是很对吗?我想要128个字符,也许我的措辞不太对。@Madhalling-那么我的回答就足够了。96字节,当基64编码时,应产生128个字符(基于每三个输入字节生成4个输出字节,1个字符表示1个输出字节的规则)。您应该运行代码并检查它。您可能还需要调查填充。当最终计数的模数为0时,.NET中的Bse64编码器可能会添加4个字符的填充,在这种情况下,您将需要使用92字节的输入。关于使这些字符更加URL友好的任何提示—正如我在下面提到的,测试表明,即使是编码/字符也会破坏路由。如果不是一回事,那就是另一回事……Base64编码的好处在于,如果您同时控制编码器和解码器,那么您可以使用任意字符集。例如,在对缓冲区进行Base64编码后,只需将
/
字符替换为尚未使用的其他字符即可。例如,和感叹号
。然后,当你收到激活链接时,在将其传递给解码器之前,只需反向操作。我可以将128个字符编码为URL安全的内容-因此,使用128个字符和我的URL前缀,如果我对128个字符进行编码,我就不太可能达到256个字符(IIRC)的URL长度限制。然而,对字符串中的/字符进行测试是不可行的,即使这些字符被编码,它们似乎仍然会破坏路由(这是一个MVC项目)。这让我回到了之前的状态,如果我有一个字符集a-zA-Z0-9,我如何使用强加密数据来选择这些字符?