Skip to content

Commit

Permalink
Changed the default random_generator implementation to use
Browse files Browse the repository at this point in the history
operating-system provided entropy as it is more secure and
faster for the typical use case of generating one uuid at
a time.

This is a breaking change for anyone passing a mt19937
into one of the explicit constructors of random_generator,
which would be quite rare.

Changed the default random provider on Windows to use BCrypt
where available, falling back to Wincrypt when necessary or
when explicitly requested through a macro.

Provide a new random_generator_mt19937 type definition for
use cases where a large number of uuids need to be created
with high performance.  This is equivalent to the previous
definition of random_generator.

Provide a random generation benchmark test showing the
cutoff where the mt19937-based generator will outperform the
standard generator based on wall time.

Removed template specialization for boost::random::random_device
so that any UniformRandomNumberGenerator can be used properly
with random_generator.

Replaced the seed_rng detail implementation (which had a number
of flaws) with a replacement header-only random_provider
implementation.

Note: entropy generation errors will cause an entropy_error
to be thrown from random_generator.  The previous implementation
ignored errors and silently failed.

Added internal support for entropy generation on cloudabi
platform leveraging the new random_provider implementation.

Added internal support for Universal Windows Platform (UWP)
development leveraging the new random_provider implementation.

Added internal support for getentropy() on Linux and OpenBSD
if certain requirements are met.

This fixes #24
This closes #53
  • Loading branch information
jeking3 committed Dec 18, 2017
1 parent 1df4b88 commit a8a1ec3
Show file tree
Hide file tree
Showing 34 changed files with 1,547 additions and 472 deletions.
7 changes: 5 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Copyright 2016 Peter Dimov
# Copyright 2017 James E. King, III
# Copyright 2017 James E. King III
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)

Expand Down Expand Up @@ -96,6 +96,7 @@ jobs:
- COMMENT=valgrind
- TOOLSET=clang
- B2_VARIANT=variant=debug
- DEFINES="define=BOOST_UUID_LIMITED_BENCH"
- TESTFLAGS=testing.launcher=valgrind
addons:
apt:
Expand Down Expand Up @@ -124,6 +125,7 @@ jobs:
- B2_VARIANT=variant=debug
- TOOLSET=gcc-7
- CXXFLAGS="cxxflags=-fno-omit-frame-pointer cxxflags=-fsanitize=undefined"
- DEFINES="define=BOOST_UUID_LIMITED_BENCH"
- LINKFLAGS=linkflags=-fsanitize=undefined
addons:
apt:
Expand All @@ -135,6 +137,7 @@ jobs:
- os: linux
env:
- COMMENT=CodeCov
- DEFINES="define=BOOST_UUID_LIMITED_BENCH"
- TOOLSET=gcc-7
addons:
apt:
Expand All @@ -148,7 +151,7 @@ jobs:
- cd libs/$SELF
- ci/codecov.sh

# osx is disabled because it is very slow to start (can delay builds by 30 minutes)
# osx was disabled because it is very slow to start (can delay builds by 30 minutes)
# - os: osx
# osx_image: xcode9
# env:
Expand Down
2 changes: 1 addition & 1 deletion Jamfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Boost.Uuid Library Jamfile
#
# Copyright (c) 2017 James E. King, III
# Copyright (c) 2017 James E. King III
#
# Use, modification, and distribution are subject to the
# Boost Software License, Version 1.0. (See accompanying file
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ Branch | Travis | Appveyor | Coverity Scan | codecov.io | Documentation

### Code Example - UUID Generation

// Copyright 2017 James E. King, III
// Distributed under the Boost Software License, Version 1.0.
// Copyright 2017 James E. King III
// Distributed under the Boost Software License, Version 1.0.
// (See http://www.boost.org/LICENSE_1_0.txt)
// mkuuid.cpp example

Expand Down
45 changes: 7 additions & 38 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright 2016, 2017 Peter Dimov
# Copyright 2017 James E. King III
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)

Expand Down Expand Up @@ -27,53 +28,21 @@ environment:
B2_LINK: link=shared,static
B2_THREADING: threading=multi,single
B2_VARIANT: variant=release,debug
CXXSTD: 03,11

matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
TOOLSET: msvc-10.0
COMMENT: Visual Studio 2010
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
# TOOLSET: msvc-11.0
# COMMENT: Visual Studio 2012
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
# TOOLSET: msvc-12.0
# COMMENT: Visual Studio 2013
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
# TOOLSET: msvc-14.0
TOOLSET: msvc-10.0,msvc-11.0,msvc-12.0
COMMENT: "Visual Studio 2010/2012/2013"
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1
TOOLSET: msvc-14.0,msvc-14.1
COMMENT: "Visual Studio 2015/2017"
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
ADDPATH: C:\cygwin\bin;
TOOLSET: gcc
CXXFLAGS: cxxflags=-std=c++03
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
# ADDPATH: C:\cygwin\bin;
# TOOLSET: gcc
# CXXFLAGS: cxxflags=-std=c++11
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
# ADDPATH: C:\mingw\bin;
# TOOLSET: gcc
# CXXFLAGS: cxxflags=-std=c++03
# MAYFAIL: true
# COMMENT: serialization and mingw compatibility issues
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
# ADDPATH: C:\mingw\bin;
# TOOLSET: gcc
# CXXFLAGS: cxxflags=-std=c++11
# MAYFAIL: true
# COMMENT: serialization and mingw compatibility issues
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
ADDPATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin;
TOOLSET: gcc
CXXFLAGS: cxxflags=-std=c++03
MAYFAIL: true
COMMENT: serialization and mingw compatibility issues
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
# ADDPATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin;
# TOOLSET: gcc
# CXXFLAGS: cxxflags=-std=c++11
# MAYFAIL: true
# COMMENT: serialization and mingw compatibility issues

install:
- set SELF=uuid
Expand All @@ -93,4 +62,4 @@ build: off
test_script:
- set SELF=uuid
- PATH=%ADDPATH%%PATH%
- b2 libs/%SELF%/test toolset=%TOOLSET% %CXXFLAGS% %B2_ADDRESS_MODEL% %B2_LINK% %B2_THREADING% %B2_VARIANT% -j3
- b2 libs/%SELF%/test toolset=%TOOLSET% cxxstd=%CXXSTD% %CXXFLAGS% %B2_ADDRESS_MODEL% %B2_LINK% %B2_THREADING% %B2_VARIANT% -j3
6 changes: 3 additions & 3 deletions ci/build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#! /bin/bash
#
# Copyright 2017 James E. King, III
# Copyright 2017 James E. King III
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
Expand All @@ -14,6 +14,6 @@ if [[ -z "$CXXSTD" ]]; then
CXXSTD=03
fi

echo "$BOOST_ROOT/b2 . toolset=$TOOLSET cxxstd=$CXXSTD $CXXFLAGS $LINKFLAGS $TESTFLAGS $B2_ADDRESS_MODEL $B2_LINK $B2_THREADING $B2_VARIANT -j3 $*"
$BOOST_ROOT/b2 . toolset=$TOOLSET cxxstd=$CXXSTD $CXXFLAGS $LINKFLAGS $TESTFLAGS $B2_ADDRESS_MODEL $B2_LINK $B2_THREADING $B2_VARIANT -j3 $*
echo "$BOOST_ROOT/b2 . toolset=$TOOLSET cxxstd=$CXXSTD $CXXFLAGS $DEFINES $LINKFLAGS $TESTFLAGS $B2_ADDRESS_MODEL $B2_LINK $B2_THREADING $B2_VARIANT -j3 $*"
$BOOST_ROOT/b2 . toolset=$TOOLSET cxxstd=$CXXSTD $CXXFLAGS $DEFINES $LINKFLAGS $TESTFLAGS $B2_ADDRESS_MODEL $B2_LINK $B2_THREADING $B2_VARIANT -j3 $*

