[Security] Use a CSPRNG for salts, tokens, and RNG seeding

Password salts and activation tokens were generated with the global SFMT
RNG, which was seeded from a 32-bit timestamp, making registration
salts and activation tokens predictable. The game RNG used the same
timestamp seed across restarts.

Add CryptoUtil backed by OpenSSL RAND_bytes and use it for salt/token
generation and to seed RNG_SFMT with a 64-bit CSPRNG value in both the
client and server. Link libcockatrice_utility against OpenSSL::Crypto.

Took 30 seconds

Took 25 minutes
This commit is contained in:
Lukas Brübach 2026-08-04 10:02:35 +02:00 • committed by GitHub
parent 704611fc1f
commit a01dca4f6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 101 additions and 27 deletions

View file

@ -17,6 +17,13 @@ RNG_SFMT::RNG_SFMT(QObject *parent) : RNG_Abstract(parent)
sfmt_init_gen_rand(&sfmt, QDateTime::currentDateTime().toSecsSinceEpoch());
}
RNG_SFMT::RNG_SFMT(uint64_t seed, QObject *parent) : RNG_Abstract(parent)
{
// initialize the random number generator with a 64bit seed, e.g. from a CSPRNG
uint32_t seedArray[2] = {static_cast<uint32_t>(seed), static_cast<uint32_t>(seed >> 32)};
sfmt_init_by_array(&sfmt, seedArray, 2);
}
/**
* This method is the rand() equivalent which calls the cdf with proper bounds.
*

View file

@ -37,6 +37,7 @@ private:
public:
explicit RNG_SFMT(QObject *parent = nullptr);
explicit RNG_SFMT(uint64_t seed, QObject *parent = nullptr);
unsigned int rand(int min, int max) override;
};