Add sha512Half and SHA512HashHasher:

These routines replace existing code to compute SHA512-Half hashes.
The new code accumulates serialized data into a hashing context
instead of allocating a buffer, for improved performance.
This commit is contained in:
Vinnie Falco
2015-05-27 09:27:35 -07:00
parent 06823349f9
commit c25184cc88
25 changed files with 357 additions and 323 deletions

View File

@@ -20,6 +20,8 @@
#ifndef RIPPLE_PROTOCOL_HASHPREFIX_H_INCLUDED
#define RIPPLE_PROTOCOL_HASHPREFIX_H_INCLUDED
#include <beast/hash/hash_append.h>
#include <beast/utility/noexcept.h>
#include <cstdint>
namespace ripple {
@@ -97,6 +99,15 @@ public:
static HashPrefix const manifest;
};
template <class Hasher>
void
hash_append (Hasher& h, HashPrefix const& hp) noexcept
{
using beast::hash_append;
hash_append(h,
static_cast<std::uint32_t>(hp));
}
} // ripple
#endif

View File

@@ -23,6 +23,7 @@
#include <ripple/protocol/SField.h>
#include <ripple/basics/base_uint.h>
#include <ripple/basics/Buffer.h>
#include <ripple/basics/Slice.h>
#include <beast/utility/noexcept.h>
#include <cassert>
#include <cstdint>
@@ -65,6 +66,11 @@ public:
;
}
Slice slice() const noexcept
{
return Slice(mData.data(), mData.size());
}
std::size_t
size() const noexcept
{
@@ -169,21 +175,6 @@ public:
// DEPRECATED
uint256 getSHA512Half() const;
// prefix hash functions
static uint256 getPrefixHash (std::uint32_t prefix, const unsigned char* data, int len);
uint256 getPrefixHash (std::uint32_t prefix) const
{
return getPrefixHash (prefix, & (mData.front ()), mData.size ());
}
static uint256 getPrefixHash (std::uint32_t prefix, Blob const& data)
{
return getPrefixHash (prefix, & (data.front ()), data.size ());
}
static uint256 getPrefixHash (std::uint32_t prefix, std::string const& strData)
{
return getPrefixHash (prefix, reinterpret_cast<const unsigned char*> (strData.data ()), strData.size ());
}
// totality functions
Blob const& peekData () const
{
@@ -317,10 +308,17 @@ private:
std::uint8_t const* p_;
std::size_t remain_;
std::size_t used_ = 0;
public:
SerialIter (void const* data,
std::size_t size) noexcept;
SerialIter (Slice const& slice)
: SerialIter(slice.data(), slice.size())
{
}
// VFALCO TODO Remove this overload use Slice instead
explicit
SerialIter (std::string const& s) noexcept
: SerialIter(s.data(), s.size())
@@ -429,30 +427,6 @@ SerialIter::getBitString()
return u;
}
//------------------------------------------------------------------------------
uint256
getSHA512Half (void const* data, int len);
// DEPRECATED
inline
uint256
getSHA512Half (std::string const& s)
{
return getSHA512Half(s.data(), s.size());
}
// DEPRECATED
template <class T,
std::enable_if_t<std::is_integral<T>::value &&
sizeof(T) == 1>* = nullptr>
inline
uint256
getSHA512Half (std::vector<T> const& v)
{
return getSHA512Half(v.data(), v.size());
}
} // ripple
#endif

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/basics/SHA512Half.h>
#include <ripple/protocol/Indexes.h>
#include <beast/utility/static_initializer.h>
@@ -27,9 +28,7 @@ namespace ripple {
uint256
getLedgerHashIndex ()
{
Serializer s (2);
s.add16 (spaceSkipList);
return s.getSHA512Half ();
return sha512Half(std::uint16_t(spaceSkipList));
}
// Get the index of the node that holds the set of 256 ledgers that includes
@@ -38,39 +37,31 @@ getLedgerHashIndex ()
uint256
getLedgerHashIndex (std::uint32_t desiredLedgerIndex)
{
Serializer s (6);
s.add16 (spaceSkipList);
s.add32 (desiredLedgerIndex >> 16);
return s.getSHA512Half ();
return sha512Half(
std::uint16_t(spaceSkipList),
std::uint32_t(desiredLedgerIndex >> 16));
}
// get the index of the node that holds the enabled amendments
uint256
getLedgerAmendmentIndex ()
{
Serializer s (2);
s.add16 (spaceAmendment);
return s.getSHA512Half ();
return sha512Half(std::uint16_t(spaceAmendment));
}
// get the index of the node that holds the fee schedule
uint256
getLedgerFeeIndex ()
{
Serializer s (2);
s.add16 (spaceFee);
return s.getSHA512Half ();
return sha512Half(std::uint16_t(spaceFee));
}
uint256
getAccountRootIndex (Account const& account)
{
Serializer s (22);
s.add16 (spaceAccount);
s.add160 (account);
return s.getSHA512Half ();
return sha512Half(
std::uint16_t(spaceAccount),
account);
}
uint256
@@ -82,72 +73,52 @@ getAccountRootIndex (const RippleAddress & account)
uint256
getGeneratorIndex (Account const& uGeneratorID)
{
Serializer s (22);
s.add16 (spaceGenerator);
s.add160 (uGeneratorID);
return s.getSHA512Half ();
return sha512Half(
std::uint16_t(spaceGenerator),
uGeneratorID);
}
uint256
getBookBase (Book const& book)
{
Serializer s (82);
assert (isConsistent (book));
s.add16 (spaceBookDir);
s.add160 (book.in.currency);
s.add160 (book.out.currency);
s.add160 (book.in.account);
s.add160 (book.out.account);
// Return with quality 0.
return getQualityIndex (s.getSHA512Half ());
return getQualityIndex(sha512Half(
std::uint16_t(spaceBookDir),
book.in.currency,
book.out.currency,
book.in.account,
book.out.account));
}
uint256
getOfferIndex (Account const& account, std::uint32_t uSequence)
{
Serializer s (26);
s.add16 (spaceOffer);
s.add160 (account);
s.add32 (uSequence);
return s.getSHA512Half ();
return sha512Half(
std::uint16_t(spaceOffer),
account,
std::uint32_t(uSequence));
}
uint256
getOwnerDirIndex (Account const& account)
{
Serializer s (22);
s.add16 (spaceOwnerDir);
s.add160 (account);
return s.getSHA512Half ();
return sha512Half(
std::uint16_t(spaceOwnerDir),
account);
}
uint256
getDirNodeIndex (uint256 const& uDirRoot, const std::uint64_t uNodeIndex)
{
if (uNodeIndex)
{
Serializer s (42);
s.add16 (spaceDirNode);
s.add256 (uDirRoot);
s.add64 (uNodeIndex);
return s.getSHA512Half ();
}
else
{
if (uNodeIndex == 0)
return uDirRoot;
}
return sha512Half(
std::uint16_t(spaceDirNode),
uDirRoot,
std::uint64_t(uNodeIndex));
}
uint256
@@ -161,6 +132,7 @@ getQualityIndex (uint256 const& uBase, const std::uint64_t uNodeDir)
uint256 uNode (uBase);
// TODO(tom): there must be a better way.
// VFALCO [base_uint] This assumes a certain storage format
((std::uint64_t*) uNode.end ())[-1] = htobe64 (uNodeDir);
return uNode;
@@ -171,49 +143,39 @@ getQualityNext (uint256 const& uBase)
{
static beast::static_initializer<uint256> const uNext (
from_hex_text<uint256>("10000000000000000"));
return uBase + *uNext;
}
std::uint64_t
getQuality (uint256 const& uBase)
{
// VFALCO [base_uint] This assumes a certain storage format
return be64toh (((std::uint64_t*) uBase.end ())[-1]);
}
uint256
getTicketIndex (Account const& account, std::uint32_t uSequence)
{
Serializer s (26);
s.add16 (spaceTicket);
s.add160 (account);
s.add32 (uSequence);
return s.getSHA512Half ();
return sha512Half(
std::uint16_t(spaceTicket),
account,
std::uint32_t(uSequence));
}
uint256
getRippleStateIndex (Account const& a, Account const& b, Currency const& currency)
{
Serializer s (62);
s.add16 (spaceRipple);
if (a < b)
{
s.add160 (a);
s.add160 (b);
}
else
{
s.add160 (b);
s.add160 (a);
}
s.add160 (currency);
return s.getSHA512Half ();
return sha512Half(
std::uint16_t(spaceRipple),
a,
b,
currency);
return sha512Half(
std::uint16_t(spaceRipple),
b,
a,
currency);
}
uint256
@@ -225,12 +187,9 @@ getRippleStateIndex (Account const& a, Issue const& issue)
uint256
getSignerListIndex (Account const& account)
{
Serializer s (22);
s.add16 (spaceSignerList); // 2
s.add160 (account); // 20
return s.getSHA512Half ();
return sha512Half(
std::uint16_t(spaceSignerList),
account);
}
} // namespace ripple
} // ripple

