创建加密安全密码.并验证它是否有效

Create cryptographically secure passwords. And verify that it works

本文关键字:是否 有效 验证 加密 安全密码 创建      更新时间:2023-10-16

我正在开发一个也可以生成密码的软件。它基本上是这样做的:

static char AllowedChars[] = {...}
static int passwordLength = 123;
std::string password;
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<int> dist(0, sizeof(AllowedChars) - 1);
for (int i = 0; i < passwordLength; ++i) {
int index = dist(mt);
password.push_back(AllowedChars[index]);
}

我怎么知道,此算法创建了加密安全密码?

我知道random_device依赖于编译器、目标平台、它自己的版本等。我也不能依赖像std::random_device::entropy这样的方法的输出,因为它可能只是一个固定值。请参阅: http://www.pcg-random.org/posts/cpps-random_device.html

我也无法对其输出进行黑盒测试:https://security.stackexchange.com/questions/83254/how-to-check-randomness-of-random-number-generators

我如何知道使用了哪个"随机源"(即哪个RNG(?如果种子有足够的熵?(显然,这必须在编译的二进制文件上完成,因为静态源代码无法揭示这些细节。 使用此输出,我可以验证是否使用了 CSPRNG。

基于Mersenne Twister的伪随机数生成器在加密上并不安全。

MT不适合加密目的的原因是,给定一组输出,您可以开始对下一个输出进行准确的预测。

加密安全要求所有原语和底层协议在加密上合理,而不会牺牲熵或均匀性。

统一性非常重要,不仅密码是"随机的",而且是统一的。

例如,ECDHE之后的共享密钥(商定的椭圆曲线点,在散列之前(很可能是一个随机的秘密,但它肯定不是统一的!

我看到的最好的方法是从这个答案:

"DH密钥交换的结果是一个组元素,该元素在计算上与组中的随机/均匀分布元素无法区分。然而,需要注意的重要一点是,均匀分布的群元素不是(读作:必然(均匀分布的字符串(后者必须每个位等于 0,概率为 1/2,概率等于 1/2(">

因此,为了更直接地回答您的问题,如果您想构建密码生成器,我只会将CSPRNG(如/dev/(u)random或板载TRNG(的字节数组编码为十六进制,而不是构建一个特殊的密码字符串。请记住十六进制的精确格式(分隔符,大写或小写(。

如果您使用的是C,为什么不直接使用libsodium来生成随机字节,它既优雅又安全。

可能不是,因为Mersenne twister算法不安全,并且算法的状态可能会确定,尤其是在有足够的输出可用的情况下。不幸的是,passwordLength整数设置为 123 - 太高了。所以这可能会泄露信息。相反,您可以尝试直接使用std:random_device而不是mt19937。在我看来,没有特别需要特殊的库。但是,您必须确保您的std:random_device版本是安全的(作为强化 std: 库的一部分(。

使用统一范围从字母表中选择密码字符的原则(如代码所示(应被认为是正确的。要了解密码的可能强度,您可以取有效字符数量的 2 个对数,然后将其与密码中的字符数相乘。好的密码应该至少有48到64位的强度,好的密码应该在64位以上。当然,使用上述算法,无法检查您是否偶然生成了弱密码,因此您无法完全确定。不过,拥有足够大的密码应该可以解决这个问题。通常,如果您允许所有ASCII 可打印字符,则可以假设每个字符最多 6.6 位,因此 10-12 个字符应该可以正常工作。对于十六进制,您当然期望每个字符 4 位,对于基数 64,每个字符 6 位。

请注意,许多系统对密码有愚蠢的要求,这使得这个方案过于简单。系统可能需要特定数量的特殊字符或数字。密码长度的限制通常也是一个问题。


我认为使用保证使用系统RNG的随机数设备对安全性至关重要。您可能想尝试另一个执行此操作的随机数生成器,但不幸的是,在许多库中有许多编译选项,最后您必须确保自己 我想.

创建自己的uniform_random_bit_generator(替换mt19937random_device将是实现此目的的一种方法,因此您可以使用依赖于它的其他std:功能。不过,该接口仅在C++ 20 中指定,所以是的,到达那里。