Generic PRNG framework:

* A new, unified interface for generating random numbers and
  filling buffers supporting any engine that fits the
  UniformRandomNumberGenerator concept;
* Automatically seeded replacement for rand using the fast
  xorshift+ PRNG engine;
* A CSPRNG engine that can be used with the new framework
  when needing to to generate cryptographically secure
  randomness.
* Unit test cleanups to work with new engine.
This commit is contained in:
Nik Bougalis
2016-01-09 02:27:32 -08:00
parent 1c9577a1ac
commit 40363f96a9
28 changed files with 647 additions and 334 deletions

View File

@@ -1964,6 +1964,8 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\qalloc.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\random.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\RangeSet.h">
</ClInclude>
<None Include="..\..\src\ripple\basics\README.md">
@@ -2156,6 +2158,8 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\CBigNum.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\csprng.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\ECDSA.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\ECDSACanonical.h">
@@ -2176,6 +2180,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\csprng.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\ECDSA.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -2214,18 +2222,12 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\crypto\impl\openssl.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\crypto\impl\RandomNumbers.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\RFC1751.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\crypto\KeyType.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\RandomNumbers.h">
</ClInclude>
<None Include="..\..\src\ripple\crypto\README.md">
</None>
<ClInclude Include="..\..\src\ripple\crypto\RFC1751.h">

View File

@@ -2697,6 +2697,9 @@
<ClInclude Include="..\..\src\ripple\basics\qalloc.h">
<Filter>ripple\basics</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\random.h">
<Filter>ripple\basics</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\basics\RangeSet.h">
<Filter>ripple\basics</Filter>
</ClInclude>
@@ -2871,6 +2874,9 @@
<ClInclude Include="..\..\src\ripple\crypto\CBigNum.h">
<Filter>ripple\crypto</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\csprng.h">
<Filter>ripple\crypto</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\ECDSA.h">
<Filter>ripple\crypto</Filter>
</ClInclude>
@@ -2892,6 +2898,9 @@
<ClCompile Include="..\..\src\ripple\crypto\impl\CBigNum.cpp">
<Filter>ripple\crypto\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\csprng.cpp">
<Filter>ripple\crypto\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\ECDSA.cpp">
<Filter>ripple\crypto\impl</Filter>
</ClCompile>
@@ -2925,18 +2934,12 @@
<ClInclude Include="..\..\src\ripple\crypto\impl\openssl.h">
<Filter>ripple\crypto\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\crypto\impl\RandomNumbers.cpp">
<Filter>ripple\crypto\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\RFC1751.cpp">
<Filter>ripple\crypto\impl</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\crypto\KeyType.h">
<Filter>ripple\crypto</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\RandomNumbers.h">
<Filter>ripple\crypto</Filter>
</ClInclude>
<None Include="..\..\src\ripple\crypto\README.md">
<Filter>ripple\crypto</Filter>
</None>

View File

@@ -70,7 +70,7 @@
#include <ripple/shamap/Family.h>
#include <ripple/unity/git_id.h>
#include <ripple/websocket/MakeServer.h>
#include <ripple/crypto/RandomNumbers.h>
#include <ripple/crypto/csprng.h>
#include <beast/asio/io_latency_probe.h>
#include <beast/module/core/text/LexicalCast.h>
#include <beast/module/core/thread/DeadlineTimer.h>
@@ -844,7 +844,7 @@ public:
{
if (timer == m_entropyTimer)
{
add_entropy (nullptr, 0);
crypto_prng().mix_entropy ();
return;
}

View File

@@ -29,7 +29,7 @@
#include <ripple/core/Config.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/core/TimeKeeper.h>
#include <ripple/crypto/RandomNumbers.h>
#include <ripple/crypto/csprng.h>
#include <ripple/json/to_string.h>
#include <ripple/net/RPCCall.h>
#include <ripple/resource/Fees.h>
@@ -44,7 +44,6 @@
#include <google/protobuf/stubs/common.h>
#include <boost/program_options.hpp>
#include <cstdlib>
#include <thread>
#include <utility>
#if defined(BEAST_LINUX) || defined(BEAST_MAC) || defined(BEAST_BSD)
@@ -113,7 +112,7 @@ void startServer (Application& app)
// Try to write out some entropy to use the next time we start.
auto entropy = getEntropyFile (app.config());
if (!entropy.empty ())
stir_entropy (entropy.string ());
crypto_prng().save_state(entropy.string ());
}
void printHelp (const po::options_description& desc)
@@ -189,30 +188,6 @@ int run (int argc, char** argv)
setCallingThreadName ("main");
{
// We want to seed the RNG early. We acquire a small amount of
// questionable quality entropy from the current time and our
// environment block which will get stirred into the RNG pool
// along with high-quality entropy from the system.
struct entropy_t
{
std::uint64_t timestamp;
std::size_t tid;
std::uintptr_t ptr[4];
};
auto entropy = std::make_unique<entropy_t> ();
entropy->timestamp = beast::Time::currentTimeMillis ();
entropy->tid = std::hash <std::thread::id>() (std::this_thread::get_id ());
entropy->ptr[0] = reinterpret_cast<std::uintptr_t>(entropy.get ());
entropy->ptr[1] = reinterpret_cast<std::uintptr_t>(&argc);
entropy->ptr[2] = reinterpret_cast<std::uintptr_t>(argv);
entropy->ptr[3] = reinterpret_cast<std::uintptr_t>(argv[0]);
add_entropy (entropy.get (), sizeof (entropy_t));
}
po::variables_map vm;
std::string importText;
@@ -333,10 +308,12 @@ int run (int argc, char** argv)
config->LEDGER_HISTORY = 0;
}
// Use any previously available entropy to stir the pool
auto entropy = getEntropyFile (*config);
if (!entropy.empty ())
stir_entropy (entropy.string ());
{
// Stir any previously saved entropy into the pool:
auto entropy = getEntropyFile (*config);
if (!entropy.empty ())
crypto_prng().load_state(entropy.string ());
}
if (vm.count ("start"))
config->START_UP = Config::FRESH;