View File

@@ -19,6 +19,7 @@
#include <BeastConfig.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/SHA512Half.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/crypto/ECDSA.h>
#include <ripple/crypto/ECIES.h>
@@ -63,16 +64,8 @@ bool isCanonicalEd25519Signature (std::uint8_t const* signature)
static
uint128 PassPhraseToKey (std::string const& passPhrase)
{
Serializer s;
s.addRaw (passPhrase);
// NIKB TODO this calling sequence is a bit ugly; this should be improved.
uint256 hash256 = s.getSHA512Half ();
uint128 ret (uint128::fromVoid (hash256.data()));
s.secureErase ();
return ret;
return uint128::fromVoid(sha512Half_s(
make_Slice(passPhrase)).data());
}
static
@@ -543,8 +536,9 @@ bool RippleAddress::accountPublicVerify (
&& isCanonicalEd25519Signature (signature);
}
uint256 const uHash = getSHA512Half (message);
return verifySignature (getAccountPublic(), uHash, vucSig, fullyCanonical);
return verifySignature (getAccountPublic(),
sha512Half(make_Slice(message)), vucSig,
fullyCanonical);
}
RippleAddress RippleAddress::createAccountID (Account const& account)
@@ -632,9 +626,8 @@ Blob RippleAddress::accountPrivateSign (Blob const& message) const
return signature;
}
uint256 const uHash = getSHA512Half (message);
Blob result = ECDSASign (uHash, getAccountPrivate());
Blob result = ECDSASign(
sha512Half(make_Slice(message)), getAccountPrivate());
bool const ok = !result.empty();
CondLog (!ok, lsWARNING, RippleAddress)
@@ -893,14 +886,8 @@ RippleAddress RippleAddress::createSeedGeneric (std::string const& strText)
uint256 keyFromSeed (uint128 const& seed)
{
Serializer s;
s.add128 (seed);
uint256 result = s.getSHA512Half();
s.secureErase ();
return result;
return sha512Half_s(Slice(
seed.data(), seed.size()));
}
RippleAddress getSeedFromRPC (Json::Value const& params)

