mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
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:
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
202
src/ripple/basics/random.h
Normal 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
|
||||
@@ -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),
|
||||
|
||||
@@ -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
109
src/ripple/crypto/csprng.h
Normal 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
|
||||
@@ -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;
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
}
|
||||
138
src/ripple/crypto/impl/csprng.cpp
Normal file
138
src/ripple/crypto/impl/csprng.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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, ©, 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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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, ©, batch);
|
||||
expect (areBatchesEqual (batch, copy), "Should be equal");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ());
|
||||
|
||||
|
||||
@@ -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 <<
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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--)
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user