View File

@@ -45,6 +45,7 @@
#include <ripple/app/tx/apply.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/random.h>
#include <ripple/basics/Time.h>
#include <ripple/protocol/digest.h>
#include <ripple/basics/StringUtilities.h>
@@ -53,7 +54,7 @@
#include <ripple/core/Config.h>
#include <ripple/core/LoadFeeTrack.h>
#include <ripple/core/TimeKeeper.h>
#include <ripple/crypto/RandomNumbers.h>
#include <ripple/crypto/csprng.h>
#include <ripple/crypto/RFC1751.h>
#include <ripple/json/to_string.h>
#include <ripple/overlay/ClusterNode.h>
@@ -70,6 +71,7 @@
#include <beast/module/core/text/LexicalCast.h>
#include <beast/module/core/thread/DeadlineTimer.h>
#include <beast/module/core/system/SystemStats.h>
#include <beast/random/rngfill.h>
#include <beast/utility/make_lock.h>
#include <boost/optional.hpp>
#include <condition_variable>
@@ -2528,7 +2530,10 @@ bool NetworkOPsImp::subServer (InfoSub::ref isrListener, Json::Value& jvResult,
jvResult[jss::stand_alone] = m_standalone;
// CHECKME: is it necessary to provide a random number here?
random_fill (uRandom.begin (), uRandom.size ());
beast::rngfill (
uRandom.begin(),
uRandom.size(),
crypto_prng());
jvResult[jss::random] = to_string (uRandom);
jvResult[jss::server_status] = strOperatingMode ();

202
src/ripple/basics/random.h Normal file
View File

@@ -0,0 +1,202 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_BASICS_RANDOM_H_INCLUDED
#define RIPPLE_BASICS_RANDOM_H_INCLUDED
#include <beast/random/xor_shift_engine.h>
#include <beast/is_call_possible.h>
#include <beast/win32_workaround.h>
#include <boost/thread/tss.hpp>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <random>
#include <limits>
#include <type_traits>
namespace ripple {
static_assert (
std::is_integral <beast::xor_shift_engine::result_type>::value &&
std::is_unsigned <beast::xor_shift_engine::result_type>::value,
"The Ripple default PRNG engine must return an unsigned integral type.");
static_assert (
std::numeric_limits<beast::xor_shift_engine::result_type>::max() >=
std::numeric_limits<std::uint64_t>::max(),
"The Ripple default PRNG engine return must be at least 64 bits wide.");
namespace detail {
// Determines if a type can be called like an Engine
template <class Engine, class Result = typename Engine::result_type>
using is_engine =
beast::is_call_possible<Engine, Result()>;
}
/** Return the default random engine.
This engine is guaranteed to be deterministic, but by
default will be randomly seeded. It is NOT cryptographically
secure and MUST NOT be used to generate randomness that
will be used for keys, secure cookies, IVs, padding, etc.
Each thread gets its own instance of the engine which
will be randomly seeded.
*/
inline
beast::xor_shift_engine&
default_prng ()
{
static
boost::thread_specific_ptr<beast::xor_shift_engine> engine;
if (!engine.get())
{
std::random_device rng;
std::uint64_t seed = rng();
for (int i = 0; i < 6; ++i)
{
if (seed == 0)
seed = rng();
seed ^= (seed << (7 - i)) * rng();
}
engine.reset (new beast::xor_shift_engine (seed));
}
return *engine;
}
/** Return a uniformly distributed random integer.
@param min The smallest value to return. If not specified
the value defaults to 0.
@param max The largest value to return. If not specified
the value defaults to the largest value that
can be represented.
The randomness is generated by the specified engine (or
the default engine if one is not specified). The result
is only cryptographicallys secure if the PRNG engine is
cryptographically secure.
@note The range is always a closed interval, so calling
rand_int(-5, 15) can return any integer in the
closed interval [-5, 15]; similarly, calling
rand_int(7) can return any integer in the closed
interval [0, 7].
*/
/** @{ */
template <class Engine, class Integral>
std::enable_if_t<
std::is_integral<Integral>::value &&
detail::is_engine<Engine>::value,
Integral>
rand_int (
Engine& engine,
Integral min,
Integral max)
{
assert (max > min);
// This should have no state and constructing it should
// be very cheap. If that turns out not to be the case
// it could be hand-optimized.
return std::uniform_int_distribution<Integral>(min, max)(engine);
}
template <class Integral>
std::enable_if_t<std::is_integral<Integral>::value, Integral>
rand_int (
Integral min,
Integral max)
{
return rand_int (default_prng(), min, max);
}
template <class Engine, class Integral>
std::enable_if_t<
std::is_integral<Integral>::value &&
detail::is_engine<Engine>::value,
Integral>
rand_int (
Engine& engine,
Integral max)
{
return rand_int (engine, Integral(0), max);
}
template <class Integral>
std::enable_if_t<std::is_integral<Integral>::value, Integral>
rand_int (Integral max)
{
return rand_int (default_prng(), max);
}
template <class Integral, class Engine>
std::enable_if_t<
std::is_integral<Integral>::value &&
detail::is_engine<Engine>::value,
Integral>
rand_int (
Engine& engine)
{
return rand_int (
engine,
std::numeric_limits<Integral>::max());
}
template <class Integral = int>
std::enable_if_t<std::is_integral<Integral>::value, Integral>
rand_int ()
{
return rand_int (
default_prng(),
std::numeric_limits<Integral>::max());
}
/** @} */
/** Return a random boolean value */
/** @{ */
template <class Engine>
inline
bool
rand_bool (Engine& engine)
{
return rand_int (engine, 1) == 1;
}
inline
bool
rand_bool ()
{
return rand_bool (default_prng());
}
/** @} */
} // ripple
#endif // RIPPLE_BASICS_RANDOM_H_INCLUDED

View File

@@ -20,7 +20,7 @@
#include <BeastConfig.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/ThreadName.h>
#include <ripple/crypto/RandomNumbers.h>
#include <ripple/basics/random.h>
#include <ripple/core/impl/SNTPClock.h>
#include <beast/asio/placeholders.h>
#include <beast/threads/Thread.h>
@@ -351,12 +351,16 @@ public:
return;
}
ip::udp::resolver::iterator sel = it;
assert (it != ip::udp::resolver::iterator());
auto sel = it;
int i = 1;
while (++it != ip::udp::resolver::iterator())
if ((rand () % ++i) == 0)
{
if (rand_int (i++) == 0)
sel = it;
}
if (sel != ip::udp::resolver::iterator ())
{
@@ -374,7 +378,7 @@ public:
query.replied = false;
query.sent = now;
random_fill (&query.nonce);
query.nonce = rand_int<std::uint32_t>();
reinterpret_cast<std::uint32_t*> (SNTPQueryData)[NTP_OFF_XMITTS_INT] = static_cast<std::uint32_t> (time (nullptr)) + NTP_UNIX_OFFSET;
reinterpret_cast<std::uint32_t*> (SNTPQueryData)[NTP_OFF_XMITTS_FRAC] = query.nonce;
socket_.async_send_to(buffer(SNTPQueryData, 48),

View File

@@ -1,67 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_CRYPTO_RANDOMNUMBERS_H_INCLUDED
#define RIPPLE_CRYPTO_RANDOMNUMBERS_H_INCLUDED
#include <string>
#include <type_traits>
namespace ripple {
/** Stir the RNG using entropy from stable storage.
@param file the file from which state is loaded and into
which it is saved.
@return true if the pool has sufficient entropy; false
otherwise.
*/
bool stir_entropy (std::string file);
/** Adds entropy to the RNG pool.
@param buffer An optional buffer that contains random data.
@param count The size of the buffer, in bytes (or 0).
This can be called multiple times to stir entropy into the pool
without any locks.
*/
void add_entropy (void* buffer = nullptr, int count = 0);
/** Generate random bytes, suitable for cryptography. */
/**@{*/
/**
@param buffer The place to store the bytes.
@param count The number of bytes to generate.
*/
void random_fill (void* buffer, int count);
/** Fills a POD object with random data */
template <class T, class = std::enable_if_t<std::is_pod<T>::value>>
void
random_fill (T* object)
{
random_fill (object, sizeof (T));
}
/**@}*/
}
#endif

109
src/ripple/crypto/csprng.h Normal file
View File

@@ -0,0 +1,109 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_CRYPTO_RANDOM_H_INCLUDED
#define RIPPLE_CRYPTO_RANDOM_H_INCLUDED
#include <mutex>
#include <string>
#include <type_traits>
namespace ripple {
/** A cryptographically secure random number engine
The engine is thread-safe (it uses a lock to serialize
access) and will, automatically, mix in some randomness
from std::random_device.
Meets the requirements of UniformRandomNumberEngine
*/
class csprng_engine
{
private:
std::mutex mutex_;
void
mix (
void* buffer,
std::size_t count,
double bitsPerByte);
public:
using result_type = std::uint64_t;
csprng_engine(csprng_engine const&) = delete;
csprng_engine& operator=(csprng_engine const&) = delete;
csprng_engine(csprng_engine&&) = delete;
csprng_engine& operator=(csprng_engine&&) = delete;
csprng_engine ();
~csprng_engine ();
/** Mix entropy into the pool */
void
mix_entropy (void* buffer = nullptr, std::size_t count = 0);
/** Load entropy from the specified file */
void
load_state (std::string const& file);
/** Save entropy to the specified file */
void
save_state (std::string const& file);
/** Generate a random integer */
result_type
operator()();
/** Fill a buffer with the requested amount of random data */
void
operator()(void *ptr, std::size_t count);
/* The smallest possible value that can be returned */
static constexpr
result_type
min()
{
return std::numeric_limits<result_type>::min();
}
/* The largest possible value that can be returned */
static constexpr
result_type
max()
{
return std::numeric_limits<result_type>::max();
}
};
/** The default cryptographically secure PRNG
Use this when you need to generate random numbers or
data that will be used for encryption or passed into
cryptographic routines.
This meets the requirements of UniformRandomNumberEngine
*/
csprng_engine& crypto_prng();
}
#endif

View File

@@ -22,7 +22,8 @@
#include <ripple/crypto/ECIES.h>
#include <ripple/crypto/impl/ec_key.h>
#include <ripple/crypto/impl/ECDSAKey.h>
#include <ripple/crypto/RandomNumbers.h>
#include <ripple/crypto/csprng.h>
#include <beast/random/rngfill.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/hmac.h>
@@ -142,7 +143,10 @@ Blob encryptECIES (uint256 const& secretKey, Blob const& publicKey, Blob const&
{
ECIES_ENC_IV_TYPE iv;
random_fill (iv.begin (), ECIES_ENC_BLK_SIZE);
beast::rngfill (
iv.begin (),
ECIES_ENC_BLK_SIZE,
crypto_prng());
ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey;

View File

@@ -1,72 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <BeastConfig.h>
#include <ripple/basics/contract.h>
#include <ripple/crypto/RandomNumbers.h>
#include <openssl/rand.h>
#include <cassert>
#include <random>
#include <stdexcept>
namespace ripple {
bool stir_entropy (std::string file)
{
// First, we attempt to stir any existing saved entropy
// into the pool: no use letting it go to waste.
RAND_load_file (file.c_str (), 1024);
// And now, we extract some entropy out, and save it for
// the future. If the quality of the entropy isn't great
// then we let the user know.
return RAND_write_file (file.c_str ()) != -1;
}
void add_entropy (void* buffer, int count)
{
assert (buffer == nullptr || count != 0);
// If we are passed data in we use it but conservatively estimate that it
// contains only around 2 bits of entropy per byte.
if (buffer != nullptr && count != 0)
RAND_add (buffer, count, count / 4.0);
// And try to add some entropy from the system
unsigned int rdbuf[32];
std::random_device rd;
for (auto& x : rdbuf)
x = rd ();
// In all our supported platforms, std::random_device is non-deterministic
// but we conservatively estimate it has around 4 bits of entropy per byte.
RAND_add (rdbuf, sizeof (rdbuf), sizeof (rdbuf) / 2.0);
}
void random_fill (void* buffer, int count)
{
assert (count > 0);
if (RAND_bytes (reinterpret_cast <unsigned char*> (buffer), count) != 1)
Throw<std::runtime_error> ("Insufficient entropy in pool.");
}
}

View File

@@ -0,0 +1,138 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <BeastConfig.h>
#include <ripple/basics/contract.h>
#include <ripple/crypto/csprng.h>
#include <openssl/rand.h>
#include <array>
#include <cassert>
#include <random>
#include <stdexcept>
namespace ripple {
void
csprng_engine::mix (
void* data, std::size_t size, double bitsPerByte)
{
assert (data != nullptr);
assert (size != 0);
assert (bitsPerByte != 0);
std::lock_guard<std::mutex> lock (mutex_);
RAND_add (data, size, (size * bitsPerByte) / 8.0);
}
csprng_engine::csprng_engine ()
{
mix_entropy ();
}
csprng_engine::~csprng_engine ()
{
RAND_cleanup ();
}
void
csprng_engine::load_state (std::string const& file)
{
if (!file.empty())
{
std::lock_guard<std::mutex> lock (mutex_);
RAND_load_file (file.c_str (), 1024);
RAND_write_file (file.c_str ());
}
}
void
csprng_engine::save_state (std::string const& file)
{
if (!file.empty())
{
std::lock_guard<std::mutex> lock (mutex_);
RAND_write_file (file.c_str ());
}
}
void
csprng_engine::mix_entropy (void* buffer, std::size_t count)
{
std::array<std::random_device::result_type, 128> entropy;
{
// On every platform we support, std::random_device
// is non-deterministic and should provide some good
// quality entropy.
std::random_device rd;
for (auto& e : entropy)
e = rd();
}
// Assume 2 bits per byte for the system entropy:
mix (
entropy.data(),
entropy.size() * sizeof(std::random_device::result_type),
2.0);
// We want to be extremely conservative about estimating
// how much entropy the buffer the user gives us contains
// and assume only 0.5 bits of entropy per byte:
if (buffer != nullptr && count != 0)
mix (buffer, count, 0.5);
}
csprng_engine::result_type
csprng_engine::operator()()
{
result_type ret;
std::lock_guard<std::mutex> lock (mutex_);
auto const result = RAND_bytes (
reinterpret_cast<unsigned char*>(&ret),
sizeof(ret));
if (result == 0)
Throw<std::runtime_error> ("Insufficient entropy");
return ret;
}
void
csprng_engine::operator()(void *ptr, std::size_t count)
{
std::lock_guard<std::mutex> lock (mutex_);
auto const result = RAND_bytes (
reinterpret_cast<unsigned char*>(ptr),
count);
if (result != 1)
Throw<std::runtime_error> ("Insufficient entropy");
}
csprng_engine& crypto_prng()
{
static csprng_engine engine;
return engine;
}
}

View File

@@ -22,6 +22,7 @@
#include <ripple/nodestore/DummyScheduler.h>
#include <ripple/nodestore/Manager.h>
#include <beast/module/core/diagnostic/UnitTestUtilities.h>
#include <algorithm>
namespace ripple {
namespace NodeStore {
@@ -31,8 +32,10 @@ namespace NodeStore {
class Backend_test : public TestBase
{
public:
void testBackend (std::string const& type, std::int64_t const seedValue,
int numObjectsToTest = 2000)
void testBackend (
std::string const& type,
std::uint64_t const seedValue,
int numObjectsToTest = 2000)
{
DummyScheduler scheduler;
@@ -43,9 +46,11 @@ public:
params.set ("type", type);
params.set ("path", path.getFullPathName ().toStdString ());
beast::xor_shift_engine rng (seedValue);
// Create a batch
Batch batch;
createPredictableBatch (batch, numObjectsToTest, seedValue);
auto batch = createPredictableBatch (
numObjectsToTest, rng());
beast::Journal j;
@@ -66,8 +71,11 @@ public:
{
// Reorder and read the copy again
std::shuffle (
batch.begin(),
batch.end(),
rng);
Batch copy;
beast::UnitTestUtilities::repeatableShuffle (batch.size (), batch, seedValue);
fetchCopyOfBatch (*backend, &copy, batch);
expect (areBatchesEqual (batch, copy), "Should be equal");
}
@@ -92,7 +100,7 @@ public:
void run ()
{
int const seedValue = 50;
std::uint64_t const seedValue = 50;
testBackend ("nudb", seedValue);

View File

@@ -21,9 +21,11 @@
#define RIPPLE_NODESTORE_BASE_H_INCLUDED
#include <ripple/nodestore/Database.h>
#include <ripple/basics/random.h>
#include <ripple/basics/StringUtilities.h>
#include <beast/unit_test/suite.h>
#include <beast/module/core/maths/Random.h>
#include <beast/random/rngfill.h>
#include <beast/random/xor_shift_engine.h>
#include <boost/algorithm/string.hpp>
#include <iomanip>
@@ -66,61 +68,47 @@ class TestBase : public beast::unit_test::suite
public:
// Tunable parameters
//
enum
{
maxPayloadBytes = 2000,
numObjectsToTest = 2000
};
// Creates predictable objects
class PredictableObjectFactory
{
public:
explicit PredictableObjectFactory (std::int64_t seedValue)
: r (seedValue)
{
}
std::shared_ptr<NodeObject> createObject ()
{
NodeObjectType type;
switch (r.nextInt (4))
{
case 0: type = hotLEDGER; break;
case 2: type = hotACCOUNT_NODE; break;
case 3: type = hotTRANSACTION_NODE; break;
default:
case 1: // was hotTRANSACTION
type = hotUNKNOWN;
break;
};
uint256 hash;
r.fillBitsRandomly (hash.begin (), hash.size ());
int const payloadBytes = 1 + r.nextInt (maxPayloadBytes);
Blob data (payloadBytes);
r.fillBitsRandomly (data.data (), payloadBytes);
return NodeObject::createObject(type, std::move(data), hash);
}
private:
beast::Random r;
};
static std::size_t const minPayloadBytes = 1;
static std::size_t const maxPayloadBytes = 2000;
static int const numObjectsToTest = 2000;
public:
// Create a predictable batch of objects
static void createPredictableBatch(Batch& batch, int numObjects,
std::int64_t seedValue) {
// Create a predictable batch of objects
static
Batch createPredictableBatch(
int numObjects, std::uint64_t seed)
{
Batch batch;
batch.reserve (numObjects);
PredictableObjectFactory factory (seedValue);
beast::xor_shift_engine rng (seed);
for (int i = 0; i < numObjects; ++i)
batch.push_back (factory.createObject ());
{
NodeObjectType type;
switch (rand_int(rng, 3))
{
case 0: type = hotLEDGER; break;
case 1: type = hotACCOUNT_NODE; break;
case 2: type = hotTRANSACTION_NODE; break;
case 3: type = hotUNKNOWN; break;
}
uint256 hash;
beast::rngfill (hash.begin(), hash.size(), rng);
Blob blob (
rand_int(rng,
minPayloadBytes, maxPayloadBytes));
beast::rngfill (blob.data(), blob.size(), rng);
batch.push_back (
NodeObject::createObject(
type, std::move(blob), hash));
}
return batch;
}
// Compare two batches for equality

View File

@@ -33,31 +33,31 @@ class NodeStoreBasic_test : public TestBase
{
public:
// Make sure predictable object generation works!
void testBatches (std::int64_t const seedValue)
void testBatches (std::uint64_t const seedValue)
{
testcase ("batch");
Batch batch1;
createPredictableBatch (batch1, numObjectsToTest, seedValue);
auto batch1 = createPredictableBatch (
numObjectsToTest, seedValue);
Batch batch2;
createPredictableBatch (batch2, numObjectsToTest, seedValue);
auto batch2 = createPredictableBatch (
numObjectsToTest, seedValue);
expect (areBatchesEqual (batch1, batch2), "Should be equal");
Batch batch3;
createPredictableBatch (batch3, numObjectsToTest, seedValue+1);
auto batch3 = createPredictableBatch (
numObjectsToTest, seedValue + 1);
expect (! areBatchesEqual (batch1, batch3), "Should not be equal");
}
// Checks encoding/decoding blobs
void testBlobs (std::int64_t const seedValue)
void testBlobs (std::uint64_t const seedValue)
{
testcase ("encoding");
Batch batch;
createPredictableBatch (batch, numObjectsToTest, seedValue);
auto batch = createPredictableBatch (
numObjectsToTest, seedValue);
EncodedBlob encoded;
for (int i = 0; i < batch.size (); ++i)
@@ -79,7 +79,7 @@ public:
void run ()
{
std::int64_t const seedValue = 50;
std::uint64_t const seedValue = 50;
testBatches (seedValue);

View File

@@ -22,6 +22,7 @@
#include <ripple/nodestore/DummyScheduler.h>
#include <ripple/nodestore/Manager.h>
#include <beast/module/core/diagnostic/UnitTestUtilities.h>
#include <algorithm>
namespace ripple {
namespace NodeStore {
@@ -40,8 +41,8 @@ public:
srcParams.set ("path", node_db.getFullPathName ().toStdString ());
// Create a batch
Batch batch;
createPredictableBatch (batch, numObjectsToTest, seedValue);
auto batch = createPredictableBatch (
numObjectsToTest, seedValue);
beast::Journal j;
@@ -102,9 +103,11 @@ public:
nodeParams.set ("type", type);
nodeParams.set ("path", node_db.getFullPathName ().toStdString ());
beast::xor_shift_engine rng (seedValue);
// Create a batch
Batch batch;
createPredictableBatch (batch, numObjectsToTest, seedValue);
auto batch = createPredictableBatch (
numObjectsToTest, rng());
beast::Journal j;
@@ -125,8 +128,11 @@ public:
{
// Reorder and read the copy again
std::shuffle (
batch.begin(),
batch.end(),
rng);
Batch copy;
beast::UnitTestUtilities::repeatableShuffle (batch.size (), batch, seedValue);
fetchCopyOfBatch (*db, &copy, batch);
expect (areBatchesEqual (batch, copy), "Should be equal");
}

View File

@@ -32,6 +32,7 @@
#include <ripple/app/misc/Validations.h>
#include <ripple/app/tx/apply.h>
#include <ripple/protocol/digest.h>
#include <ripple/basics/random.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/UptimeTimer.h>
#include <ripple/core/JobQueue.h>
@@ -546,7 +547,7 @@ PeerImp::onTimer (error_code const& ec)
{
// Make sequence unpredictable enough that a peer
// can't fake their latency
lastPingSeq_ = (rand() % 65536);
lastPingSeq_ = rand_int (65535);
lastPingTime_ = clock_type::now();
protocol::TMPing message;
@@ -2371,23 +2372,21 @@ PeerImp::getScore (bool haveItem) const
{
// Random component of score, used to break ties and avoid
// overloading the "best" peer
static const int spRandom = 10000;
static const int spRandomMax = 9999;
// Score for being very likely to have the thing we are
// look for
// Should be roughly spRandom
static const int spHaveItem = 10000;
// look for; should be roughly spRandomMax
static const int spHaveItem = 10000;
// Score reduction for each millisecond of latency
// Should be roughly spRandom divided by
// the maximum reasonable latency
static const int spLatency = 30;
// Score reduction for each millisecond of latency; should
// be roughly spRandomMax divided by the maximum reasonable
// latency
static const int spLatency = 30;
// Penalty for unknown latency
// Should be roughly spRandom
static const int spNoLatency = 8000;
// Penalty for unknown latency; should be roughly spRandomMax
static const int spNoLatency = 8000;
int score = rand() % spRandom;
int score = rand_int(spRandomMax);
if (haveItem)
score += spHaveItem;
@@ -2395,9 +2394,9 @@ PeerImp::getScore (bool haveItem) const
std::chrono::milliseconds latency;
{
std::lock_guard<std::mutex> sl (recentLock_);
latency = latency_;
}
if (latency != std::chrono::milliseconds (-1))
score -= latency.count() * spLatency;
else

View File

@@ -20,10 +20,10 @@
#ifndef RIPPLE_PEERFINDER_COUNTS_H_INCLUDED
#define RIPPLE_PEERFINDER_COUNTS_H_INCLUDED
#include <ripple/basics/random.h>
#include <ripple/peerfinder/PeerfinderManager.h>
#include <ripple/peerfinder/Slot.h>
#include <ripple/peerfinder/impl/Tuning.h>
#include <random>
namespace ripple {
namespace PeerFinder {
@@ -46,14 +46,9 @@ public:
, m_acceptCount (0)
, m_closingCount (0)
{
#if 1
std::random_device rd;
std::mt19937 gen (rd());
m_roundingThreshold =
std::generate_canonical <double, 10> (gen);
#else
m_roundingThreshold = Random::getSystemRandom().nextDouble();
#endif
std::generate_canonical <double, 10> (
default_prng());
}
//--------------------------------------------------------------------------

View File

@@ -20,11 +20,12 @@
#include <BeastConfig.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/random.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/crypto/ECDSA.h>
#include <ripple/crypto/ECIES.h>
#include <ripple/crypto/GenerateDeterministicKey.h>
#include <ripple/crypto/RandomNumbers.h>
#include <ripple/crypto/csprng.h>
#include <ripple/crypto/RFC1751.h>
#include <ripple/protocol/digest.h>
#include <ripple/protocol/JsonFields.h>
@@ -32,6 +33,7 @@
#include <ripple/protocol/Serializer.h>
#include <ripple/protocol/RipplePublicKey.h>
#include <ripple/protocol/types.h>
#include <beast/random/rngfill.h>
#include <beast/unit_test/suite.h>
#include <ed25519-donna/ed25519.h>
#include <openssl/ripemd.h>
@@ -740,7 +742,10 @@ void RippleAddress::setSeedRandom ()
// XXX Maybe we should call MakeNewKey
uint128 key;
random_fill (key.begin (), key.size ());
beast::rngfill (
key.begin(),
key.size(),
crypto_prng());
RippleAddress::setSeed (key);
}

View File

@@ -23,8 +23,9 @@
#include <ripple/protocol/impl/secp256k1.h>
#include <ripple/basics/contract.h>
#include <ripple/crypto/GenerateDeterministicKey.h>
#include <ripple/crypto/RandomNumbers.h>
#include <ripple/crypto/csprng.h>
#include <beast/crypto/secure_erase.h>
#include <beast/random/rngfill.h>
#include <ed25519-donna/ed25519.h>
#include <cstring>
@@ -150,7 +151,10 @@ Seed
randomSeed()
{
std::uint8_t buf[16];
random_fill(buf, sizeof(buf));
beast::rngfill(
buf,
sizeof(buf),
crypto_prng());
Seed seed(Slice{ buf, sizeof(buf) });
beast::secure_erase(buf, sizeof(buf));
return seed;
@@ -170,7 +174,10 @@ SecretKey
randomSecretKey()
{
std::uint8_t buf[32];
random_fill(buf, sizeof(buf));
beast::rngfill(
buf,
sizeof(buf),
crypto_prng());
SecretKey sk(Slice{ buf, sizeof(buf) });
beast::secure_erase(buf, sizeof(buf));
return sk;

View File

@@ -19,6 +19,7 @@
#include <BeastConfig.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/random.h>
#include <ripple/crypto/CBigNum.h>
#include <ripple/protocol/STAmount.h>
#include <beast/unit_test/suite.h>
@@ -407,9 +408,7 @@ public:
for (int i = 0; i < 16; ++i)
{
std::uint64_t r = rand ();
r <<= 32;
r |= rand ();
std::uint64_t r = rand_int<std::uint64_t>();
b.setuint64 (r);
if (b.getuint64 () != r)
@@ -458,7 +457,11 @@ public:
roundTest (7, 11, 44);
for (int i = 0; i <= 100000; ++i)
mulTest (rand () % 10000000, rand () % 10000000);
{
mulTest (
rand_int(10000000),
rand_int(10000000));
}
}
//--------------------------------------------------------------------------
@@ -484,12 +487,6 @@ public:
expect (bigDsmall == zero, "small/big != 0: " + bigDsmall.getText ());
#if 0
// TODO(tom): this test makes no sense - we should have no way to have
// the currency not be XRP while the account is XRP.
bigDsmall = divide (smallValue, bigNative, noCurrency(), xrpAccount ());
#endif
expect (bigDsmall == zero,
"small/bigNative != 0: " + bigDsmall.getText ());

View File

@@ -19,9 +19,9 @@
#include <BeastConfig.h>
#include <ripple/basics/chrono.h>
#include <ripple/basics/random.h>
#include <beast/unit_test/suite.h>
#include <beast/chrono/chrono_io.h>
#include <beast/module/core/maths/Random.h>
#include <boost/utility/base_from_member.hpp>
namespace ripple {
@@ -60,16 +60,15 @@ public:
void createGossip (Gossip& gossip)
{
beast::Random r;
int const v (10 + r.nextInt (10));
int const n (10 + r.nextInt (10));
int const v (10 + rand_int(9));
int const n (10 + rand_int(9));
gossip.items.reserve (n);
for (int i = 0; i < n; ++i)
{
Gossip::Item item;
item.balance = 100 + r.nextInt (500);
item.balance = 100 + rand_int(499);
item.address = beast::IP::Endpoint (
beast::IP::AddressV4 (207, 127, 82, v + i));
beast::IP::AddressV4 (192, 0, 2, v + i));
gossip.items.push_back (item);
}
}
@@ -84,7 +83,7 @@ public:
Charge const fee (dropThreshold + 1);
beast::IP::Endpoint const addr (
beast::IP::Endpoint::from_string ("207.127.82.2"));
beast::IP::Endpoint::from_string ("192.0.2.2"));
{
Consumer c (logic.newInboundEndpoint (addr));
@@ -191,7 +190,7 @@ public:
Gossip::Item item;
item.balance = 100;
item.address = beast::IP::Endpoint (
beast::IP::AddressV4 (207, 127, 82, 1));
beast::IP::AddressV4 (192, 0, 2, 1));
g.items.push_back (item);
logic.importConsumers ("g", g);
@@ -206,7 +205,7 @@ public:
TestLogic logic (j);
{
beast::IP::Endpoint address (beast::IP::Endpoint::from_string ("207.127.82.1"));
beast::IP::Endpoint address (beast::IP::Endpoint::from_string ("192.0.2.1"));
Consumer c (logic.newInboundEndpoint (address));
Charge fee (1000);
j.info <<
@@ -222,7 +221,7 @@ public:
}
{
beast::IP::Endpoint address (beast::IP::Endpoint::from_string ("207.127.82.2"));
beast::IP::Endpoint address (beast::IP::Endpoint::from_string ("192.0.2.2"));
Consumer c (logic.newInboundEndpoint (address));
Charge fee (1000);
j.info <<

View File

@@ -18,12 +18,13 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/crypto/RandomNumbers.h>
#include <ripple/crypto/csprng.h>
#include <ripple/json/json_value.h>
#include <ripple/net/RPCErr.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/JsonFields.h>
#include <ripple/basics/base_uint.h>
#include <beast/random/rngfill.h>
namespace ripple {
@@ -42,7 +43,10 @@ Json::Value doRandom (RPC::Context& context)
try
{
uint256 rand;
random_fill (rand.begin (), rand.size ());
beast::rngfill (
rand.begin(),
rand.size(),
crypto_prng());
Json::Value jvResult;
jvResult[jss::random] = to_string (rand);

View File

@@ -19,7 +19,7 @@
#include <BeastConfig.h>
#include <ripple/shamap/SHAMapNodeID.h>
#include <ripple/crypto/RandomNumbers.h>
#include <ripple/crypto/csprng.h>
#include <beast/module/core/text/LexicalCast.h>
#include <boost/format.hpp>
#include <cassert>

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/basics/random.h>
#include <ripple/shamap/SHAMap.h>
#include <ripple/nodestore/Database.h>
#include <beast/unit_test/suite.h>
@@ -162,7 +163,7 @@ SHAMap::getMissingNodes(std::vector<SHAMapNodeID>& nodeIDs, std::vector<uint256>
// (randomly selected) inner node. This increases the likelihood
// that the two threads will produce different request sets (which is
// more efficient than sending identical requests).
int firstChild = rand() % 256;
int firstChild = rand_int(255);
int currentChild = 0;
bool fullBelow = true;
@@ -212,7 +213,7 @@ SHAMap::getMissingNodes(std::vector<SHAMapNodeID>& nodeIDs, std::vector<uint256>
// Switch to processing the child node
node = static_cast<SHAMapInnerNode*>(d);
nodeID = childID;
firstChild = rand() % 256;
firstChild = rand_int(255);
currentChild = 0;
fullBelow = true;
}

View File

@@ -22,10 +22,11 @@
#include <ripple/shamap/tests/common.h>
#include <ripple/protocol/digest.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/random.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/UnorderedContainers.h>
#include <ripple/protocol/UInt160.h>
#include <beast/module/core/maths/Random.h>
#include <beast/random/xor_shift_engine.h>
#include <beast/unit_test/suite.h>
#include <functional>
#include <stdexcept>
@@ -84,17 +85,20 @@ public:
};
std::shared_ptr <Item>
make_random_item (beast::Random& r)
make_random_item (beast::xor_shift_engine& r)
{
Serializer s;
for (int d = 0; d < 3; ++d)
s.add32 (r.nextInt ());
s.add32 (ripple::rand_int<std::uint32_t>(r));
return std::make_shared <Item> (
s.getSHA512Half(), s.peekData ());
}
void
add_random_items (std::size_t n, Table& t, beast::Random& r)
add_random_items (
std::size_t n,
Table& t,
beast::xor_shift_engine& r)
{
while (n--)
{

View File

@@ -21,10 +21,10 @@
#include <ripple/shamap/SHAMap.h>
#include <ripple/shamap/SHAMapItem.h>
#include <ripple/shamap/tests/common.h>
#include <ripple/basics/random.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/protocol/UInt160.h>
#include <beast/unit_test/suite.h>
#include <openssl/rand.h> // DEPRECATED
namespace ripple {
namespace tests {
@@ -40,7 +40,8 @@ public:
{
Serializer s;
for (int d = 0; d < 3; ++d) s.add32 (rand ());
for (int d = 0; d < 3; ++d)
s.add32 (rand_int<std::uint32_t>());
return std::make_shared<SHAMapItem>(
s.getSHA512Half(), s.peekData ());
@@ -92,13 +93,7 @@ public:
void run ()
{
unsigned int seed;
// VFALCO DEPRECATED Should use C++11
RAND_pseudo_bytes (reinterpret_cast<unsigned char*> (&seed), sizeof (seed));
srand (seed);
beast::Journal const j; // debug journal
beast::Journal const j; // debug journal
TestFamily f(j);
SHAMap source (SHAMapType::FREE, f);
SHAMap destination (SHAMapType::FREE, f);
@@ -123,9 +118,9 @@ public:
destination.setSynching ();
unexpected (!source.getNodeFat (SHAMapNodeID (), nodeIDs, gotNodes,
(rand () % 2) == 0, rand () % 3),
"GetNodeFat");
unexpected (!source.getNodeFat (
SHAMapNodeID (), nodeIDs, gotNodes,
rand_bool(), rand_int(2)), "GetNodeFat");
unexpected (gotNodes.size () < 1, "NodeSize");
@@ -153,7 +148,7 @@ public:
for (nodeIDIterator = nodeIDs.begin (); nodeIDIterator != nodeIDs.end (); ++nodeIDIterator)
{
if (!source.getNodeFat (*nodeIDIterator, gotNodeIDs, gotNodes,
(rand () % 2) == 0, rand () % 3))
rand_bool(), rand_int(2)))
{
fail ("GetNodeFat");
}

View File

@@ -30,7 +30,7 @@
#include <ripple/crypto/impl/GenerateDeterministicKey.cpp>
#include <ripple/crypto/impl/KeyType.cpp>
#include <ripple/crypto/impl/openssl.cpp>
#include <ripple/crypto/impl/RandomNumbers.cpp>
#include <ripple/crypto/impl/csprng.cpp>
#include <ripple/crypto/impl/RFC1751.cpp>
#include <ripple/crypto/tests/CKey.test.cpp>