View File

@@ -19,9 +19,8 @@
#include <BeastConfig.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/SHA512Half.h>
#include <ripple/protocol/Serializer.h>
#include <openssl/ripemd.h>
#include <openssl/pem.h>
namespace ripple {
@@ -298,25 +297,7 @@ Blob Serializer::getRaw (int offset, int length) const
uint256 Serializer::getSHA512Half () const
{
return ripple::getSHA512Half (mData);
}
uint256 Serializer::getPrefixHash (std::uint32_t prefix, const unsigned char* data, int len)
{
char be_prefix[4];
be_prefix[0] = static_cast<unsigned char> (prefix >> 24);
be_prefix[1] = static_cast<unsigned char> ((prefix >> 16) & 0xff);
be_prefix[2] = static_cast<unsigned char> ((prefix >> 8) & 0xff);
be_prefix[3] = static_cast<unsigned char> (prefix & 0xff);
uint256 j[2];
SHA512_CTX ctx;
SHA512_Init (&ctx);
SHA512_Update (&ctx, &be_prefix[0], 4);
SHA512_Update (&ctx, data, len);
SHA512_Final (reinterpret_cast<unsigned char*> (&j[0]), &ctx);
return j[0];
return sha512Half(make_Slice(mData));
}
int Serializer::addVL (Blob const& vector)
@@ -674,17 +655,4 @@ SerialIter::getVLBuffer()
return getRawHelper<Buffer> (getVLDataLength ());
}
//------------------------------------------------------------------------------
uint256
getSHA512Half (void const* data, int len)
{
uint256 j[2];
SHA512 (
reinterpret_cast<unsigned char const*>(
data), len, (unsigned char*) j);
return j[0];
}
} // ripple

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/basics/SHA512Half.h>
#include <ripple/basics/TestSuite.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/protocol/RipplePublicKey.h>
@@ -46,7 +47,7 @@ public:
// Check node signing.
Blob vucTextSrc = strCopy ("Hello, nurse!");
uint256 uHash = getSHA512Half (vucTextSrc);
uint256 uHash = sha512Half(make_Slice(vucTextSrc));
Blob vucTextSig;
naNodePrivate.signNodePrivate (uHash, vucTextSig);

View File

@@ -1,45 +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/protocol/Serializer.h>
#include <beast/unit_test/suite.h>
namespace ripple {
class Serializer_test : public beast::unit_test::suite
{
public:
void run ()
{
Serializer s1;
s1.add32 (3);
s1.add256 (uint256 ());
Serializer s2;
s2.add32 (0x12345600);
s2.addRaw (s1.peekData ());
expect (s1.getPrefixHash (0x12345600) == s2.getSHA512Half ());
}
};
BEAST_DEFINE_TESTSUITE(Serializer,ripple_data,ripple);
} // ripple