-
-
Notifications
You must be signed in to change notification settings - Fork 166
Description
The current way of generating passwords is insecure. All passwords that have been generated with QtPass in the past must be regenerated and changed.
Here is the current password generation function:
for (int i = 0; i < length; ++i) {
int index = Util::rand() % charset.length();
QChar nextChar = charset.at(index);
passwd.append(nextChar);
}The problem here is that modulo will not uniformly distribute that set. The proper way to do things is to just throw away values that are out of bounds. You could try to do the calculation correctly to uniformly stretch or compress, but it's hard to get right, so it's best to just discard numbers outside the set and try again.
Secondly, and more critically, here is the implementation of Util::rand:
...
qsrand(static_cast<uint>(QTime::currentTime().msec()));
...
int Util::rand() {
#ifdef Q_OS_WIN
quint32 ret = 0;
if (FAILED(BCryptGenRandom(NULL, (PUCHAR)&ret, sizeof(ret),
BCRYPT_USE_SYSTEM_PREFERRED_RNG)))
return qrand();
return ret % RAND_MAX;
#else
return qrand();
#endif
}Unfortunately, using a non-cryptographically secure random number generator like libc's rand() is problematic -- future outputs can be derived from knowing only a handful of past outputs -- and seeding that deterministic rng with currentTime()->msec() is even more dangerous. Not only is the current time a guessable/bruteforcable parameter, but the documentation for QTime::msec actually indicates that this is merely the "the millisecond part (0 to 999) of the time", which means there are only 1000 possibilities of generated sequences of passwords.
This is as bad as it gets, in terms of password manager password generation.
The proper fix is to use Qt 5.10's QRandomGenerator::system(). If 5.10 is not available to you, use /dev/urandom on Mac/Linux and RtlGenRandom on Windows.
The password generator inside pass(1) itself is implemented like this:
read -r -n $length pass < <(LC_ALL=C tr -dc "$characters" < /dev/urandom)- uses /dev/urandom
- discards characters that aren't part of the set