mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-04 18:55:49 +00:00
Use libsecp256k1 instead of OpenSSL for key derivation:
While most of the code associated with secp256k1 operations had been migrated to libsecp256k1, the deterministic key derivation code was still using calls to OpenSSL. If merged, this commit replaces the OpenSSL-based routines with new libsecp256k1-based implementations. No functional change is expected and the change should be transparent. This commit also removes several support classes and utility functions that wrapped or adapted various OpenSSL types that are no longer needed. A tip of the hat to the original author of this truly superb library, Dr. Pieter Wuille, and to all other contributors.
This commit is contained in:
@@ -111,11 +111,8 @@ target_sources (xrpl_core PRIVATE
|
|||||||
main sources:
|
main sources:
|
||||||
subdir: crypto
|
subdir: crypto
|
||||||
#]===============================]
|
#]===============================]
|
||||||
src/ripple/crypto/impl/GenerateDeterministicKey.cpp
|
|
||||||
src/ripple/crypto/impl/RFC1751.cpp
|
src/ripple/crypto/impl/RFC1751.cpp
|
||||||
src/ripple/crypto/impl/csprng.cpp
|
src/ripple/crypto/impl/csprng.cpp
|
||||||
src/ripple/crypto/impl/ec_key.cpp
|
|
||||||
src/ripple/crypto/impl/openssl.cpp
|
|
||||||
src/ripple/crypto/impl/secure_erase.cpp)
|
src/ripple/crypto/impl/secure_erase.cpp)
|
||||||
|
|
||||||
add_library (Ripple::xrpl_core ALIAS xrpl_core)
|
add_library (Ripple::xrpl_core ALIAS xrpl_core)
|
||||||
@@ -174,16 +171,10 @@ install (
|
|||||||
DESTINATION include/ripple/basics)
|
DESTINATION include/ripple/basics)
|
||||||
install (
|
install (
|
||||||
FILES
|
FILES
|
||||||
src/ripple/crypto/GenerateDeterministicKey.h
|
|
||||||
src/ripple/crypto/RFC1751.h
|
src/ripple/crypto/RFC1751.h
|
||||||
src/ripple/crypto/csprng.h
|
src/ripple/crypto/csprng.h
|
||||||
src/ripple/crypto/secure_erase.h
|
src/ripple/crypto/secure_erase.h
|
||||||
DESTINATION include/ripple/crypto)
|
DESTINATION include/ripple/crypto)
|
||||||
install (
|
|
||||||
FILES
|
|
||||||
src/ripple/crypto/impl/ec_key.h
|
|
||||||
src/ripple/crypto/impl/openssl.h
|
|
||||||
DESTINATION include/ripple/crypto/impl)
|
|
||||||
install (
|
install (
|
||||||
FILES
|
FILES
|
||||||
src/ripple/json/JsonPropertyStream.h
|
src/ripple/json/JsonPropertyStream.h
|
||||||
@@ -770,11 +761,6 @@ target_sources (rippled PRIVATE
|
|||||||
src/test/core/SociDB_test.cpp
|
src/test/core/SociDB_test.cpp
|
||||||
src/test/core/Stoppable_test.cpp
|
src/test/core/Stoppable_test.cpp
|
||||||
src/test/core/Workers_test.cpp
|
src/test/core/Workers_test.cpp
|
||||||
#[===============================[
|
|
||||||
test sources:
|
|
||||||
subdir: crypto
|
|
||||||
#]===============================]
|
|
||||||
src/test/crypto/Openssl_test.cpp
|
|
||||||
#[===============================[
|
#[===============================[
|
||||||
test sources:
|
test sources:
|
||||||
subdir: csf
|
subdir: csf
|
||||||
|
|||||||
@@ -34,9 +34,6 @@ Loop: ripple.basics ripple.rpc
|
|||||||
Loop: ripple.core ripple.net
|
Loop: ripple.core ripple.net
|
||||||
ripple.net > ripple.core
|
ripple.net > ripple.core
|
||||||
|
|
||||||
Loop: ripple.crypto ripple.protocol
|
|
||||||
ripple.protocol > ripple.crypto
|
|
||||||
|
|
||||||
Loop: ripple.net ripple.rpc
|
Loop: ripple.net ripple.rpc
|
||||||
ripple.rpc > ripple.net
|
ripple.rpc > ripple.net
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ ripple.peerfinder > ripple.beast
|
|||||||
ripple.peerfinder > ripple.core
|
ripple.peerfinder > ripple.core
|
||||||
ripple.peerfinder > ripple.protocol
|
ripple.peerfinder > ripple.protocol
|
||||||
ripple.protocol > ripple.beast
|
ripple.protocol > ripple.beast
|
||||||
|
ripple.protocol > ripple.crypto
|
||||||
ripple.protocol > ripple.json
|
ripple.protocol > ripple.json
|
||||||
ripple.resource > ripple.basics
|
ripple.resource > ripple.basics
|
||||||
ripple.resource > ripple.beast
|
ripple.resource > ripple.beast
|
||||||
@@ -117,8 +118,6 @@ test.core > ripple.server
|
|||||||
test.core > test.jtx
|
test.core > test.jtx
|
||||||
test.core > test.toplevel
|
test.core > test.toplevel
|
||||||
test.core > test.unit_test
|
test.core > test.unit_test
|
||||||
test.crypto > ripple.beast
|
|
||||||
test.crypto > ripple.crypto
|
|
||||||
test.csf > ripple.basics
|
test.csf > ripple.basics
|
||||||
test.csf > ripple.beast
|
test.csf > ripple.beast
|
||||||
test.csf > ripple.consensus
|
test.csf > ripple.consensus
|
||||||
|
|||||||
@@ -1,47 +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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
||||||
// Copyright (c) 2011 The Bitcoin developers
|
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|
||||||
|
|
||||||
#ifndef RIPPLE_CRYPTO_GENERATEDETERMINISTICKEY_H_INCLUDED
|
|
||||||
#define RIPPLE_CRYPTO_GENERATEDETERMINISTICKEY_H_INCLUDED
|
|
||||||
|
|
||||||
#include <ripple/basics/Blob.h>
|
|
||||||
#include <ripple/basics/base_uint.h>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
|
|
||||||
Blob
|
|
||||||
generateRootDeterministicPublicKey(uint128 const& seed);
|
|
||||||
|
|
||||||
uint256
|
|
||||||
generateRootDeterministicPrivateKey(uint128 const& seed);
|
|
||||||
|
|
||||||
Blob
|
|
||||||
generatePublicDeterministicKey(Blob const& generator, int n);
|
|
||||||
|
|
||||||
uint256
|
|
||||||
generatePrivateDeterministicKey(Blob const& family, uint128 const& seed, int n);
|
|
||||||
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,217 +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 <ripple/basics/contract.h>
|
|
||||||
#include <ripple/crypto/GenerateDeterministicKey.h>
|
|
||||||
#include <ripple/crypto/impl/ec_key.h>
|
|
||||||
#include <ripple/crypto/impl/openssl.h>
|
|
||||||
#include <ripple/crypto/secure_erase.h>
|
|
||||||
#include <ripple/protocol/digest.h>
|
|
||||||
#include <array>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
|
|
||||||
namespace openssl {
|
|
||||||
|
|
||||||
struct secp256k1_data
|
|
||||||
{
|
|
||||||
EC_GROUP const* group;
|
|
||||||
bignum order;
|
|
||||||
|
|
||||||
secp256k1_data()
|
|
||||||
{
|
|
||||||
group = EC_GROUP_new_by_curve_name(NID_secp256k1);
|
|
||||||
|
|
||||||
if (!group)
|
|
||||||
LogicError(
|
|
||||||
"The OpenSSL library on this system lacks elliptic curve "
|
|
||||||
"support.");
|
|
||||||
|
|
||||||
bn_ctx ctx;
|
|
||||||
order = get_order(group, ctx);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static secp256k1_data const&
|
|
||||||
secp256k1curve()
|
|
||||||
{
|
|
||||||
static secp256k1_data const curve{};
|
|
||||||
return curve;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace openssl
|
|
||||||
|
|
||||||
using namespace openssl;
|
|
||||||
|
|
||||||
static Blob
|
|
||||||
serialize_ec_point(ec_point const& point)
|
|
||||||
{
|
|
||||||
Blob result(33);
|
|
||||||
|
|
||||||
serialize_ec_point(point, &result[0]);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class FwdIt>
|
|
||||||
void
|
|
||||||
copy_uint32(FwdIt out, std::uint32_t v)
|
|
||||||
{
|
|
||||||
*out++ = v >> 24;
|
|
||||||
*out++ = (v >> 16) & 0xff;
|
|
||||||
*out++ = (v >> 8) & 0xff;
|
|
||||||
*out = v & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Functions to add support for deterministic EC keys
|
|
||||||
|
|
||||||
// --> seed
|
|
||||||
// <-- private root generator + public root generator
|
|
||||||
static bignum
|
|
||||||
generateRootDeterministicKey(uint128 const& seed)
|
|
||||||
{
|
|
||||||
// find non-zero private key less than the curve's order
|
|
||||||
bignum privKey;
|
|
||||||
std::uint32_t seq = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// buf: 0 seed 16 seq 20
|
|
||||||
// |<--------------------------------->|<------>|
|
|
||||||
std::array<std::uint8_t, 20> buf;
|
|
||||||
std::copy(seed.begin(), seed.end(), buf.begin());
|
|
||||||
copy_uint32(buf.begin() + 16, seq++);
|
|
||||||
auto root = sha512Half(buf);
|
|
||||||
secure_erase(buf.data(), buf.size());
|
|
||||||
privKey.assign(root.data(), root.size());
|
|
||||||
secure_erase(root.data(), root.size());
|
|
||||||
} while (privKey.is_zero() || privKey >= secp256k1curve().order);
|
|
||||||
secure_erase(&seq, sizeof(seq));
|
|
||||||
return privKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --> seed
|
|
||||||
// <-- private root generator + public root generator
|
|
||||||
Blob
|
|
||||||
generateRootDeterministicPublicKey(uint128 const& seed)
|
|
||||||
{
|
|
||||||
bn_ctx ctx;
|
|
||||||
|
|
||||||
bignum privKey = generateRootDeterministicKey(seed);
|
|
||||||
|
|
||||||
// compute the corresponding public key point
|
|
||||||
ec_point pubKey = multiply(secp256k1curve().group, privKey, ctx);
|
|
||||||
|
|
||||||
privKey.clear(); // security erase
|
|
||||||
|
|
||||||
return serialize_ec_point(pubKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint256
|
|
||||||
generateRootDeterministicPrivateKey(uint128 const& seed)
|
|
||||||
{
|
|
||||||
bignum key = generateRootDeterministicKey(seed);
|
|
||||||
|
|
||||||
return uint256_from_bignum_clear(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Take ripple address.
|
|
||||||
// --> root public generator (consumes)
|
|
||||||
// <-- root public generator in EC format
|
|
||||||
static ec_point
|
|
||||||
generateRootPubKey(bignum&& pubGenerator)
|
|
||||||
{
|
|
||||||
ec_point pubPoint = bn2point(secp256k1curve().group, pubGenerator.get());
|
|
||||||
|
|
||||||
return pubPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --> public generator
|
|
||||||
static bignum
|
|
||||||
makeHash(Blob const& pubGen, int seq, bignum const& order)
|
|
||||||
{
|
|
||||||
int subSeq = 0;
|
|
||||||
|
|
||||||
bignum result;
|
|
||||||
|
|
||||||
assert(pubGen.size() == 33);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// buf: 0 pubGen 33 seq 37 subSeq 41
|
|
||||||
// |<--------------------------->|<------>|<-------->|
|
|
||||||
std::array<std::uint8_t, 41> buf;
|
|
||||||
std::copy(pubGen.begin(), pubGen.end(), buf.begin());
|
|
||||||
copy_uint32(buf.begin() + 33, seq);
|
|
||||||
copy_uint32(buf.begin() + 37, subSeq++);
|
|
||||||
auto root = sha512Half_s(buf);
|
|
||||||
secure_erase(buf.data(), buf.size());
|
|
||||||
result.assign(root.data(), root.size());
|
|
||||||
secure_erase(root.data(), root.size());
|
|
||||||
} while (result.is_zero() || result >= order);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --> public generator
|
|
||||||
Blob
|
|
||||||
generatePublicDeterministicKey(Blob const& pubGen, int seq)
|
|
||||||
{
|
|
||||||
// publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
|
|
||||||
ec_point rootPubKey = generateRootPubKey(bignum(pubGen));
|
|
||||||
|
|
||||||
bn_ctx ctx;
|
|
||||||
|
|
||||||
// Calculate the private additional key.
|
|
||||||
bignum hash = makeHash(pubGen, seq, secp256k1curve().order);
|
|
||||||
|
|
||||||
// Calculate the corresponding public key.
|
|
||||||
ec_point newPoint = multiply(secp256k1curve().group, hash, ctx);
|
|
||||||
|
|
||||||
// Add the master public key and set.
|
|
||||||
add_to(secp256k1curve().group, rootPubKey, newPoint, ctx);
|
|
||||||
|
|
||||||
return serialize_ec_point(newPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --> root private key
|
|
||||||
uint256
|
|
||||||
generatePrivateDeterministicKey(
|
|
||||||
Blob const& pubGen,
|
|
||||||
uint128 const& seed,
|
|
||||||
int seq)
|
|
||||||
{
|
|
||||||
// privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
|
|
||||||
bignum rootPrivKey = generateRootDeterministicKey(seed);
|
|
||||||
|
|
||||||
bn_ctx ctx;
|
|
||||||
|
|
||||||
// calculate the private additional key
|
|
||||||
bignum privKey = makeHash(pubGen, seq, secp256k1curve().order);
|
|
||||||
|
|
||||||
// calculate the final private key
|
|
||||||
add_to(rootPrivKey, privKey, secp256k1curve().order, ctx);
|
|
||||||
|
|
||||||
rootPrivKey.clear(); // security erase
|
|
||||||
|
|
||||||
return uint256_from_bignum_clear(privKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ripple
|
|
||||||
@@ -1,65 +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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
||||||
// Copyright (c) 2011 The Bitcoin developers
|
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|
||||||
|
|
||||||
#include <ripple/basics/contract.h>
|
|
||||||
#include <ripple/crypto/impl/ec_key.h>
|
|
||||||
#include <openssl/ec.h>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
namespace openssl {
|
|
||||||
|
|
||||||
static inline EC_KEY*
|
|
||||||
get_EC_KEY(const ec_key& that)
|
|
||||||
{
|
|
||||||
return (EC_KEY*)that.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
ec_key::ec_key(const ec_key& that)
|
|
||||||
{
|
|
||||||
if (that.ptr == nullptr)
|
|
||||||
{
|
|
||||||
ptr = nullptr;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = (pointer_t)EC_KEY_dup(get_EC_KEY(that));
|
|
||||||
|
|
||||||
if (ptr == nullptr)
|
|
||||||
Throw<std::runtime_error>("ec_key::ec_key() : EC_KEY_dup failed");
|
|
||||||
|
|
||||||
EC_KEY_set_conv_form(get_EC_KEY(*this), POINT_CONVERSION_COMPRESSED);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ec_key::destroy()
|
|
||||||
{
|
|
||||||
if (ptr != nullptr)
|
|
||||||
{
|
|
||||||
EC_KEY_free(get_EC_KEY(*this));
|
|
||||||
ptr = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace openssl
|
|
||||||
} // namespace ripple
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
Copyright (c) 2014 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_EC_KEY_H_INCLUDED
|
|
||||||
#define RIPPLE_CRYPTO_EC_KEY_H_INCLUDED
|
|
||||||
|
|
||||||
#include <ripple/basics/base_uint.h>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
namespace openssl {
|
|
||||||
|
|
||||||
class ec_key
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using pointer_t = struct opaque_EC_KEY*;
|
|
||||||
|
|
||||||
ec_key() : ptr(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ec_key(pointer_t raw) : ptr(raw)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~ec_key()
|
|
||||||
{
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
valid() const
|
|
||||||
{
|
|
||||||
return ptr != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
pointer_t
|
|
||||||
get() const
|
|
||||||
{
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ec_key(const ec_key&);
|
|
||||||
|
|
||||||
pointer_t
|
|
||||||
release()
|
|
||||||
{
|
|
||||||
pointer_t released = ptr;
|
|
||||||
|
|
||||||
ptr = nullptr;
|
|
||||||
|
|
||||||
return released;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
pointer_t ptr;
|
|
||||||
|
|
||||||
void
|
|
||||||
destroy();
|
|
||||||
|
|
||||||
ec_key&
|
|
||||||
operator=(const ec_key&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace openssl
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
Copyright (c) 2014 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 <ripple/basics/contract.h>
|
|
||||||
#include <ripple/crypto/impl/openssl.h>
|
|
||||||
#include <openssl/hmac.h>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
namespace openssl {
|
|
||||||
|
|
||||||
bignum::bignum()
|
|
||||||
{
|
|
||||||
ptr = BN_new();
|
|
||||||
if (ptr == nullptr)
|
|
||||||
Throw<std::runtime_error>("BN_new() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
bignum::assign(uint8_t const* data, size_t size)
|
|
||||||
{
|
|
||||||
// This reuses and assigns ptr
|
|
||||||
BIGNUM* bn = BN_bin2bn(data, size, ptr);
|
|
||||||
if (bn == nullptr)
|
|
||||||
Throw<std::runtime_error>("BN_bin2bn() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
bignum::assign_new(uint8_t const* data, size_t size)
|
|
||||||
{
|
|
||||||
// ptr must not be allocated
|
|
||||||
|
|
||||||
ptr = BN_bin2bn(data, size, nullptr);
|
|
||||||
if (ptr == nullptr)
|
|
||||||
Throw<std::runtime_error>("BN_bin2bn() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
bn_ctx::bn_ctx()
|
|
||||||
{
|
|
||||||
ptr = BN_CTX_new();
|
|
||||||
if (ptr == nullptr)
|
|
||||||
Throw<std::runtime_error>("BN_CTX_new() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
bignum
|
|
||||||
get_order(EC_GROUP const* group, bn_ctx& ctx)
|
|
||||||
{
|
|
||||||
bignum result;
|
|
||||||
if (!EC_GROUP_get_order(group, result.get(), ctx.get()))
|
|
||||||
Throw<std::runtime_error>("EC_GROUP_get_order() failed");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ec_point::ec_point(EC_GROUP const* group)
|
|
||||||
{
|
|
||||||
ptr = EC_POINT_new(group);
|
|
||||||
if (ptr == nullptr)
|
|
||||||
Throw<std::runtime_error>("EC_POINT_new() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
add_to(EC_GROUP const* group, ec_point const& a, ec_point& b, bn_ctx& ctx)
|
|
||||||
{
|
|
||||||
if (!EC_POINT_add(group, b.get(), a.get(), b.get(), ctx.get()))
|
|
||||||
Throw<std::runtime_error>("EC_POINT_add() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
ec_point
|
|
||||||
multiply(EC_GROUP const* group, bignum const& n, bn_ctx& ctx)
|
|
||||||
{
|
|
||||||
ec_point result(group);
|
|
||||||
if (!EC_POINT_mul(
|
|
||||||
group, result.get(), n.get(), nullptr, nullptr, ctx.get()))
|
|
||||||
Throw<std::runtime_error>("EC_POINT_mul() failed");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ec_point
|
|
||||||
bn2point(EC_GROUP const* group, BIGNUM const* number)
|
|
||||||
{
|
|
||||||
EC_POINT* result = EC_POINT_bn2point(group, number, nullptr, nullptr);
|
|
||||||
if (result == nullptr)
|
|
||||||
Throw<std::runtime_error>("EC_POINT_bn2point() failed");
|
|
||||||
|
|
||||||
return ec_point::acquire(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ec_key
|
|
||||||
ec_key_new_secp256k1_compressed()
|
|
||||||
{
|
|
||||||
EC_KEY* key = EC_KEY_new_by_curve_name(NID_secp256k1);
|
|
||||||
|
|
||||||
if (key == nullptr)
|
|
||||||
Throw<std::runtime_error>("EC_KEY_new_by_curve_name() failed");
|
|
||||||
|
|
||||||
EC_KEY_set_conv_form(key, POINT_CONVERSION_COMPRESSED);
|
|
||||||
|
|
||||||
return ec_key((ec_key::pointer_t)key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
serialize_ec_point(ec_point const& point, std::uint8_t* ptr)
|
|
||||||
{
|
|
||||||
ec_key key = ec_key_new_secp256k1_compressed();
|
|
||||||
if (EC_KEY_set_public_key((EC_KEY*)key.get(), point.get()) <= 0)
|
|
||||||
Throw<std::runtime_error>("EC_KEY_set_public_key() failed");
|
|
||||||
|
|
||||||
int const size = i2o_ECPublicKey((EC_KEY*)key.get(), &ptr);
|
|
||||||
|
|
||||||
assert(size <= 33);
|
|
||||||
(void)size;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace openssl
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
FILE _iob[] = {*stdin, *stdout, *stderr};
|
|
||||||
extern "C" FILE* __cdecl __iob_func(void)
|
|
||||||
{
|
|
||||||
return _iob;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,236 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
Copyright (c) 2014 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_OPENSSL_H
|
|
||||||
#define RIPPLE_OPENSSL_H
|
|
||||||
|
|
||||||
#include <ripple/basics/base_uint.h>
|
|
||||||
#include <ripple/crypto/impl/ec_key.h>
|
|
||||||
#include <openssl/bn.h>
|
|
||||||
#include <openssl/ec.h>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
namespace openssl {
|
|
||||||
|
|
||||||
class bignum
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
BIGNUM* ptr;
|
|
||||||
|
|
||||||
// non-copyable
|
|
||||||
bignum(bignum const&) = delete;
|
|
||||||
bignum&
|
|
||||||
operator=(bignum const&) = delete;
|
|
||||||
|
|
||||||
void
|
|
||||||
assign_new(uint8_t const* data, size_t size);
|
|
||||||
|
|
||||||
public:
|
|
||||||
bignum();
|
|
||||||
|
|
||||||
~bignum()
|
|
||||||
{
|
|
||||||
if (ptr != nullptr)
|
|
||||||
{
|
|
||||||
BN_free(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bignum(uint8_t const* data, size_t size)
|
|
||||||
{
|
|
||||||
assign_new(data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
explicit bignum(T const& thing)
|
|
||||||
{
|
|
||||||
assign_new(thing.data(), thing.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
bignum(bignum&& that) noexcept : ptr(that.ptr)
|
|
||||||
{
|
|
||||||
that.ptr = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bignum&
|
|
||||||
operator=(bignum&& that) noexcept
|
|
||||||
{
|
|
||||||
using std::swap;
|
|
||||||
|
|
||||||
swap(ptr, that.ptr);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
BIGNUM*
|
|
||||||
get()
|
|
||||||
{
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
BIGNUM const*
|
|
||||||
get() const
|
|
||||||
{
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
is_zero() const
|
|
||||||
{
|
|
||||||
return BN_is_zero(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
clear()
|
|
||||||
{
|
|
||||||
BN_clear(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
assign(uint8_t const* data, size_t size);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
operator<(bignum const& a, bignum const& b)
|
|
||||||
{
|
|
||||||
return BN_cmp(a.get(), b.get()) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
operator>=(bignum const& a, bignum const& b)
|
|
||||||
{
|
|
||||||
return !(a < b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint256
|
|
||||||
uint256_from_bignum_clear(bignum& number)
|
|
||||||
{
|
|
||||||
uint256 result;
|
|
||||||
result.zero();
|
|
||||||
|
|
||||||
BN_bn2bin(number.get(), result.end() - BN_num_bytes(number.get()));
|
|
||||||
|
|
||||||
number.clear();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
class bn_ctx
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
BN_CTX* ptr;
|
|
||||||
|
|
||||||
// non-copyable
|
|
||||||
bn_ctx(bn_ctx const&);
|
|
||||||
bn_ctx&
|
|
||||||
operator=(bn_ctx const&);
|
|
||||||
|
|
||||||
public:
|
|
||||||
bn_ctx();
|
|
||||||
|
|
||||||
~bn_ctx()
|
|
||||||
{
|
|
||||||
BN_CTX_free(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
BN_CTX*
|
|
||||||
get()
|
|
||||||
{
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
BN_CTX const*
|
|
||||||
get() const
|
|
||||||
{
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bignum
|
|
||||||
get_order(EC_GROUP const* group, bn_ctx& ctx);
|
|
||||||
|
|
||||||
inline void
|
|
||||||
add_to(bignum const& a, bignum& b, bignum const& modulus, bn_ctx& ctx)
|
|
||||||
{
|
|
||||||
BN_mod_add(b.get(), a.get(), b.get(), modulus.get(), ctx.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
class ec_point
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using pointer_t = EC_POINT*;
|
|
||||||
|
|
||||||
private:
|
|
||||||
pointer_t ptr;
|
|
||||||
|
|
||||||
ec_point(pointer_t raw) : ptr(raw)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
static ec_point
|
|
||||||
acquire(pointer_t raw)
|
|
||||||
{
|
|
||||||
return ec_point(raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
ec_point(EC_GROUP const* group);
|
|
||||||
|
|
||||||
~ec_point()
|
|
||||||
{
|
|
||||||
EC_POINT_free(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
ec_point(ec_point const&) = delete;
|
|
||||||
ec_point&
|
|
||||||
operator=(ec_point const&) = delete;
|
|
||||||
|
|
||||||
ec_point(ec_point&& that) noexcept
|
|
||||||
{
|
|
||||||
ptr = that.ptr;
|
|
||||||
that.ptr = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
EC_POINT*
|
|
||||||
get()
|
|
||||||
{
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
EC_POINT const*
|
|
||||||
get() const
|
|
||||||
{
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
add_to(EC_GROUP const* group, ec_point const& a, ec_point& b, bn_ctx& ctx);
|
|
||||||
|
|
||||||
ec_point
|
|
||||||
multiply(EC_GROUP const* group, bignum const& n, bn_ctx& ctx);
|
|
||||||
|
|
||||||
ec_point
|
|
||||||
bn2point(EC_GROUP const* group, BIGNUM const* number);
|
|
||||||
|
|
||||||
// output buffer must hold 33 bytes
|
|
||||||
void
|
|
||||||
serialize_ec_point(ec_point const& point, std::uint8_t* ptr);
|
|
||||||
|
|
||||||
} // namespace openssl
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -20,7 +20,6 @@
|
|||||||
#include <ripple/basics/contract.h>
|
#include <ripple/basics/contract.h>
|
||||||
#include <ripple/basics/strHex.h>
|
#include <ripple/basics/strHex.h>
|
||||||
#include <ripple/beast/utility/rngfill.h>
|
#include <ripple/beast/utility/rngfill.h>
|
||||||
#include <ripple/crypto/GenerateDeterministicKey.h>
|
|
||||||
#include <ripple/crypto/csprng.h>
|
#include <ripple/crypto/csprng.h>
|
||||||
#include <ripple/crypto/secure_erase.h>
|
#include <ripple/crypto/secure_erase.h>
|
||||||
#include <ripple/protocol/SecretKey.h>
|
#include <ripple/protocol/SecretKey.h>
|
||||||
@@ -54,45 +53,160 @@ SecretKey::to_string() const
|
|||||||
return strHex(*this);
|
return strHex(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
void
|
||||||
|
copy_uint32(std::uint8_t* out, std::uint32_t v)
|
||||||
|
{
|
||||||
|
*out++ = v >> 24;
|
||||||
|
*out++ = (v >> 16) & 0xff;
|
||||||
|
*out++ = (v >> 8) & 0xff;
|
||||||
|
*out = v & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256
|
||||||
|
deriveDeterministicRootKey(Seed const& seed)
|
||||||
|
{
|
||||||
|
// We fill this buffer with the seed and append a 32-bit "counter"
|
||||||
|
// that counts how many attempts we've had to make to generate a
|
||||||
|
// non-zero key that's less than the curve's order:
|
||||||
|
//
|
||||||
|
// 1 2
|
||||||
|
// 0 6 0
|
||||||
|
// buf |----------------|----|
|
||||||
|
// | seed | seq|
|
||||||
|
|
||||||
|
std::array<std::uint8_t, 20> buf;
|
||||||
|
std::copy(seed.begin(), seed.end(), buf.begin());
|
||||||
|
|
||||||
|
// The odds that this loop executes more than once are neglible
|
||||||
|
// but *just* in case someone managed to generate a key that required
|
||||||
|
// more iterations loop a few times.
|
||||||
|
for (std::uint32_t seq = 0; seq != 128; ++seq)
|
||||||
|
{
|
||||||
|
copy_uint32(buf.data() + 16, seq);
|
||||||
|
|
||||||
|
auto const ret = sha512Half(buf);
|
||||||
|
|
||||||
|
if (secp256k1_ec_seckey_verify(secp256k1Context(), ret.data()) == 1)
|
||||||
|
{
|
||||||
|
secure_erase(buf.data(), buf.size());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Throw<std::runtime_error>("Unable to derive generator from seed");
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Produces a sequence of secp256k1 key pairs. */
|
/** Produces a sequence of secp256k1 key pairs.
|
||||||
|
|
||||||
|
The reference implementation of the XRP Ledger uses a custom derivation
|
||||||
|
algorithm which enables the derivation of an entire family of secp256k1
|
||||||
|
keypairs from a single 128-bit seed. The algorithm predates widely-used
|
||||||
|
standards like BIP-32 and BIP-44.
|
||||||
|
|
||||||
|
Important note to implementers:
|
||||||
|
|
||||||
|
Using this algorithm is not required: all valid secp256k1 keypairs will
|
||||||
|
work correctly. Third party implementations can use whatever mechanisms
|
||||||
|
they prefer. However, implementers of wallets or other tools that allow
|
||||||
|
users to use existing accounts should consider at least supporting this
|
||||||
|
derivation technique to make it easier for users to 'import' accounts.
|
||||||
|
|
||||||
|
For more details, please check out:
|
||||||
|
https://xrpl.org/cryptographic-keys.html#secp256k1-key-derivation
|
||||||
|
*/
|
||||||
class Generator
|
class Generator
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Blob gen_; // VFALCO compile time size?
|
uint256 root_;
|
||||||
|
std::array<std::uint8_t, 33> generator_;
|
||||||
|
|
||||||
|
uint256
|
||||||
|
calculateTweak(std::uint32_t seq) const
|
||||||
|
{
|
||||||
|
// We fill the buffer with the generator, the provided sequence
|
||||||
|
// and a 32-bit counter tracking the number of attempts we have
|
||||||
|
// already made looking for a non-zero key that's less than the
|
||||||
|
// curve's order:
|
||||||
|
// 3 3 4
|
||||||
|
// 0 pubGen 3 7 1
|
||||||
|
// buf |---------------------------------|----|----|
|
||||||
|
// | generator | seq| cnt|
|
||||||
|
|
||||||
|
std::array<std::uint8_t, 41> buf;
|
||||||
|
std::copy(generator_.begin(), generator_.end(), buf.begin());
|
||||||
|
copy_uint32(buf.data() + 33, seq);
|
||||||
|
|
||||||
|
// The odds that this loop executes more than once are neglible
|
||||||
|
// but we impose a maximum limit just in case.
|
||||||
|
for (std::uint32_t subseq = 0; subseq != 128; ++subseq)
|
||||||
|
{
|
||||||
|
copy_uint32(buf.data() + 37, subseq);
|
||||||
|
|
||||||
|
auto const ret = sha512Half_s(buf);
|
||||||
|
|
||||||
|
if (secp256k1_ec_seckey_verify(secp256k1Context(), ret.data()) == 1)
|
||||||
|
{
|
||||||
|
secure_erase(buf.data(), buf.size());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Throw<std::runtime_error>("Unable to derive generator from seed");
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Generator(Seed const& seed)
|
explicit Generator(Seed const& seed)
|
||||||
|
: root_(deriveDeterministicRootKey(seed))
|
||||||
{
|
{
|
||||||
// FIXME: Avoid copying the seed into a uint128 key only to have
|
secp256k1_pubkey pubkey;
|
||||||
// generateRootDeterministicPublicKey copy out of it.
|
if (secp256k1_ec_pubkey_create(
|
||||||
uint128 ui;
|
secp256k1Context(), &pubkey, root_.data()) != 1)
|
||||||
std::memcpy(ui.data(), seed.data(), seed.size());
|
LogicError("derivePublicKey: secp256k1_ec_pubkey_create failed");
|
||||||
gen_ = generateRootDeterministicPublicKey(ui);
|
|
||||||
|
auto len = generator_.size();
|
||||||
|
|
||||||
|
if (secp256k1_ec_pubkey_serialize(
|
||||||
|
secp256k1Context(),
|
||||||
|
generator_.data(),
|
||||||
|
&len,
|
||||||
|
&pubkey,
|
||||||
|
SECP256K1_EC_COMPRESSED) != 1)
|
||||||
|
LogicError("derivePublicKey: secp256k1_ec_pubkey_serialize failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Generate the nth key pair.
|
~Generator()
|
||||||
|
|
||||||
The seed is required to produce the private key.
|
|
||||||
*/
|
|
||||||
std::pair<PublicKey, SecretKey>
|
|
||||||
operator()(Seed const& seed, std::size_t ordinal) const
|
|
||||||
{
|
{
|
||||||
// FIXME: Avoid copying the seed into a uint128 key only to have
|
secure_erase(root_.data(), root_.size());
|
||||||
// generatePrivateDeterministicKey copy out of it.
|
secure_erase(generator_.data(), generator_.size());
|
||||||
uint128 ui;
|
}
|
||||||
std::memcpy(ui.data(), seed.data(), seed.size());
|
|
||||||
auto gsk = generatePrivateDeterministicKey(gen_, ui, ordinal);
|
/** Generate the nth key pair. */
|
||||||
auto gpk = generatePublicDeterministicKey(gen_, ordinal);
|
std::pair<PublicKey, SecretKey>
|
||||||
SecretKey const sk(Slice{gsk.data(), gsk.size()});
|
operator()(std::size_t ordinal) const
|
||||||
PublicKey const pk(Slice{gpk.data(), gpk.size()});
|
{
|
||||||
secure_erase(ui.data(), ui.size());
|
// Generates Nth secret key:
|
||||||
secure_erase(gsk.data(), gsk.size());
|
auto gsk = [this, tweak = calculateTweak(ordinal)]() {
|
||||||
return {pk, sk};
|
auto rpk = root_;
|
||||||
|
|
||||||
|
if (secp256k1_ec_privkey_tweak_add(
|
||||||
|
secp256k1Context(), rpk.data(), tweak.data()) == 1)
|
||||||
|
{
|
||||||
|
SecretKey sk{Slice{rpk.data(), rpk.size()}};
|
||||||
|
secure_erase(rpk.data(), rpk.size());
|
||||||
|
return sk;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogicError("Unable to add a tweak!");
|
||||||
|
}();
|
||||||
|
|
||||||
|
return {derivePublicKey(KeyType::secp256k1, gsk), gsk};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
} // namespace detail
|
||||||
|
|
||||||
Buffer
|
Buffer
|
||||||
signDigest(PublicKey const& pk, SecretKey const& sk, uint256 const& digest)
|
signDigest(PublicKey const& pk, SecretKey const& sk, uint256 const& digest)
|
||||||
@@ -173,28 +287,22 @@ randomSecretKey()
|
|||||||
return sk;
|
return sk;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VFALCO TODO Rewrite all this without using OpenSSL
|
|
||||||
// or calling into GenerateDetermisticKey
|
|
||||||
SecretKey
|
SecretKey
|
||||||
generateSecretKey(KeyType type, Seed const& seed)
|
generateSecretKey(KeyType type, Seed const& seed)
|
||||||
{
|
{
|
||||||
if (type == KeyType::ed25519)
|
if (type == KeyType::ed25519)
|
||||||
{
|
{
|
||||||
auto key = sha512Half_s(Slice(seed.data(), seed.size()));
|
auto key = sha512Half_s(Slice(seed.data(), seed.size()));
|
||||||
SecretKey sk = Slice{key.data(), key.size()};
|
SecretKey sk{Slice{key.data(), key.size()}};
|
||||||
secure_erase(key.data(), key.size());
|
secure_erase(key.data(), key.size());
|
||||||
return sk;
|
return sk;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == KeyType::secp256k1)
|
if (type == KeyType::secp256k1)
|
||||||
{
|
{
|
||||||
// FIXME: Avoid copying the seed into a uint128 key only to have
|
auto key = detail::deriveDeterministicRootKey(seed);
|
||||||
// generateRootDeterministicPrivateKey copy out of it.
|
SecretKey sk{Slice{key.data(), key.size()}};
|
||||||
uint128 ps;
|
secure_erase(key.data(), key.size());
|
||||||
std::memcpy(ps.data(), seed.data(), seed.size());
|
|
||||||
auto const upk = generateRootDeterministicPrivateKey(ps);
|
|
||||||
SecretKey sk = Slice{upk.data(), upk.size()};
|
|
||||||
secure_erase(ps.data(), ps.size());
|
|
||||||
return sk;
|
return sk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,8 +353,8 @@ generateKeyPair(KeyType type, Seed const& seed)
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case KeyType::secp256k1: {
|
case KeyType::secp256k1: {
|
||||||
Generator g(seed);
|
detail::Generator g(seed);
|
||||||
return g(seed, 0);
|
return g(0);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
case KeyType::ed25519: {
|
case KeyType::ed25519: {
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
Copyright (c) 2018 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 <ripple/beast/unit_test.h>
|
|
||||||
#include <ripple/crypto/impl/openssl.h>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
struct Openssl_test : public beast::unit_test::suite
|
|
||||||
{
|
|
||||||
void
|
|
||||||
testBasicProperties()
|
|
||||||
{
|
|
||||||
using namespace openssl;
|
|
||||||
|
|
||||||
BEAST_EXPECT(std::is_default_constructible<bignum>{});
|
|
||||||
BEAST_EXPECT(!std::is_copy_constructible<bignum>{});
|
|
||||||
BEAST_EXPECT(!std::is_copy_assignable<bignum>{});
|
|
||||||
BEAST_EXPECT(std::is_nothrow_move_constructible<bignum>{});
|
|
||||||
BEAST_EXPECT(std::is_nothrow_move_assignable<bignum>{});
|
|
||||||
|
|
||||||
BEAST_EXPECT(!std::is_default_constructible<ec_point>{});
|
|
||||||
BEAST_EXPECT(!std::is_copy_constructible<ec_point>{});
|
|
||||||
BEAST_EXPECT(!std::is_copy_assignable<ec_point>{});
|
|
||||||
BEAST_EXPECT(std::is_nothrow_move_constructible<ec_point>{});
|
|
||||||
BEAST_EXPECT(!std::is_nothrow_move_assignable<ec_point>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
run() override
|
|
||||||
{
|
|
||||||
testBasicProperties();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE(Openssl, crypto, ripple);
|
|
||||||
|
|
||||||
} // namespace ripple
|
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user