summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qrandom.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2017-10-23 19:39:45 -0700
committerThiago Macieira <thiago.macieira@intel.com>2017-11-11 08:11:03 +0000
commitcfad4e298f4d65fe26c3a4109d19839bdfcd30c2 (patch)
treef8fb986455c844a355e634de02e0421cbae59fc6 /src/corelib/global/qrandom.cpp
parentaf456842e13ab83cfeb44f3638b62652b201281c (diff)
QRandomGenerator: add securelySeeded(), to ensure appropriate seeding
Since we don't document how many bytes one needs (it's 2496), it's difficult for the caller to provide just enough data in the seed sequence. Moreover, since std::mt19937 doesn't make it easy to provide the ideal size either, we can't actually write code that operates optimally given a quint32 range either -- we only provide it via std::seed_seq, which is inefficient. However, we can do it internally by passing QRandomGenerator to the std::mersenne_twister_engine constructor, as it's designed to work. Change-Id: Icaa86fc7b54d4b368c0efffd14f0613c10998321 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/global/qrandom.cpp')
-rw-r--r--src/corelib/global/qrandom.cpp60
1 files changed, 51 insertions, 9 deletions
diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp
index 44b807d745..2241dc7095 100644
--- a/src/corelib/global/qrandom.cpp
+++ b/src/corelib/global/qrandom.cpp
@@ -422,6 +422,9 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
QRandomGenerator will generate the same sequence of numbers. But given
different seeds, the results should be considerably different.
+ QRandomGenerator::securelySeeded() can be used to create a QRandomGenerator
+ that is securely seeded with QRandomGenerator::system(), meaning that the
+ sequence of numbers it generates cannot be easily predicted. Additionally,
QRandomGenerator::global() returns a global instance of QRandomGenerator
that Qt will ensure to be securely seeded. This object is thread-safe, may
be shared for most uses, and is always seeded from
@@ -462,7 +465,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
itself. Due to mixing of the seed data, QRandomGenerator cannot guarantee
that distinct seeds will produce different sequences.
- QRandomGenerator::global() is always seeded from
+ QRandomGenerator::global(), like all generators created by
+ QRandomGenerator::securelySeeded(), is always seeded from
QRandomGenerator::system(), so it's not possible to make it produce
identical sequences.
@@ -576,6 +580,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
Initializes this QRandomGenerator object with the value \a seed as
the seed. Two objects constructed with the same seed value will
produce the same number sequence.
+
+ \sa securelySeeded()
*/
/*!
@@ -585,6 +591,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
Initializes this QRandomGenerator object with the values found in the
array \a seedBuffer as the seed. Two objects constructed or reseeded with
the same seed value will produce the same number sequence.
+
+ \sa securelySeeded()
*/
/*!
@@ -600,6 +608,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
std::seed_seq sseq(seedBuffer, seedBuffer + len);
QRandomGenerator generator(sseq);
\endcode
+
+ \sa securelySeeded()
*/
/*!
@@ -615,6 +625,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
std::seed_seq sseq(begin, end);
QRandomGenerator generator(sseq);
\endcode
+
+ \sa securelySeeded()
*/
/*!
@@ -624,6 +636,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
Initializes this QRandomGenerator object with the seed sequence \a
sseq as the seed. Two objects constructed or reseeded with the same seed
value will produce the same number sequence.
+
+ \sa securelySeeded()
*/
/*!
@@ -640,8 +654,8 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
For that reason, it is not adviseable to create a copy of
QRandomGenerator::global(). If one needs an exclusive deterministic
- generator, consider instead creating a new object and seeding it from
- QRandomGenerator::system().
+ generator, consider instead using securelySeeded() to obtain a new object
+ that shares no relationship with the QRandomGenerator::global().
*/
/*!
@@ -882,7 +896,7 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
QRandomGenerator will also access the operating system facilities, but they
will not generate the same sequence.
- \sa global()
+ \sa securelySeeded(), global()
*/
/*!
@@ -890,10 +904,9 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
\threadsafe
Returns a pointer to a shared QRandomGenerator that was seeded using
- QRandomGenerator::system(). This function should be used to create random data
- without the expensive creation of a securely-seeded QRandomGenerator for a
- specific use or storing the rather large QRandomGenerator object.
- large QRandomGenerator object.
+ securelySeeded(). This function should be used to create random data
+ without the expensive creation of a securely-seeded QRandomGenerator
+ for a specific use or storing the rather large QRandomGenerator object.
For example, the following creates a random RGB color:
@@ -907,10 +920,29 @@ Q_NEVER_INLINE void QRandomGenerator::SystemGenerator::generate(quint32 *begin,
Note, however, that if there are other threads accessing the global object,
those threads may obtain samples at unpredictable intervals.
- \sa system()
+ \sa securelySeeded(), system()
*/
/*!
+ \fn QRandomGenerator QRandomGenerator::securelySeeded()
+
+ Returns a new QRandomGenerator object that was securely seeded with
+ QRandomGenerator::system(). This function will obtain the ideal seed size
+ for the algorithm that QRandomGenerator uses and is therefore the
+ recommended way for creating a new QRandomGenerator object that will be
+ kept for some time.
+
+ Given the amount of data required to securely seed the deterministic
+ engine, this function is somewhat expensive and should not be used for
+ short-term uses of QRandomGenerator (using it to generate fewer than 2600
+ bytes of random data is effectively a waste of resources). If the use
+ doesn't require that much data, consider using QRandomGenerator::global()
+ and not storing a QRandomGenerator object instead.
+
+ \sa global(), system()
+ */
+
+/*!
\class QRandomGenerator64
\inmodule QtCore
\since 5.10
@@ -999,6 +1031,16 @@ QRandomGenerator64 *QRandomGenerator64::global()
return &global;
}
+QRandomGenerator64 QRandomGenerator64::securelySeeded()
+{
+ QRandomGenerator64 result(System{});
+ result.type = MersenneTwister;
+
+ // seed with the system CSPRNG
+ new (&result.storage.engine()) RandomEngine(static_cast<SystemGenerator &>(system()->storage.sys));
+ return result;
+}
+
/// \internal
inline QRandomGenerator::QRandomGenerator(System)
: type(SystemRNG)