2 changes: 1 addition & 1 deletion ci/codecov.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#! /bin/bash
#
# Copyright 2017 James E. King, III
# Copyright 2017 James E. King III
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
Expand Down
2 changes: 1 addition & 1 deletion ci/coverity.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#! /bin/bash
#
# Copyright 2017 James E. King, III
# Copyright 2017 James E. King III
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
Expand Down
142 changes: 102 additions & 40 deletions doc/uuid.html
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,12 @@ <h4><a name="Synopsis_random_generator">Synopsis</a></h4>
namespace boost {
namespace uuids {

class random_generator {
public:
typedef uuid result_type;
result_type operator()();
};

template &lt;typename UniformRandomNumberGenerator&gt;
class basic_random_generator {
public:
Expand All @@ -599,34 +605,108 @@ <h4><a name="Synopsis_random_generator">Synopsis</a></h4>
explicit basic_random_generator(UniformRandomNumberGenerator&amp; gen);
explicit basic_random_generator(UniformRandomNumberGenerator* pGen);

uuid operator()();
result_type operator()();
};
typedef basic_random_generator&lt;mt19937&gt; random_generator;

typedef basic_random_generator&lt;boost::mt19937&gt; random_generator_mt19937;

}} // namespace boost::uuids
</pre>

<h4><a name="Random Generator">Random Generator</a></h4>
<p>
The <tt>boost::uuids::basic_random_generator</tt> class generates a random number
based uuid from a random number generator (one that conforms to the
<a href="http://www.boost.org/libs/random/random-concepts.html#uniform-rng">UniformRandomNumberGenerator</a>
concept).
<pre>
//default construct the random number generator and seed it
boost::uuids::basic_random_generator&lt;boost::mt19937&gt; gen;
boost::uuids::uuid u = gen();
<p>
<tt>boost::uuids::random_generator</tt> class generates uuids using
operating system provided entropy. For the majority of use cases this
should be sufficient, as this generator has very low startup overhead
when compared to a generator with seeding requirements.
</p>
<p>
<tt>boost::uuids::basic_random_generator</tt> class generates a random number
based uuid from a random number generator (one that conforms to the
<a href="http://www.boost.org/libs/random/random-concepts.html#uniform-rng">UniformRandomNumberGenerator</a>
concept). The default constructor will properly seed the random number generator
if it requires the behavior for proper operation. Additional constructors allow you
to provide your own <tt>UniformRandomNumberGenerator</tt> and you are responsible for
properly seeding it if necessary.
</p>
<p>
<tt>boost::uuids::random_generator_mt19937</tt> is a type definition for:
<tt>boost::uuids::basic_random_generator&lt;mt19937&gt;</tt> and is provided for
convenience.
</p>

<h5>Platforms</h5>
<p>
The following platforms are supported and entropy selection logic explained:
<ul>
<li>CloudABI</li>
<li>Unix
<ul>
<li>OpenBSD: <tt>use <a href="https://man.openbsd.org/arc4random.3">arc4random(3)</a></tt></li>
<li>Linux with glibc 2.25 or later: use <tt>getentropy(3)</tt></li>
<li>All other cases: use <tt>/dev/urandom</tt></li>
</ul>
</li>
<li>Windows (UWP Compatible): use BCrypt if available, otherwise use Wincrypt
</ul>
</p>

