我正在开发一个还会生成密码的软件。它基本上是这样的:
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
之类的方法的输出,因为它may只是一个固定值。请参阅: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不能用于加密目的的原因是,由于给出了一些设定的输出,您可以在下一个输出上开始进行accurate预测。
密码安全要求所有原语和底层协议在密码上都是合理的,而不牺牲熵或均匀性。
Uniformity非常重要,不仅密码是“随机的”,而且是统一的。
例如,在ECDHE之后的共享机密(哈希之前的同意的椭圆曲线点)可能是随机机密,但肯定不是统一的!
我看过这个看跌期权的最好方法是来自this答案:
“ DH密钥交换的结果是group元素,它与随机/ group中均匀分布的元素] 计算上不可区分。但是,什么需要注意的重要一点是一个均匀分布的组元素不是(必读:不是)一个均匀分布的字符串(后者必须使每个位的概率为0等于1/2,概率为1/2等于1) “
因此,如果想构建一个密码生成器,我将直接从hex
(例如CSPRNG
或板载/dev/(u)random
)中转储TRNG
数据。
如果使用C
,为什么不只使用libsodium
到generate随机字节,它又优雅又安全。
至少std::mt19937
在C ++标准下有一个定义明确的算法:所有C ++标准库实现都必须遵循32-bit Mersenne Twister engine。如另一个答案所述,Mersenne Twister std::mt19937
在密码上不是安全的。 (实际上,C ++标准提供的所有引擎都不是加密安全的。)即使“已编译的二进制文件”将std::random_device
实现为具有完全熵及其Mersenne Twister整个状态的加密安全随机数生成器,也是如此。用该生成器(not necessarily easy和almost certainly not done in your code sample)播种。
就您问题的“验证有效”部分而言,我将从两个角度进行探讨: