我今天必须要有某种谷歌版块,因为我找不到应该是什么常见问题的答案。我在我的网站上编码我的密码重置部分,我想通过电子邮件向用户发送一个包含128个字符熵的后缀的URL,用于确认生成新密码。我环顾四周并不推荐使用随机功能,因为它不够随机,所以我正在寻找使用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的模数结果(像这样)
.....
foreach (byte b in data)
{
result.Append(chars[b%(chars.Length - 1)]);
}
.....
但显然除非字节中数字范围的限制是62的倍数,否则会使字符的分布出现偏差,因此该方法看起来并不理想。
感谢MH
答案 0 :(得分:3)
简单地生成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位)。如果是这种情况,那么上面的示例代码将是不够的,并且Base64无法编码128字节(1024位)的熵,只有128个可读字符。
答案 1 :(得分:0)
在这种情况下无所谓。只要值足够长,Random
的熵就足够了。即使您只使用10个随机数字串,这也是恶意用户可以猜出该数字的10,000,000,000的偶然数。通过将其更改为10个随机字母(a-z),在141,167,095,653,376中成为一个。事实并非如此。
当您直接将其用作加密设备中的密钥时,Random的熵只是一个问题,“重置密码”链接当然不是。
答案 2 :(得分:0)
您不能将128个字节的熵放入128个URL安全字符中,因为一个字节可以容纳比URL安全字符更多的值。
您需要为较短的网址使用较少的熵,或使用可存储完整128个字节的较长网址。