//for convenience boost::uuids::random_generator
//is equivalent to boost::uuids::basic_random_generator&lt;boost::mt19937&gt;
<h5>Preprocessor Macros</h5>
<p>
<ul>
<li>
<tt>BOOST_UUID_RANDOM_PROVIDER_FORCE_POSIX</tt>: on Unix this will force the
selection of <tt>/dev/*random</tt> over <tt>getentropy(3)</tt>.
</li>
<li>
<tt>BOOST_UUID_RANDOM_PROVIDER_FORCE_WINCRYPT</tt>: on Windows this will force the
selection of Wincrypt over BCrypt.
</li>
<li>
<tt>BOOST_UUID_RANDOM_PROVIDER_NO_LIB</tt> (or <tt>BOOST_ALL_NO_LIB</tt>): disable Windows auto linking.
</li>
</ul>
</p>

<h5>Performance</h5>
<p>
In most cases <tt>random_generator</tt> will be optimal. A benchmark can be found
in the tests (test_bench_random) that will determine the cutoff point where
<tt>random_generator_mt19937</tt> outperforms <tt>random_generator</tt> in wall time.
</p>
<p>
On Windows when using the wincrypt entropy provider, a measurable delay may occur the
first time a <tt>random_generator</tt> is constructed within a running instance. This
has been observed using <tt>test_bench_random</tt> and was so significant that the
benchmark was changed to throw out the first loop of measurements.
</p>

<h5>Exceptions</h5>
<p>
The exception <tt>boost::uuids::entropy_error</tt> is thrown if there is an error
getting entropy from the operating system.
</p>

<h5>Examples</h5>
<pre>
// Depending on the platform there may be a setup cost in
// initializing the generator so plan to reuse it if you can.
boost::uuids::random_generator gen;
boost::uuids::uuid u = gen();

//use an existing random number generator
//pass either a reference or a pointer to the random number generator
boost::mt19937 ran;
boost::uuids::basic_random_generator&lt;boost::mt19937&gt; gen(&amp;ran);
boost::uuids::uuid u = gen();
boost::uuids::uuid id = gen();
std::cout << id << std::endl;
boost::uuids::uuid id2 = gen();
std::cout << id2 << std::endl;
assert(id != id2);

// You can still use a PseudoRandomNumberGenerator to create
// UUIDs, however this is not the preferred mechanism.
boost::uuids::random_generator_mt19937 bulkgen;
for (size_t i = 0; i < 1000; ++i)
{
boost::uuids::uuid u = bulkgen();
// do something with u
boost::ignore_unused(u);
}
</pre>

<h3><a name="boost/uuid/uuid_io.hpp" href="./../../boost/uuid/uuid_io.hpp">boost/uuid/uuid_io.hpp</a></h3>
Expand Down Expand Up @@ -753,24 +833,6 @@ <h2><a name="Design notes">Design notes</a></h2>
http://www.itu.int/ITU-T/studygroups/com17/oid/X.667-E.pdf</a>, was used to design
and implement the <b>boost::uuids::uuid</b> struct.

<p>The <tt>boost::uuids::basic_random_generator</tt> class' default constructor
seeds the random number generator with a SHA-1 hash of a number of different
values including <tt>std::time(0)</tt>, <tt>std::clock()</tt>, uninitialized
data, value return from <tt>new unsigned int</tt>, etc..

<p>Using <a href="http://valgrind.org/">Valgrind</a> produces a number of false
positives with the default constructor of <tt>boost::uuids::basic_random_generator</tt>.
One solution is to suppress the errors as described in
<a href="http://valgrind.org/docs/manual/manual-core.html#manual-core.suppress">Valgrind's documentation</a>.
Another solution is to use a different constructor of <tt>boost::uuids::basic_random_generator</tt>
and explicitly pass in a random number generator.
<pre>
boost::mt19937 ran;
ran.seed(time(NULL)); // one should likely seed in a better way
boost::uuids::basic_random_generator&lt;boost::mt19937&gt; gen(&ran);
boost::uuids::uuid u = gen();
</pre>

<p>All functions are re-entrant. Classes are as thread-safe as an int. That is an
instance can not be shared between threads without proper synchronization.

Expand All @@ -779,11 +841,11 @@ <h2><a name="History and Acknowledgements">History and Acknowledgements</a></h2>
A number of people on the <a href="http://www.boost.org/">boost.org</a>
mailing list provided useful comments and greatly helped to shape the library.

<p>Revised September 26, 2017</p>
<p>Revised November 8, 2017</p>

<hr>
<p>© Copyright Andy Tompkins, 2006</p>
<p>© Copyright James E. King, III - 2017</p>
<p>© Copyright 2017 James E. King III</p>
<p> Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
www.boost.org/LICENSE_1_0.txt</a>)</p>
Expand Down
2 changes: 1 addition & 1 deletion include/boost/uuid/basic_name_generator.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Boost basic_name_generator.hpp header file -----------------------//

// Copyright 2010 Andy Tompkins.
// Copyright 2017 James E. King, III
// Copyright 2017 James E. King III

// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
Expand Down
Loading

0 comments on commit a8a1ec3

Please sign in to comment.