mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-24 13:05:53 +00:00
Refactor GenerateDeterministicKey and its call sites:
Remove the use of ec_key parameters and return values from ECDSA crypto
prototypes. Don't store key data into an ec_key variable only to fetch
it back into the original type again. Use uint256 and Blob explicitly.
Pass private keys as uint256, and pass public keys as either pointer and
length or Blob in calls to ECDSA{Sign,Verify}() and {en,de}cryptECIES().
Replace GenerateRootDeterministicKey() with separate functions returning
either the public or private key, since no caller needs both at once.
Simplify the use of GenerateDeterministicKey within RippleAddress. Call
a single routine rather than pass the result of one as input to another.
Add openssl unit with RAII classes for bignum, bn_ctx, and ec_point plus
free utility functions.
Rewrite the functions in GenerateDeterministicKey.cpp to use RAII rather
than explicit cleanup code:
* factor out secp256k1_group and secp256k1_order for reuse rather than
computing them each time
* replace getPublicKey() with serialize_ec_point(), which makes, sets,
and destroys an ec_key internally (sparing the caller those details)
and calls i2o_ECPublicKey() directly
* return bignum rather than ec_key from GenerateRootDeterministicKey()
* return ec_point rather than EC_KEY* from GenerateRootPubKey()
Move ECDSA{Private,Public}Key() to a new ECDSAKey unit.
Move ec_key.h into impl/ since it's no longer used outside crypto/.
Remove now-unused member functions from ec_key.
Change tabs to spaces; trim trailing whitespace (including blank lines).
This commit is contained in:
committed by
Tom Ritchford
parent
be44f75d2d
commit
7a6d533014
14
Builds/VisualStudio2013/RippleD.vcxproj
Executable file → Normal file
14
Builds/VisualStudio2013/RippleD.vcxproj
Executable file → Normal file
@@ -1945,8 +1945,6 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\crypto\ECIES.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\crypto\ec_key.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\crypto\GenerateDeterministicKey.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\Base58.cpp">
|
||||
@@ -1967,15 +1965,27 @@
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\ECDSACanonical.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\ECDSAKey.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\crypto\impl\ECDSAKey.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\ECIES.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\ec_key.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\crypto\impl\ec_key.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\GenerateDeterministicKey.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\openssl.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\crypto\impl\openssl.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\RandomNumbers.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
||||
@@ -2871,9 +2871,6 @@
|
||||
<ClInclude Include="..\..\src\ripple\crypto\ECIES.h">
|
||||
<Filter>ripple\crypto</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\crypto\ec_key.h">
|
||||
<Filter>ripple\crypto</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\crypto\GenerateDeterministicKey.h">
|
||||
<Filter>ripple\crypto</Filter>
|
||||
</ClInclude>
|
||||
@@ -2895,15 +2892,30 @@
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\ECDSACanonical.cpp">
|
||||
<Filter>ripple\crypto\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\ECDSAKey.cpp">
|
||||
<Filter>ripple\crypto\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\crypto\impl\ECDSAKey.h">
|
||||
<Filter>ripple\crypto\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\ECIES.cpp">
|
||||
<Filter>ripple\crypto\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\ec_key.cpp">
|
||||
<Filter>ripple\crypto\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\crypto\impl\ec_key.h">
|
||||
<Filter>ripple\crypto\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\GenerateDeterministicKey.cpp">
|
||||
<Filter>ripple\crypto\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\crypto\impl\openssl.cpp">
|
||||
<Filter>ripple\crypto\impl</Filter>
|
||||
</ClCompile>
|
||||
<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>
|
||||
|
||||
@@ -20,18 +20,17 @@
|
||||
#ifndef RIPPLE_CRYPTO_ECDSA_H_INCLUDED
|
||||
#define RIPPLE_CRYPTO_ECDSA_H_INCLUDED
|
||||
|
||||
#include <ripple/crypto/ec_key.h>
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <ripple/basics/Blob.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
openssl::ec_key ECDSAPrivateKey (uint256 const& serialized);
|
||||
openssl::ec_key ECDSAPublicKey (Blob const& serialized);
|
||||
Blob ECDSASign (uint256 const& hash, uint256 const& key);
|
||||
|
||||
Blob ECDSASign (uint256 const& hash, const openssl::ec_key& key);
|
||||
|
||||
bool ECDSAVerify (uint256 const& hash, Blob const& sig, const openssl::ec_key& key);
|
||||
bool ECDSAVerify (uint256 const& hash,
|
||||
Blob const& sig,
|
||||
std::uint8_t const* key_data,
|
||||
std::size_t key_size);
|
||||
|
||||
} // ripple
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#ifndef RIPPLE_CRYPTO_ECIES_H_INCLUDED
|
||||
#define RIPPLE_CRYPTO_ECIES_H_INCLUDED
|
||||
|
||||
#include <ripple/crypto/ec_key.h>
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <ripple/basics/Blob.h>
|
||||
|
||||
namespace ripple {
|
||||
@@ -29,8 +29,8 @@ namespace ripple {
|
||||
|
||||
// encrypt/decrypt functions with integrity checking.
|
||||
// Note that the other side must somehow know what keys to use
|
||||
Blob encryptECIES (const openssl::ec_key& secretKey, const openssl::ec_key& publicKey, Blob const& plaintext);
|
||||
Blob decryptECIES (const openssl::ec_key& secretKey, const openssl::ec_key& publicKey, Blob const& ciphertext);
|
||||
Blob encryptECIES (uint256 const& secretKey, Blob const& publicKey, Blob const& plaintext);
|
||||
Blob decryptECIES (uint256 const& secretKey, Blob const& publicKey, Blob const& ciphertext);
|
||||
|
||||
} // ripple
|
||||
|
||||
|
||||
@@ -25,15 +25,15 @@
|
||||
#ifndef RIPPLE_CRYPTO_GENERATEDETERMINISTICKEY_H_INCLUDED
|
||||
#define RIPPLE_CRYPTO_GENERATEDETERMINISTICKEY_H_INCLUDED
|
||||
|
||||
#include <ripple/crypto/ec_key.h>
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
openssl::ec_key GenerateRootDeterministicKey (const uint128& passPhrase);
|
||||
openssl::ec_key GeneratePublicDeterministicKey (Blob const& generator, int n);
|
||||
openssl::ec_key GeneratePrivateDeterministicKey (Blob const& family, const BIGNUM* rootPriv, int n);
|
||||
Blob GenerateRootDeterministicPublicKey (const uint128& passPhrase);
|
||||
uint256 GenerateRootDeterministicPrivateKey (const uint128& passPhrase);
|
||||
|
||||
Blob GeneratePublicDeterministicKey (Blob const& generator, int n);
|
||||
uint256 GeneratePrivateDeterministicKey (Blob const& family, uint128 const& seed, int n);
|
||||
|
||||
} // ripple
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/crypto/ECDSA.h>
|
||||
#include <ripple/crypto/ECDSACanonical.h>
|
||||
#include <ripple/crypto/impl/ec_key.h>
|
||||
#include <ripple/crypto/impl/ECDSAKey.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/hmac.h>
|
||||
@@ -34,63 +36,7 @@ namespace ripple {
|
||||
|
||||
using openssl::ec_key;
|
||||
|
||||
static EC_KEY* new_initialized_EC_KEY()
|
||||
{
|
||||
EC_KEY* key = EC_KEY_new_by_curve_name (NID_secp256k1);
|
||||
|
||||
if (key == nullptr)
|
||||
{
|
||||
throw std::runtime_error ("new_initialized_EC_KEY() : EC_KEY_new_by_curve_name failed");
|
||||
}
|
||||
|
||||
EC_KEY_set_conv_form (key, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
ec_key ECDSAPrivateKey (uint256 const& serialized)
|
||||
{
|
||||
EC_KEY* key = new_initialized_EC_KEY();
|
||||
|
||||
BIGNUM* bn = BN_bin2bn (serialized.begin(), serialized.size(), nullptr);
|
||||
|
||||
if (bn == nullptr)
|
||||
{
|
||||
// leaks key
|
||||
throw std::runtime_error ("ec_key::ec_key: BN_bin2bn failed");
|
||||
}
|
||||
|
||||
const bool ok = EC_KEY_set_private_key (key, bn);
|
||||
|
||||
BN_clear_free (bn);
|
||||
|
||||
if (! ok)
|
||||
{
|
||||
EC_KEY_free (key);
|
||||
}
|
||||
|
||||
return ec_key::acquire ((ec_key::pointer_t) key);
|
||||
}
|
||||
|
||||
ec_key ECDSAPublicKey (Blob const& serialized)
|
||||
{
|
||||
EC_KEY* key = new_initialized_EC_KEY();
|
||||
|
||||
std::uint8_t const* begin = &serialized[0];
|
||||
|
||||
if (o2i_ECPublicKey (&key, &begin, serialized.size()) != nullptr)
|
||||
{
|
||||
EC_KEY_set_conv_form (key, POINT_CONVERSION_COMPRESSED);
|
||||
}
|
||||
else
|
||||
{
|
||||
EC_KEY_free (key);
|
||||
}
|
||||
|
||||
return ec_key::acquire ((ec_key::pointer_t) key);
|
||||
}
|
||||
|
||||
Blob ECDSASign (uint256 const& hash, const openssl::ec_key& key)
|
||||
static Blob ECDSASign (uint256 const& hash, const openssl::ec_key& key)
|
||||
{
|
||||
Blob result;
|
||||
|
||||
@@ -112,15 +58,28 @@ Blob ECDSASign (uint256 const& hash, const openssl::ec_key& key)
|
||||
return result;
|
||||
}
|
||||
|
||||
Blob ECDSASign (uint256 const& hash, uint256 const& key)
|
||||
{
|
||||
return ECDSASign (hash, ECDSAPrivateKey (key));
|
||||
}
|
||||
|
||||
static bool ECDSAVerify (uint256 const& hash, std::uint8_t const* sig, size_t sigLen, EC_KEY* key)
|
||||
{
|
||||
// -1 = error, 0 = bad sig, 1 = good
|
||||
return ECDSA_verify (0, hash.begin(), hash.size(), sig, sigLen, key) > 0;
|
||||
}
|
||||
|
||||
bool ECDSAVerify (uint256 const& hash, Blob const& sig, const openssl::ec_key& key)
|
||||
static bool ECDSAVerify (uint256 const& hash, Blob const& sig, const openssl::ec_key& key)
|
||||
{
|
||||
return ECDSAVerify (hash, sig.data(), sig.size(), (EC_KEY*) key.get());
|
||||
}
|
||||
|
||||
bool ECDSAVerify (uint256 const& hash,
|
||||
Blob const& sig,
|
||||
std::uint8_t const* key_data,
|
||||
std::size_t key_size)
|
||||
{
|
||||
return ECDSAVerify (hash, sig, ECDSAPublicKey (key_data, key_size));
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
92
src/ripple/crypto/impl/ECDSAKey.cpp
Normal file
92
src/ripple/crypto/impl/ECDSAKey.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <BeastConfig.h>
|
||||
#include <ripple/crypto/impl/ECDSAKey.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
using openssl::ec_key;
|
||||
|
||||
static EC_KEY* new_initialized_EC_KEY()
|
||||
{
|
||||
EC_KEY* key = EC_KEY_new_by_curve_name (NID_secp256k1);
|
||||
|
||||
if (key == nullptr)
|
||||
{
|
||||
throw std::runtime_error ("new_initialized_EC_KEY() : EC_KEY_new_by_curve_name failed");
|
||||
}
|
||||
|
||||
EC_KEY_set_conv_form (key, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
ec_key ECDSAPrivateKey (uint256 const& serialized)
|
||||
{
|
||||
BIGNUM* bn = BN_bin2bn (serialized.begin(), serialized.size(), nullptr);
|
||||
|
||||
if (bn == nullptr)
|
||||
{
|
||||
throw std::runtime_error ("ec_key::ec_key: BN_bin2bn failed");
|
||||
}
|
||||
|
||||
EC_KEY* key = new_initialized_EC_KEY();
|
||||
|
||||
const bool ok = EC_KEY_set_private_key (key, bn);
|
||||
|
||||
BN_clear_free (bn);
|
||||
|
||||
if (! ok)
|
||||
{
|
||||
EC_KEY_free (key);
|
||||
}
|
||||
|
||||
return ec_key::acquire ((ec_key::pointer_t) key);
|
||||
}
|
||||
|
||||
ec_key ECDSAPublicKey (std::uint8_t const* data, std::size_t size)
|
||||
{
|
||||
EC_KEY* key = new_initialized_EC_KEY();
|
||||
|
||||
if (o2i_ECPublicKey (&key, &data, size) != nullptr)
|
||||
{
|
||||
EC_KEY_set_conv_form (key, POINT_CONVERSION_COMPRESSED);
|
||||
}
|
||||
else
|
||||
{
|
||||
EC_KEY_free (key);
|
||||
}
|
||||
|
||||
return ec_key::acquire ((ec_key::pointer_t) key);
|
||||
}
|
||||
|
||||
ec_key ECDSAPublicKey (Blob const& serialized)
|
||||
{
|
||||
return ECDSAPublicKey (&serialized[0], serialized.size());
|
||||
}
|
||||
|
||||
} // ripple
|
||||
36
src/ripple/crypto/impl/ECDSAKey.h
Normal file
36
src/ripple/crypto/impl/ECDSAKey.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_ECDSAKEY_H
|
||||
#define RIPPLE_ECDSAKEY_H
|
||||
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <ripple/basics/Blob.h>
|
||||
#include <ripple/crypto/impl/ec_key.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
openssl::ec_key ECDSAPrivateKey (uint256 const& serialized);
|
||||
openssl::ec_key ECDSAPublicKey (Blob const& serialized);
|
||||
|
||||
openssl::ec_key ECDSAPublicKey (std::uint8_t const* data, std::size_t size);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/crypto/ECIES.h>
|
||||
#include <ripple/crypto/impl/ec_key.h>
|
||||
#include <ripple/crypto/impl/ECDSAKey.h>
|
||||
#include <ripple/crypto/RandomNumbers.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
@@ -97,6 +99,14 @@ static void getECIESSecret (const openssl::ec_key& secretKey, const openssl::ec_
|
||||
memset (hbuf, 0, ECIES_KEY_LENGTH);
|
||||
}
|
||||
|
||||
static void getECIESSecret (uint256 const& secretKey,
|
||||
Blob const& publicKey,
|
||||
ECIES_ENC_KEY_TYPE& enc_key,
|
||||
ECIES_HMAC_KEY_TYPE& hmac_key)
|
||||
{
|
||||
getECIESSecret (ECDSAPrivateKey (secretKey), ECDSAPublicKey (publicKey), enc_key, hmac_key);
|
||||
}
|
||||
|
||||
static ECIES_HMAC_TYPE makeHMAC (const ECIES_HMAC_KEY_TYPE& secret, Blob const& data)
|
||||
{
|
||||
HMAC_CTX ctx;
|
||||
@@ -129,7 +139,7 @@ static ECIES_HMAC_TYPE makeHMAC (const ECIES_HMAC_KEY_TYPE& secret, Blob const&
|
||||
return ret;
|
||||
}
|
||||
|
||||
Blob encryptECIES (const openssl::ec_key& secretKey, const openssl::ec_key& publicKey, Blob const& plaintext)
|
||||
Blob encryptECIES (uint256 const& secretKey, Blob const& publicKey, Blob const& plaintext)
|
||||
{
|
||||
|
||||
ECIES_ENC_IV_TYPE iv;
|
||||
@@ -204,7 +214,7 @@ Blob encryptECIES (const openssl::ec_key& secretKey, const openssl::ec_key& publ
|
||||
return out;
|
||||
}
|
||||
|
||||
Blob decryptECIES (const openssl::ec_key& secretKey, const openssl::ec_key& publicKey, Blob const& ciphertext)
|
||||
Blob decryptECIES (uint256 const& secretKey, Blob const& publicKey, Blob const& ciphertext)
|
||||
{
|
||||
// minimum ciphertext = IV + HMAC + 1 block
|
||||
if (ciphertext.size () < ((2 * ECIES_ENC_BLK_SIZE) + ECIES_HMAC_SIZE) )
|
||||
|
||||
@@ -19,17 +19,32 @@
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/crypto/GenerateDeterministicKey.h>
|
||||
#include <ripple/crypto/Base58.h>
|
||||
#include <ripple/crypto/CBigNum.h>
|
||||
#include <ripple/crypto/impl/ec_key.h>
|
||||
#include <ripple/crypto/impl/openssl.h>
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
using openssl::ec_key;
|
||||
namespace openssl {
|
||||
|
||||
static EC_GROUP const* const secp256k1_group = EC_GROUP_new_by_curve_name (NID_secp256k1);
|
||||
static bignum const secp256k1_order = get_order (secp256k1_group);
|
||||
|
||||
} // 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;
|
||||
}
|
||||
|
||||
uint256
|
||||
getSHA512Half (void const* data, std::size_t bytes)
|
||||
@@ -56,43 +71,12 @@ copy_uint32 (FwdIt out, std::uint32_t v)
|
||||
|
||||
// --> seed
|
||||
// <-- private root generator + public root generator
|
||||
ec_key GenerateRootDeterministicKey (uint128 const& seed)
|
||||
static bignum GenerateRootDeterministicKey (uint128 const& seed)
|
||||
{
|
||||
BN_CTX* ctx = BN_CTX_new ();
|
||||
|
||||
if (!ctx) return ec_key::invalid;
|
||||
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
|
||||
|
||||
if (!pkey)
|
||||
{
|
||||
BN_CTX_free (ctx);
|
||||
return ec_key::invalid;
|
||||
}
|
||||
|
||||
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
BIGNUM* order = BN_new ();
|
||||
|
||||
if (!order)
|
||||
{
|
||||
BN_CTX_free (ctx);
|
||||
EC_KEY_free (pkey);
|
||||
return ec_key::invalid;
|
||||
}
|
||||
|
||||
if (!EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
|
||||
{
|
||||
assert (false);
|
||||
BN_free (order);
|
||||
EC_KEY_free (pkey);
|
||||
BN_CTX_free (ctx);
|
||||
return ec_key::invalid;
|
||||
}
|
||||
|
||||
// find non-zero private key less than the curve's order
|
||||
BIGNUM* privKey = nullptr;
|
||||
bignum privKey;
|
||||
std::uint32_t seq = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// buf: 0 seed 16 seq 20
|
||||
@@ -102,114 +86,54 @@ ec_key GenerateRootDeterministicKey (uint128 const& seed)
|
||||
copy_uint32 (buf.begin() + 16, seq++);
|
||||
uint256 root = getSHA512Half (buf.data(), buf.size());
|
||||
std::fill (buf.begin(), buf.end(), 0); // security erase
|
||||
privKey = BN_bin2bn ((const unsigned char*) &root, sizeof (root), privKey);
|
||||
if (privKey == nullptr)
|
||||
{
|
||||
EC_KEY_free (pkey);
|
||||
BN_free (order);
|
||||
BN_CTX_free (ctx);
|
||||
return ec_key::invalid;
|
||||
}
|
||||
privKey.assign ((unsigned char const*) &root, sizeof (root));
|
||||
|
||||
root.zero(); // security erase
|
||||
}
|
||||
while (BN_is_zero (privKey) || (BN_cmp (privKey, order) >= 0));
|
||||
while (privKey.is_zero() || privKey >= secp256k1_order);
|
||||
|
||||
BN_free (order);
|
||||
|
||||
if (!EC_KEY_set_private_key (pkey, privKey))
|
||||
{
|
||||
// set the random point as the private key
|
||||
assert (false);
|
||||
EC_KEY_free (pkey);
|
||||
BN_clear_free (privKey);
|
||||
BN_CTX_free (ctx);
|
||||
return ec_key::invalid;
|
||||
return privKey;
|
||||
}
|
||||
|
||||
EC_POINT* pubKey = EC_POINT_new (EC_KEY_get0_group (pkey));
|
||||
|
||||
if (!EC_POINT_mul (EC_KEY_get0_group (pkey), pubKey, privKey, nullptr, nullptr, ctx))
|
||||
// --> 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
|
||||
assert (false);
|
||||
BN_clear_free (privKey);
|
||||
EC_POINT_free (pubKey);
|
||||
EC_KEY_free (pkey);
|
||||
BN_CTX_free (ctx);
|
||||
return ec_key::invalid;
|
||||
ec_point pubKey = multiply (secp256k1_group, privKey, ctx);
|
||||
|
||||
privKey.clear(); // security erase
|
||||
|
||||
return serialize_ec_point (pubKey);
|
||||
}
|
||||
|
||||
BN_clear_free (privKey);
|
||||
|
||||
if (!EC_KEY_set_public_key (pkey, pubKey))
|
||||
uint256 GenerateRootDeterministicPrivateKey (uint128 const& seed)
|
||||
{
|
||||
assert (false);
|
||||
EC_POINT_free (pubKey);
|
||||
EC_KEY_free (pkey);
|
||||
BN_CTX_free (ctx);
|
||||
return ec_key::invalid;
|
||||
}
|
||||
bignum key = GenerateRootDeterministicKey (seed);
|
||||
|
||||
EC_POINT_free (pubKey);
|
||||
|
||||
BN_CTX_free (ctx);
|
||||
|
||||
#ifdef EC_DEBUG
|
||||
assert (EC_KEY_check_key (pkey) == 1); // CAUTION: This check is *very* expensive
|
||||
#endif
|
||||
return ec_key::acquire ((ec_key::pointer_t) pkey);
|
||||
return uint256_from_bignum_clear (key);
|
||||
}
|
||||
|
||||
// Take ripple address.
|
||||
// --> root public generator (consumes)
|
||||
// <-- root public generator in EC format
|
||||
static EC_KEY* GenerateRootPubKey (BIGNUM* pubGenerator)
|
||||
static ec_point GenerateRootPubKey (bignum&& pubGenerator)
|
||||
{
|
||||
if (pubGenerator == nullptr)
|
||||
{
|
||||
assert (false);
|
||||
return nullptr;
|
||||
}
|
||||
ec_point pubPoint = bn2point (secp256k1_group, pubGenerator.get());
|
||||
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
|
||||
|
||||
if (!pkey)
|
||||
{
|
||||
BN_free (pubGenerator);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
EC_POINT* pubPoint = EC_POINT_bn2point (EC_KEY_get0_group (pkey), pubGenerator, nullptr, nullptr);
|
||||
BN_free (pubGenerator);
|
||||
|
||||
if (!pubPoint)
|
||||
{
|
||||
assert (false);
|
||||
EC_KEY_free (pkey);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!EC_KEY_set_public_key (pkey, pubPoint))
|
||||
{
|
||||
assert (false);
|
||||
EC_POINT_free (pubPoint);
|
||||
EC_KEY_free (pkey);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EC_POINT_free (pubPoint);
|
||||
|
||||
return pkey;
|
||||
return pubPoint;
|
||||
}
|
||||
|
||||
// --> public generator
|
||||
static BIGNUM* makeHash (Blob const& pubGen, int seq, BIGNUM const* order)
|
||||
static bignum makeHash (Blob const& pubGen, int seq, bignum const& order)
|
||||
{
|
||||
int subSeq = 0;
|
||||
BIGNUM* ret = nullptr;
|
||||
|
||||
bignum result;
|
||||
|
||||
assert(pubGen.size() == 33);
|
||||
do
|
||||
@@ -222,167 +146,51 @@ static BIGNUM* makeHash (Blob const& pubGen, int seq, BIGNUM const* order)
|
||||
copy_uint32 (buf.begin() + 37, subSeq++);
|
||||
uint256 root = getSHA512Half (buf.data(), buf.size());
|
||||
std::fill(buf.begin(), buf.end(), 0); // security erase
|
||||
ret = BN_bin2bn ((const unsigned char*) &root, sizeof (root), ret);
|
||||
if (!ret) return nullptr;
|
||||
result.assign ((unsigned char const*) &root, sizeof (root));
|
||||
root.zero(); // security erase
|
||||
}
|
||||
while (BN_is_zero (ret) || (BN_cmp (ret, order) >= 0));
|
||||
while (result.is_zero() || result >= order);
|
||||
|
||||
return ret;
|
||||
return result;
|
||||
}
|
||||
|
||||
// --> public generator
|
||||
ec_key GeneratePublicDeterministicKey (Blob const& pubGen, int seq)
|
||||
Blob GeneratePublicDeterministicKey (Blob const& pubGen, int seq)
|
||||
{
|
||||
// publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
|
||||
BIGNUM* generator = BN_bin2bn (
|
||||
pubGen.data(),
|
||||
pubGen.size(),
|
||||
nullptr);
|
||||
ec_point rootPubKey = GenerateRootPubKey (bignum (pubGen));
|
||||
|
||||
if (generator == nullptr)
|
||||
return ec_key::invalid;
|
||||
|
||||
EC_KEY* rootKey = GenerateRootPubKey (generator);
|
||||
const EC_POINT* rootPubKey = EC_KEY_get0_public_key (rootKey);
|
||||
BN_CTX* ctx = BN_CTX_new ();
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
|
||||
EC_POINT* newPoint = 0;
|
||||
BIGNUM* order = 0;
|
||||
BIGNUM* hash = 0;
|
||||
bool success = true;
|
||||
|
||||
if (!ctx || !pkey) success = false;
|
||||
|
||||
if (success)
|
||||
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
if (success)
|
||||
{
|
||||
newPoint = EC_POINT_new (EC_KEY_get0_group (pkey));
|
||||
|
||||
if (!newPoint) success = false;
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
order = BN_new ();
|
||||
|
||||
if (!order || !EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
|
||||
success = false;
|
||||
}
|
||||
bn_ctx ctx;
|
||||
|
||||
// Calculate the private additional key.
|
||||
if (success)
|
||||
{
|
||||
hash = makeHash (pubGen, seq, order);
|
||||
bignum hash = makeHash (pubGen, seq, secp256k1_order);
|
||||
|
||||
if (!hash) success = false;
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
// Calculate the corresponding public key.
|
||||
EC_POINT_mul (EC_KEY_get0_group (pkey), newPoint, hash, nullptr, nullptr, ctx);
|
||||
ec_point newPoint = multiply (secp256k1_group, hash, ctx);
|
||||
|
||||
// Add the master public key and set.
|
||||
EC_POINT_add (EC_KEY_get0_group (pkey), newPoint, newPoint, rootPubKey, ctx);
|
||||
EC_KEY_set_public_key (pkey, newPoint);
|
||||
}
|
||||
add_to (secp256k1_group, rootPubKey, newPoint, ctx);
|
||||
|
||||
if (order) BN_free (order);
|
||||
|
||||
if (hash) BN_free (hash);
|
||||
|
||||
if (newPoint) EC_POINT_free (newPoint);
|
||||
|
||||
if (ctx) BN_CTX_free (ctx);
|
||||
|
||||
if (rootKey) EC_KEY_free (rootKey);
|
||||
|
||||
if (pkey && !success) EC_KEY_free (pkey);
|
||||
|
||||
return success ? ec_key::acquire ((ec_key::pointer_t) pkey) : ec_key::invalid;
|
||||
return serialize_ec_point (newPoint);
|
||||
}
|
||||
|
||||
// --> root private key
|
||||
ec_key GeneratePrivateDeterministicKey (Blob const& pubGen, const BIGNUM* rootPrivKey, int seq)
|
||||
uint256 GeneratePrivateDeterministicKey (Blob const& pubGen, uint128 const& seed, int seq)
|
||||
{
|
||||
// privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
|
||||
BN_CTX* ctx = BN_CTX_new ();
|
||||
bignum rootPrivKey = GenerateRootDeterministicKey (seed);
|
||||
|
||||
if (ctx == nullptr) return ec_key::invalid;
|
||||
|
||||
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
|
||||
|
||||
if (pkey == nullptr)
|
||||
{
|
||||
BN_CTX_free (ctx);
|
||||
return ec_key::invalid;
|
||||
}
|
||||
|
||||
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
BIGNUM* order = BN_new ();
|
||||
|
||||
if (order == nullptr)
|
||||
{
|
||||
BN_CTX_free (ctx);
|
||||
EC_KEY_free (pkey);
|
||||
return ec_key::invalid;
|
||||
}
|
||||
|
||||
if (!EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
|
||||
{
|
||||
BN_free (order);
|
||||
BN_CTX_free (ctx);
|
||||
EC_KEY_free (pkey);
|
||||
return ec_key::invalid;
|
||||
}
|
||||
bn_ctx ctx;
|
||||
|
||||
// calculate the private additional key
|
||||
BIGNUM* privKey = makeHash (pubGen, seq, order);
|
||||
|
||||
if (privKey == nullptr)
|
||||
{
|
||||
BN_free (order);
|
||||
BN_CTX_free (ctx);
|
||||
EC_KEY_free (pkey);
|
||||
return ec_key::invalid;
|
||||
}
|
||||
bignum privKey = makeHash (pubGen, seq, secp256k1_order);
|
||||
|
||||
// calculate the final private key
|
||||
BN_mod_add (privKey, privKey, rootPrivKey, order, ctx);
|
||||
BN_free (order);
|
||||
EC_KEY_set_private_key (pkey, privKey);
|
||||
add_to (rootPrivKey, privKey, secp256k1_order, ctx);
|
||||
|
||||
// compute the corresponding public key
|
||||
EC_POINT* pubKey = EC_POINT_new (EC_KEY_get0_group (pkey));
|
||||
rootPrivKey.clear(); // security erase
|
||||
|
||||
if (!pubKey)
|
||||
{
|
||||
BN_clear_free (privKey);
|
||||
BN_CTX_free (ctx);
|
||||
EC_KEY_free (pkey);
|
||||
return ec_key::invalid;
|
||||
}
|
||||
|
||||
if (EC_POINT_mul (EC_KEY_get0_group (pkey), pubKey, privKey, nullptr, nullptr, ctx) == 0)
|
||||
{
|
||||
BN_clear_free (privKey);
|
||||
EC_POINT_free (pubKey);
|
||||
EC_KEY_free (pkey);
|
||||
BN_CTX_free (ctx);
|
||||
return ec_key::invalid;
|
||||
}
|
||||
|
||||
BN_clear_free (privKey);
|
||||
EC_KEY_set_public_key (pkey, pubKey);
|
||||
|
||||
EC_POINT_free (pubKey);
|
||||
BN_CTX_free (ctx);
|
||||
|
||||
return ec_key::acquire ((ec_key::pointer_t) pkey);
|
||||
return uint256_from_bignum_clear (privKey);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/crypto/ec_key.h>
|
||||
#include <ripple/crypto/impl/ec_key.h>
|
||||
#include <openssl/ec.h>
|
||||
|
||||
namespace ripple {
|
||||
@@ -63,53 +63,5 @@ void ec_key::destroy()
|
||||
}
|
||||
}
|
||||
|
||||
uint256 ec_key::get_private_key() const
|
||||
{
|
||||
uint256 result;
|
||||
result.zero();
|
||||
|
||||
if (valid())
|
||||
{
|
||||
const BIGNUM* bn = EC_KEY_get0_private_key (get_EC_KEY (*this));
|
||||
|
||||
if (bn == nullptr)
|
||||
{
|
||||
throw std::runtime_error ("ec_key::get_private_key: EC_KEY_get0_private_key failed");
|
||||
}
|
||||
|
||||
BN_bn2bin (bn, result.end() - BN_num_bytes (bn));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::size_t ec_key::get_public_key_size() const
|
||||
{
|
||||
int const size = i2o_ECPublicKey (get_EC_KEY (*this), nullptr);
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
throw std::runtime_error ("ec_key::get_public_key_size() : i2o_ECPublicKey failed");
|
||||
}
|
||||
|
||||
if (size > get_public_key_max_size())
|
||||
{
|
||||
throw std::runtime_error ("ec_key::get_public_key_size() : i2o_ECPublicKey() result too big");
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
std::uint8_t ec_key::get_public_key (std::uint8_t* buffer) const
|
||||
{
|
||||
std::uint8_t* begin = buffer;
|
||||
|
||||
int const size = i2o_ECPublicKey (get_EC_KEY (*this), &begin);
|
||||
|
||||
assert (size == get_public_key_size());
|
||||
|
||||
return std::uint8_t (size);
|
||||
}
|
||||
|
||||
} // openssl
|
||||
} // ripple
|
||||
|
||||
@@ -67,14 +67,6 @@ public:
|
||||
}
|
||||
|
||||
bool valid() const { return ptr != nullptr; }
|
||||
|
||||
uint256 get_private_key() const;
|
||||
|
||||
static std::size_t get_public_key_max_size() { return 33; }
|
||||
|
||||
std::size_t get_public_key_size() const;
|
||||
|
||||
std::uint8_t get_public_key (std::uint8_t* buffer) const;
|
||||
};
|
||||
|
||||
} // openssl
|
||||
154
src/ripple/crypto/impl/openssl.cpp
Normal file
154
src/ripple/crypto/impl/openssl.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/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::acquire ((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);
|
||||
}
|
||||
|
||||
} // openssl
|
||||
} // ripple
|
||||
200
src/ripple/crypto/impl/openssl.h
Normal file
200
src/ripple/crypto/impl/openssl.h
Normal file
@@ -0,0 +1,200 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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) : ptr( that.ptr )
|
||||
{
|
||||
that.ptr = nullptr;
|
||||
}
|
||||
|
||||
bignum& operator= (bignum&& that)
|
||||
{
|
||||
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 bignum get_order (EC_GROUP const* group)
|
||||
{
|
||||
bn_ctx ctx;
|
||||
|
||||
return get_order (group, 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:
|
||||
typedef EC_POINT* pointer_t;
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
} // openssl
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -40,11 +40,8 @@ public:
|
||||
seed1.SetHex ("71ED064155FFADFA38782C5E0158CB26");
|
||||
seed2.SetHex ("CF0C3BE4485961858C4198515AE5B965");
|
||||
|
||||
openssl::ec_key root1 = GenerateRootDeterministicKey (seed1);
|
||||
openssl::ec_key root2 = GenerateRootDeterministicKey (seed2);
|
||||
|
||||
uint256 const priv1 = root1.get_private_key();
|
||||
uint256 const priv2 = root2.get_private_key();
|
||||
uint256 const priv1 = GenerateRootDeterministicPrivateKey (seed1);
|
||||
uint256 const priv2 = GenerateRootDeterministicPrivateKey (seed2);
|
||||
|
||||
unexpected (to_string (priv1) != "7CFBA64F771E93E817E15039215430B53F7401C34931D111EAB3510B22DBB0D8",
|
||||
"Incorrect private key for generator");
|
||||
@@ -57,4 +54,3 @@ public:
|
||||
BEAST_DEFINE_TESTSUITE(CKey,ripple_data,ripple);
|
||||
|
||||
} // ripple
|
||||
|
||||
|
||||
@@ -30,18 +30,11 @@
|
||||
#include <ripple/protocol/RipplePublicKey.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <openssl/ripemd.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <mutex>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
static BIGNUM* GetSecretBN (const openssl::ec_key& keypair)
|
||||
{
|
||||
// DEPRECATED
|
||||
return BN_dup (EC_KEY_get0_private_key ((EC_KEY*) keypair.get()));
|
||||
}
|
||||
|
||||
// <-- seed
|
||||
static uint128 PassPhraseToKey (std::string const& passPhrase)
|
||||
{
|
||||
@@ -57,15 +50,6 @@ static uint128 PassPhraseToKey (std::string const& passPhrase)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Blob getPublicKey (openssl::ec_key const& key)
|
||||
{
|
||||
Blob result (33);
|
||||
|
||||
key.get_public_key (&result[0]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool verifySignature (Blob const& pubkey, uint256 const& hash, Blob const& sig, ECDSA fullyCanonical)
|
||||
{
|
||||
if (! isCanonicalECDSASig (sig, fullyCanonical))
|
||||
@@ -73,9 +57,7 @@ static bool verifySignature (Blob const& pubkey, uint256 const& hash, Blob const
|
||||
return false;
|
||||
}
|
||||
|
||||
openssl::ec_key key = ECDSAPublicKey (pubkey);
|
||||
|
||||
return key.valid() && ECDSAVerify (hash, sig, key);
|
||||
return ECDSAVerify (hash, sig, &pubkey[0], pubkey.size());
|
||||
}
|
||||
|
||||
RippleAddress::RippleAddress ()
|
||||
@@ -116,7 +98,7 @@ RippleAddress RippleAddress::createNodePublic (RippleAddress const& naSeed)
|
||||
RippleAddress naNew;
|
||||
|
||||
// YYY Should there be a GetPubKey() equiv that returns a uint256?
|
||||
naNew.setNodePublic (getPublicKey (GenerateRootDeterministicKey (naSeed.getSeed())));
|
||||
naNew.setNodePublic (GenerateRootDeterministicPublicKey (naSeed.getSeed()));
|
||||
|
||||
return naNew;
|
||||
}
|
||||
@@ -229,7 +211,7 @@ RippleAddress RippleAddress::createNodePrivate (RippleAddress const& naSeed)
|
||||
{
|
||||
RippleAddress naNew;
|
||||
|
||||
naNew.setNodePrivate (GenerateRootDeterministicKey (naSeed.getSeed()).get_private_key());
|
||||
naNew.setNodePrivate (GenerateRootDeterministicPrivateKey (naSeed.getSeed()));
|
||||
|
||||
return naNew;
|
||||
}
|
||||
@@ -302,9 +284,7 @@ void RippleAddress::setNodePrivate (uint256 hash256)
|
||||
|
||||
void RippleAddress::signNodePrivate (uint256 const& hash, Blob& vchSig) const
|
||||
{
|
||||
openssl::ec_key key = ECDSAPrivateKey (getNodePrivate());
|
||||
|
||||
vchSig = ECDSASign (hash, key);
|
||||
vchSig = ECDSASign (hash, getNodePrivate());
|
||||
|
||||
if (vchSig.empty())
|
||||
throw std::runtime_error ("Signing failed.");
|
||||
@@ -502,7 +482,7 @@ void RippleAddress::setAccountPublic (Blob const& vPublic)
|
||||
|
||||
void RippleAddress::setAccountPublic (RippleAddress const& generator, int seq)
|
||||
{
|
||||
setAccountPublic (getPublicKey (GeneratePublicDeterministicKey (generator.getGenerator(), seq)));
|
||||
setAccountPublic (GeneratePublicDeterministicKey (generator.getGenerator(), seq));
|
||||
}
|
||||
|
||||
bool RippleAddress::accountPublicVerify (
|
||||
@@ -571,26 +551,14 @@ void RippleAddress::setAccountPrivate (uint256 hash256)
|
||||
void RippleAddress::setAccountPrivate (
|
||||
RippleAddress const& generator, RippleAddress const& naSeed, int seq)
|
||||
{
|
||||
openssl::ec_key publicKey = GenerateRootDeterministicKey (naSeed.getSeed());
|
||||
openssl::ec_key secretKey = GeneratePrivateDeterministicKey (generator.getGenerator(), GetSecretBN (publicKey), seq);
|
||||
uint256 secretKey = GeneratePrivateDeterministicKey (generator.getGenerator(), naSeed.getSeed(), seq);
|
||||
|
||||
setAccountPrivate (secretKey.get_private_key());
|
||||
setAccountPrivate (secretKey);
|
||||
}
|
||||
|
||||
bool RippleAddress::accountPrivateSign (uint256 const& uHash, Blob& vucSig) const
|
||||
{
|
||||
openssl::ec_key key = ECDSAPrivateKey (getAccountPrivate());
|
||||
|
||||
if (!key.valid())
|
||||
{
|
||||
// Bad private key.
|
||||
WriteLog (lsWARNING, RippleAddress)
|
||||
<< "accountPrivateSign: Bad private key.";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
vucSig = ECDSASign (uHash, key);
|
||||
vucSig = ECDSASign (uHash, getAccountPrivate());
|
||||
const bool ok = !vucSig.empty();
|
||||
|
||||
CondLog (!ok, lsWARNING, RippleAddress)
|
||||
@@ -602,23 +570,11 @@ bool RippleAddress::accountPrivateSign (uint256 const& uHash, Blob& vucSig) cons
|
||||
Blob RippleAddress::accountPrivateEncrypt (
|
||||
RippleAddress const& naPublicTo, Blob const& vucPlainText) const
|
||||
{
|
||||
openssl::ec_key secretKey = ECDSAPrivateKey (getAccountPrivate());
|
||||
openssl::ec_key publicKey = ECDSAPublicKey (naPublicTo.getAccountPublic());
|
||||
uint256 secretKey = getAccountPrivate();
|
||||
Blob publicKey = naPublicTo.getAccountPublic();
|
||||
|
||||
Blob vucCipherText;
|
||||
|
||||
if (! publicKey.valid())
|
||||
{
|
||||
WriteLog (lsWARNING, RippleAddress)
|
||||
<< "accountPrivateEncrypt: Bad public key.";
|
||||
}
|
||||
|
||||
if (! secretKey.valid())
|
||||
{
|
||||
WriteLog (lsWARNING, RippleAddress)
|
||||
<< "accountPrivateEncrypt: Bad private key.";
|
||||
}
|
||||
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -635,23 +591,11 @@ Blob RippleAddress::accountPrivateEncrypt (
|
||||
Blob RippleAddress::accountPrivateDecrypt (
|
||||
RippleAddress const& naPublicFrom, Blob const& vucCipherText) const
|
||||
{
|
||||
openssl::ec_key secretKey = ECDSAPrivateKey (getAccountPrivate());
|
||||
openssl::ec_key publicKey = ECDSAPublicKey (naPublicFrom.getAccountPublic());
|
||||
uint256 secretKey = getAccountPrivate();
|
||||
Blob publicKey = naPublicFrom.getAccountPublic();
|
||||
|
||||
Blob vucPlainText;
|
||||
|
||||
if (! publicKey.valid())
|
||||
{
|
||||
WriteLog (lsWARNING, RippleAddress)
|
||||
<< "accountPrivateDecrypt: Bad public key.";
|
||||
}
|
||||
|
||||
if (! secretKey.valid())
|
||||
{
|
||||
WriteLog (lsWARNING, RippleAddress)
|
||||
<< "accountPrivateDecrypt: Bad private key.";
|
||||
}
|
||||
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -710,7 +654,7 @@ void RippleAddress::setGenerator (Blob const& vPublic)
|
||||
RippleAddress RippleAddress::createGeneratorPublic (RippleAddress const& naSeed)
|
||||
{
|
||||
RippleAddress naNew;
|
||||
naNew.setGenerator (getPublicKey (GenerateRootDeterministicKey (naSeed.getSeed())));
|
||||
naNew.setGenerator (GenerateRootDeterministicPublicKey (naSeed.getSeed()));
|
||||
return naNew;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,10 @@
|
||||
#include <ripple/crypto/impl/ec_key.cpp>
|
||||
#include <ripple/crypto/impl/ECDSA.cpp>
|
||||
#include <ripple/crypto/impl/ECDSACanonical.cpp>
|
||||
#include <ripple/crypto/impl/ECDSAKey.cpp>
|
||||
#include <ripple/crypto/impl/ECIES.cpp>
|
||||
#include <ripple/crypto/impl/GenerateDeterministicKey.cpp>
|
||||
#include <ripple/crypto/impl/openssl.cpp>
|
||||
#include <ripple/crypto/impl/RandomNumbers.cpp>
|
||||
#include <ripple/crypto/impl/RFC1751.cpp>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user