Clean up CKey and RippleAddress (RIPD-672)

* Remove CKey dependency on RippleAddress
* Create RAII ec_key wrapper that hides EC_KEY and other OpenSSL details
* Move CKey member logic into free functions
* Delete CKey class
* Rename units that are no longer CKey-related
* Delete code that was unused
This commit is contained in:
Josh Juran
2014-11-14 00:34:35 -08:00
committed by Vinnie Falco
parent 9aa040d917
commit b2eeb49a45
15 changed files with 638 additions and 535 deletions

View File

@@ -2274,29 +2274,40 @@
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\DHUtil.h"> <ClInclude Include="..\..\src\ripple\crypto\DHUtil.h">
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\ECDSA.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\ECDSACanonical.h"> <ClInclude Include="..\..\src\ripple\crypto\ECDSACanonical.h">
</ClInclude> </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\Base58Data.cpp"> <ClCompile Include="..\..\src\ripple\crypto\impl\Base58Data.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild> <ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\CBigNum.cpp"> <ClCompile Include="..\..\src\ripple\crypto\impl\CBigNum.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild> <ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\CKey.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\CKeyDeterministic.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\CKeyECIES.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\DHUtil.cpp"> <ClCompile Include="..\..\src\ripple\crypto\impl\DHUtil.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild> <ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\ECDSA.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\ECDSACanonical.cpp"> <ClCompile Include="..\..\src\ripple\crypto\impl\ECDSACanonical.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild> <ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile> </ClCompile>
<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>
<ClCompile Include="..\..\src\ripple\crypto\impl\GenerateDeterministicKey.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\RandomNumbers.cpp"> <ClCompile Include="..\..\src\ripple\crypto\impl\RandomNumbers.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild> <ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile> </ClCompile>
@@ -2309,6 +2320,9 @@
</None> </None>
<ClInclude Include="..\..\src\ripple\crypto\RFC1751.h"> <ClInclude Include="..\..\src\ripple\crypto\RFC1751.h">
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ripple\crypto\tests\CKey.test.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\json\impl\JsonPropertyStream.cpp"> <ClCompile Include="..\..\src\ripple\json\impl\JsonPropertyStream.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild> <ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile> </ClCompile>

View File

@@ -352,6 +352,9 @@
<Filter Include="ripple\crypto\impl"> <Filter Include="ripple\crypto\impl">
<UniqueIdentifier>{8EF07519-1C32-2E82-D707-702EB0157733}</UniqueIdentifier> <UniqueIdentifier>{8EF07519-1C32-2E82-D707-702EB0157733}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="ripple\crypto\tests">
<UniqueIdentifier>{ACAAFBB2-022D-2EAB-80CD-FBE3D9432F17}</UniqueIdentifier>
</Filter>
<Filter Include="ripple\json"> <Filter Include="ripple\json">
<UniqueIdentifier>{BEDCC703-A2C8-FF25-7E1E-3471BD39ED98}</UniqueIdentifier> <UniqueIdentifier>{BEDCC703-A2C8-FF25-7E1E-3471BD39ED98}</UniqueIdentifier>
</Filter> </Filter>
@@ -3249,30 +3252,45 @@
<ClInclude Include="..\..\src\ripple\crypto\DHUtil.h"> <ClInclude Include="..\..\src\ripple\crypto\DHUtil.h">
<Filter>ripple\crypto</Filter> <Filter>ripple\crypto</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\ECDSA.h">
<Filter>ripple\crypto</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\crypto\ECDSACanonical.h"> <ClInclude Include="..\..\src\ripple\crypto\ECDSACanonical.h">
<Filter>ripple\crypto</Filter> <Filter>ripple\crypto</Filter>
</ClInclude> </ClInclude>
<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>
<ClCompile Include="..\..\src\ripple\crypto\impl\Base58Data.cpp"> <ClCompile Include="..\..\src\ripple\crypto\impl\Base58Data.cpp">
<Filter>ripple\crypto\impl</Filter> <Filter>ripple\crypto\impl</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\CBigNum.cpp"> <ClCompile Include="..\..\src\ripple\crypto\impl\CBigNum.cpp">
<Filter>ripple\crypto\impl</Filter> <Filter>ripple\crypto\impl</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\CKey.cpp">
<Filter>ripple\crypto\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\CKeyDeterministic.cpp">
<Filter>ripple\crypto\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\CKeyECIES.cpp">
<Filter>ripple\crypto\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\DHUtil.cpp"> <ClCompile Include="..\..\src\ripple\crypto\impl\DHUtil.cpp">
<Filter>ripple\crypto\impl</Filter> <Filter>ripple\crypto\impl</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\ECDSA.cpp">
<Filter>ripple\crypto\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\ECDSACanonical.cpp"> <ClCompile Include="..\..\src\ripple\crypto\impl\ECDSACanonical.cpp">
<Filter>ripple\crypto\impl</Filter> <Filter>ripple\crypto\impl</Filter>
</ClCompile> </ClCompile>
<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>
<ClCompile Include="..\..\src\ripple\crypto\impl\GenerateDeterministicKey.cpp">
<Filter>ripple\crypto\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\crypto\impl\RandomNumbers.cpp"> <ClCompile Include="..\..\src\ripple\crypto\impl\RandomNumbers.cpp">
<Filter>ripple\crypto\impl</Filter> <Filter>ripple\crypto\impl</Filter>
</ClCompile> </ClCompile>
@@ -3288,6 +3306,9 @@
<ClInclude Include="..\..\src\ripple\crypto\RFC1751.h"> <ClInclude Include="..\..\src\ripple\crypto\RFC1751.h">
<Filter>ripple\crypto</Filter> <Filter>ripple\crypto</Filter>
</ClInclude> </ClInclude>
<ClCompile Include="..\..\src\ripple\crypto\tests\CKey.test.cpp">
<Filter>ripple\crypto\tests</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\json\impl\JsonPropertyStream.cpp"> <ClCompile Include="..\..\src\ripple\json\impl\JsonPropertyStream.cpp">
<Filter>ripple\json\impl</Filter> <Filter>ripple\json\impl</Filter>
</ClCompile> </ClCompile>

View File

@@ -25,9 +25,9 @@
#ifndef RIPPLE_CRYPTO_CKEY_H_INCLUDED #ifndef RIPPLE_CRYPTO_CKEY_H_INCLUDED
#define RIPPLE_CRYPTO_CKEY_H_INCLUDED #define RIPPLE_CRYPTO_CKEY_H_INCLUDED
#include <ripple/protocol/RippleAddress.h> // VFALCO Remove this cyclic dep #include <ripple/crypto/ECDSACanonical.h>
#include <ripple/crypto/GenerateDeterministicKey.h>
#include <ripple/types/base_uint.h> #include <ripple/types/base_uint.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h> #include <openssl/ecdsa.h>
#include <openssl/hmac.h> #include <openssl/hmac.h>
@@ -42,288 +42,12 @@ namespace ripple {
// see www.keylength.com // see www.keylength.com
// script supports up to 75 for single byte push // script supports up to 75 for single byte push
// VFALCO NOTE this is unused
/*
int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
{
int okay = 0;
BN_CTX *ctx = NULL;
EC_POINT *pub_key = NULL;
if (!eckey) return 0;
const EC_GROUP *group = EC_KEY_get0_group(eckey);
if ((ctx = BN_CTX_new()) == NULL)
goto err;
pub_key = EC_POINT_new(group);
if (pub_key == NULL)
goto err;
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
goto err;
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
EC_KEY_set_private_key(eckey, priv_key);
EC_KEY_set_public_key(eckey, pub_key);
okay = 1;
err:
if (pub_key)
EC_POINT_free(pub_key);
if (ctx != NULL)
BN_CTX_free(ctx);
return (okay);
}
*/
class key_error : public std::runtime_error class key_error : public std::runtime_error
{ {
public: public:
explicit key_error (std::string const& str) : std::runtime_error (str) {} explicit key_error (std::string const& str) : std::runtime_error (str) {}
}; };
class CKey
{
protected:
EC_KEY* pkey;
bool fSet;
public:
typedef std::shared_ptr<CKey> pointer;
CKey ()
{
pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
if (pkey == nullptr)
throw key_error ("CKey::CKey() : EC_KEY_new_by_curve_name failed");
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
fSet = false;
}
CKey (const CKey& b)
{
pkey = EC_KEY_dup (b.pkey);
if (pkey == nullptr)
throw key_error ("CKey::CKey(const CKey&) : EC_KEY_dup failed");
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
fSet = b.fSet;
}
CKey& operator= (const CKey& b)
{
if (!EC_KEY_copy (pkey, b.pkey))
throw key_error ("CKey::operator=(const CKey&) : EC_KEY_copy failed");
fSet = b.fSet;
return (*this);
}
~CKey ()
{
EC_KEY_free (pkey);
}
static uint128 PassPhraseToKey (std::string const& passPhrase);
static EC_KEY* GenerateRootDeterministicKey (const uint128& passPhrase);
static EC_KEY* GenerateRootPubKey (BIGNUM* pubGenerator);
static EC_KEY* GeneratePublicDeterministicKey (RippleAddress const& generator, int n);
static EC_KEY* GeneratePrivateDeterministicKey (RippleAddress const& family, const BIGNUM* rootPriv, int n);
static EC_KEY* GeneratePrivateDeterministicKey (RippleAddress const& family, uint256 const& rootPriv, int n);
CKey (const uint128& passPhrase) : fSet (false)
{
pkey = GenerateRootDeterministicKey (passPhrase);
fSet = true;
assert (pkey);
}
CKey (RippleAddress const& generator, int n) : fSet (false)
{
// public deterministic key
pkey = GeneratePublicDeterministicKey (generator, n);
fSet = true;
assert (pkey);
}
CKey (RippleAddress const& base, const BIGNUM* rootPrivKey, int n) : fSet (false)
{
// private deterministic key
pkey = GeneratePrivateDeterministicKey (base, rootPrivKey, n);
fSet = true;
assert (pkey);
}
CKey (uint256 const& privateKey) : pkey (nullptr), fSet (false)
{
// XXX Broken pkey is null.
SetPrivateKeyU (privateKey);
}
#if 0
CKey (RippleAddress const& masterKey, int keyNum, bool isPublic) : pkey (nullptr), fSet (false)
{
if (isPublic)
SetPubSeq (masterKey, keyNum);
else
SetPrivSeq (masterKey, keyNum); // broken, need seed
fSet = true;
}
#endif
bool IsNull () const
{
return !fSet;
}
void MakeNewKey ()
{
if (!EC_KEY_generate_key (pkey))
throw key_error ("CKey::MakeNewKey() : EC_KEY_generate_key failed");
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
fSet = true;
}
// XXX Still used!
BIGNUM* GetSecretBN () const
{
// DEPRECATED
return BN_dup (EC_KEY_get0_private_key (pkey));
}
void GetPrivateKeyU (uint256& privKey)
{
const BIGNUM* bn = EC_KEY_get0_private_key (pkey);
if (bn == nullptr)
throw key_error ("CKey::GetPrivateKeyU: EC_KEY_get0_private_key failed");
privKey.zero ();
BN_bn2bin (bn, privKey.begin () + (privKey.size () - BN_num_bytes (bn)));
}
bool SetPrivateKeyU (uint256 const& key, bool bThrow = false)
{
// XXX Broken if pkey is not set.
BIGNUM* bn = BN_bin2bn (key.begin (), key.size (), nullptr);
bool bSuccess = EC_KEY_set_private_key (pkey, bn);
BN_clear_free (bn);
if (bSuccess)
{
fSet = true;
}
else if (bThrow)
{
throw key_error ("CKey::SetPrivateKeyU: EC_KEY_set_private_key failed");
}
return bSuccess;
}
bool SetPubKey (const void* ptr, size_t len)
{
const unsigned char* pbegin = static_cast<const unsigned char*> (ptr);
if (!o2i_ECPublicKey (&pkey, &pbegin, len))
return false;
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
fSet = true;
return true;
}
bool SetPubKey (Blob const& vchPubKey)
{
return SetPubKey (&vchPubKey[0], vchPubKey.size ());
}
bool SetPubKey (std::string const& pubKey)
{
return SetPubKey (pubKey.data (), pubKey.size ());
}
Blob GetPubKey () const
{
unsigned int nSize = i2o_ECPublicKey (pkey, nullptr);
assert (nSize <= 33);
if (!nSize)
throw key_error ("CKey::GetPubKey() : i2o_ECPublicKey failed");
Blob vchPubKey (33, 0);
unsigned char* pbegin = &vchPubKey[0];
if (i2o_ECPublicKey (pkey, &pbegin) != nSize)
throw key_error ("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
assert (vchPubKey.size () <= 33);
return vchPubKey;
}
bool Sign (uint256 const& hash, Blob& vchSig)
{
unsigned char pchSig[128];
unsigned int nSize = sizeof(pchSig)/sizeof(pchSig[0]) - 1;
if (!ECDSA_sign (0, (unsigned char*)hash.begin (), hash.size (), pchSig, &nSize, pkey))
return false;
size_t len = nSize;
makeCanonicalECDSASig (pchSig, len);
vchSig.resize (len);
memcpy (&vchSig[0], pchSig, len);
return true;
}
bool Verify (uint256 const& hash, const void* sig, size_t sigLen) const
{
// -1 = error, 0 = bad sig, 1 = good
if (ECDSA_verify (0, hash.begin (), hash.size (), (const unsigned char*) sig, sigLen, pkey) != 1)
return false;
return true;
}
bool Verify (uint256 const& hash, Blob const& vchSig) const
{
return Verify (hash, &vchSig[0], vchSig.size ());
}
bool Verify (uint256 const& hash, std::string const& sig) const
{
return Verify (hash, sig.data (), sig.size ());
}
// ECIES functions. These throw on failure
// returns a 32-byte secret unique to these two keys. At least one private key must be known.
void getECIESSecret (CKey& otherKey, uint256& enc_key, uint256& hmac_key);
// encrypt/decrypt functions with integrity checking.
// Note that the other side must somehow know what keys to use
Blob encryptECIES (CKey& otherKey, Blob const& plaintext);
Blob decryptECIES (CKey& otherKey, Blob const& ciphertext);
};
} // ripple } // ripple
#endif #endif

38
src/ripple/crypto/ECDSA.h Normal file
View File

@@ -0,0 +1,38 @@
//------------------------------------------------------------------------------
/*
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_ECDSA_H
#define RIPPLE_ECDSA_H
#include <ripple/crypto/ec_key.h>
#include <ripple/types/base_uint.h>
#include <ripple/types/Blob.h>
namespace ripple {
openssl::ec_key ECDSAPrivateKey (uint256 const& serialized);
openssl::ec_key ECDSAPublicKey (Blob const& serialized);
Blob ECDSASign (uint256 const& hash, const openssl::ec_key& key);
bool ECDSAVerify (uint256 const& hash, Blob const& sig, const openssl::ec_key& key);
} // ripple
#endif

37
src/ripple/crypto/ECIES.h Normal file
View File

@@ -0,0 +1,37 @@
//------------------------------------------------------------------------------
/*
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_ECIES_H
#define RIPPLE_ECIES_H
#include <ripple/crypto/ec_key.h>
#include <ripple/types/Blob.h>
namespace ripple {
// ECIES functions. These throw on failure
// 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);
} // ripple
#endif

View File

@@ -0,0 +1,40 @@
//------------------------------------------------------------------------------
/*
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_CKEYDETERMINISTIC_H
#define RIPPLE_CKEYDETERMINISTIC_H
#include <ripple/crypto/ec_key.h>
#include <ripple/types/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);
} // ripple
#endif

View File

@@ -0,0 +1,82 @@
//------------------------------------------------------------------------------
/*
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_ECKEY_H
#define RIPPLE_ECKEY_H
#include <ripple/types/base_uint.h>
namespace ripple {
namespace openssl {
class ec_key
{
public:
typedef struct opaque_EC_KEY* pointer_t;
private:
pointer_t ptr;
void destroy();
ec_key (pointer_t raw) : ptr(raw)
{
}
public:
static const ec_key invalid;
static ec_key acquire (pointer_t raw) { return ec_key (raw); }
//ec_key() : ptr() {}
ec_key (const ec_key&);
ec_key& operator= (const ec_key&) = delete;
~ec_key()
{
destroy();
}
pointer_t get() const { return ptr; }
pointer_t release()
{
pointer_t released = ptr;
ptr = nullptr;
return released;
}
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;
uint8_t get_public_key (uint8* buffer) const;
};
} // openssl
} // ripple
#endif

View File

@@ -0,0 +1,124 @@
//------------------------------------------------------------------------------
/*
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/crypto/ECDSA.h>
#include <ripple/crypto/ECDSACanonical.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.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)
{
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();
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)
{
Blob result;
unsigned char sig[128];
unsigned int siglen = sizeof sig - 1;
const unsigned char* p = hash.begin();
if (ECDSA_sign (0, p, hash.size(), sig, &siglen, (EC_KEY*) key.get()))
{
size_t newlen = siglen;
makeCanonicalECDSASig (sig, newlen);
result.resize (newlen);
memcpy (&result[0], sig, newlen);
}
return result;
}
static bool ECDSAVerify (uint256 const& hash, uint8 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)
{
return ECDSAVerify (hash, sig.data(), sig.size(), (EC_KEY*) key.get());
}
} // ripple

View File

@@ -18,8 +18,10 @@
//============================================================================== //==============================================================================
#include <ripple/crypto/CKey.h> #include <ripple/crypto/CKey.h>
#include <ripple/crypto/ECIES.h>
#include <ripple/crypto/RandomNumbers.h> #include <ripple/crypto/RandomNumbers.h>
#include <openssl/ec.h> #include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/pem.h> #include <openssl/pem.h>
namespace ripple { namespace ripple {
@@ -63,25 +65,20 @@ namespace ripple {
#define ECIES_HMAC_TYPE uint256 // Type used to hold HMAC value #define ECIES_HMAC_TYPE uint256 // Type used to hold HMAC value
#define ECIES_HMAC_SIZE (256/8) // Size of HMAC value #define ECIES_HMAC_SIZE (256/8) // Size of HMAC value
void CKey::getECIESSecret (CKey& otherKey, ECIES_ENC_KEY_TYPE& enc_key, ECIES_HMAC_KEY_TYPE& hmac_key) // returns a 32-byte secret unique to these two keys. At least one private key must be known.
static void getECIESSecret (const openssl::ec_key& secretKey, const openssl::ec_key& publicKey, ECIES_ENC_KEY_TYPE& enc_key, ECIES_HMAC_KEY_TYPE& hmac_key)
{ {
EC_KEY* privkey = (EC_KEY*) secretKey.get();
EC_KEY* pubkey = (EC_KEY*) publicKey.get();
// Retrieve a secret generated from an EC key pair. At least one private key must be known. // Retrieve a secret generated from an EC key pair. At least one private key must be known.
if (!pkey || !otherKey.pkey) if (privkey == nullptr || pubkey == nullptr)
throw std::runtime_error ("missing key"); throw std::runtime_error ("missing key");
EC_KEY* pubkey, *privkey; if (! EC_KEY_get0_private_key (privkey))
if (EC_KEY_get0_private_key (pkey))
{ {
privkey = pkey; throw std::runtime_error ("not a private key");
pubkey = otherKey.pkey;
} }
else if (EC_KEY_get0_private_key (otherKey.pkey))
{
privkey = otherKey.pkey;
pubkey = pkey;
}
else throw std::runtime_error ("no private key");
unsigned char rawbuf[512]; unsigned char rawbuf[512];
int buflen = ECDH_compute_key (rawbuf, 512, EC_KEY_get0_public_key (pubkey), privkey, nullptr); int buflen = ECDH_compute_key (rawbuf, 512, EC_KEY_get0_public_key (pubkey), privkey, nullptr);
@@ -131,7 +128,7 @@ static ECIES_HMAC_TYPE makeHMAC (const ECIES_HMAC_KEY_TYPE& secret, Blob const&
return ret; return ret;
} }
Blob CKey::encryptECIES (CKey& otherKey, Blob const& plaintext) Blob encryptECIES (const openssl::ec_key& secretKey, const openssl::ec_key& publicKey, Blob const& plaintext)
{ {
ECIES_ENC_IV_TYPE iv; ECIES_ENC_IV_TYPE iv;
@@ -140,7 +137,7 @@ Blob CKey::encryptECIES (CKey& otherKey, Blob const& plaintext)
ECIES_ENC_KEY_TYPE secret; ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey; ECIES_HMAC_KEY_TYPE hmacKey;
getECIESSecret (otherKey, secret, hmacKey); getECIESSecret (secretKey, publicKey, secret, hmacKey);
ECIES_HMAC_TYPE hmac = makeHMAC (hmacKey, plaintext); ECIES_HMAC_TYPE hmac = makeHMAC (hmacKey, plaintext);
hmacKey.zero (); hmacKey.zero ();
@@ -206,7 +203,7 @@ Blob CKey::encryptECIES (CKey& otherKey, Blob const& plaintext)
return out; return out;
} }
Blob CKey::decryptECIES (CKey& otherKey, Blob const& ciphertext) Blob decryptECIES (const openssl::ec_key& secretKey, const openssl::ec_key& publicKey, Blob const& ciphertext)
{ {
// minimum ciphertext = IV + HMAC + 1 block // minimum ciphertext = IV + HMAC + 1 block
if (ciphertext.size () < ((2 * ECIES_ENC_BLK_SIZE) + ECIES_HMAC_SIZE) ) if (ciphertext.size () < ((2 * ECIES_ENC_BLK_SIZE) + ECIES_HMAC_SIZE) )
@@ -222,7 +219,7 @@ Blob CKey::decryptECIES (CKey& otherKey, Blob const& ciphertext)
ECIES_ENC_KEY_TYPE secret; ECIES_ENC_KEY_TYPE secret;
ECIES_HMAC_KEY_TYPE hmacKey; ECIES_HMAC_KEY_TYPE hmacKey;
getECIESSecret (otherKey, secret, hmacKey); getECIESSecret (secretKey, publicKey, secret, hmacKey);
if (EVP_DecryptInit_ex (&ctx, ECIES_ENC_ALGO, nullptr, secret.begin (), iv.begin ()) != 1) if (EVP_DecryptInit_ex (&ctx, ECIES_ENC_ALGO, nullptr, secret.begin (), iv.begin ()) != 1)
{ {
@@ -288,46 +285,4 @@ Blob CKey::decryptECIES (CKey& otherKey, Blob const& ciphertext)
return plaintext; return plaintext;
} }
bool checkECIES (void)
{
CKey senderPriv, recipientPriv, senderPub, recipientPub;
for (int i = 0; i < 30000; ++i)
{
if ((i % 100) == 0)
{
// generate new keys every 100 times
senderPriv.MakeNewKey ();
recipientPriv.MakeNewKey ();
if (!senderPub.SetPubKey (senderPriv.GetPubKey ()))
throw std::runtime_error ("key error");
if (!recipientPub.SetPubKey (recipientPriv.GetPubKey ()))
throw std::runtime_error ("key error");
}
// generate message
Blob message (4096);
int msglen = i % 3000;
RandomNumbers::getInstance ().fillBytes (&message.front (), msglen);
message.resize (msglen);
// encrypt message with sender's private key and recipient's public key
Blob ciphertext = senderPriv.encryptECIES (recipientPub, message);
// decrypt message with recipient's private key and sender's public key
Blob decrypt = recipientPriv.decryptECIES (senderPub, ciphertext);
if (decrypt != message)
{
assert (false);
return false;
}
}
return true;
}
} // ripple } // ripple

View File

@@ -17,47 +17,34 @@
*/ */
//============================================================================== //==============================================================================
#include <ripple/crypto/GenerateDeterministicKey.h>
#include <ripple/crypto/CBigNum.h> #include <ripple/crypto/CBigNum.h>
#include <ripple/crypto/CKey.h>
#include <ripple/protocol/Serializer.h> #include <ripple/protocol/Serializer.h>
#include <string> #include <string>
namespace ripple { namespace ripple {
using openssl::ec_key;
// #define EC_DEBUG // #define EC_DEBUG
// Functions to add CKey support for deterministic EC keys // Functions to add support for deterministic EC keys
// <-- seed
uint128 CKey::PassPhraseToKey (std::string const& passPhrase)
{
// VFALCO NOTE This is a bad dependency, CKey shouldn't need it
Serializer s;
s.addRaw (passPhrase);
// NIKB TODO this caling sequence is a bit ugly; this should be improved.
uint256 hash256 = s.getSHA512Half ();
uint128 ret (uint128::fromVoid (hash256.data()));
s.secureErase ();
return ret;
}
// --> seed // --> seed
// <-- private root generator + public root generator // <-- private root generator + public root generator
EC_KEY* CKey::GenerateRootDeterministicKey (uint128 const& seed) ec_key GenerateRootDeterministicKey (uint128 const& seed)
{ {
BN_CTX* ctx = BN_CTX_new (); BN_CTX* ctx = BN_CTX_new ();
if (!ctx) return nullptr; if (!ctx) return ec_key::invalid;
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1); EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
if (!pkey) if (!pkey)
{ {
BN_CTX_free (ctx); BN_CTX_free (ctx);
return nullptr; return ec_key::invalid;
} }
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED); EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
@@ -68,7 +55,7 @@ EC_KEY* CKey::GenerateRootDeterministicKey (uint128 const& seed)
{ {
BN_CTX_free (ctx); BN_CTX_free (ctx);
EC_KEY_free (pkey); EC_KEY_free (pkey);
return nullptr; return ec_key::invalid;
} }
if (!EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx)) if (!EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
@@ -77,7 +64,7 @@ EC_KEY* CKey::GenerateRootDeterministicKey (uint128 const& seed)
BN_free (order); BN_free (order);
EC_KEY_free (pkey); EC_KEY_free (pkey);
BN_CTX_free (ctx); BN_CTX_free (ctx);
return nullptr; return ec_key::invalid;
} }
BIGNUM* privKey = nullptr; BIGNUM* privKey = nullptr;
@@ -98,7 +85,7 @@ EC_KEY* CKey::GenerateRootDeterministicKey (uint128 const& seed)
EC_KEY_free (pkey); EC_KEY_free (pkey);
BN_free (order); BN_free (order);
BN_CTX_free (ctx); BN_CTX_free (ctx);
return nullptr; return ec_key::invalid;
} }
root.zero (); root.zero ();
@@ -114,7 +101,7 @@ EC_KEY* CKey::GenerateRootDeterministicKey (uint128 const& seed)
EC_KEY_free (pkey); EC_KEY_free (pkey);
BN_clear_free (privKey); BN_clear_free (privKey);
BN_CTX_free (ctx); BN_CTX_free (ctx);
return nullptr; return ec_key::invalid;
} }
EC_POINT* pubKey = EC_POINT_new (EC_KEY_get0_group (pkey)); EC_POINT* pubKey = EC_POINT_new (EC_KEY_get0_group (pkey));
@@ -127,7 +114,7 @@ EC_KEY* CKey::GenerateRootDeterministicKey (uint128 const& seed)
EC_POINT_free (pubKey); EC_POINT_free (pubKey);
EC_KEY_free (pkey); EC_KEY_free (pkey);
BN_CTX_free (ctx); BN_CTX_free (ctx);
return nullptr; return ec_key::invalid;
} }
BN_clear_free (privKey); BN_clear_free (privKey);
@@ -138,7 +125,7 @@ EC_KEY* CKey::GenerateRootDeterministicKey (uint128 const& seed)
EC_POINT_free (pubKey); EC_POINT_free (pubKey);
EC_KEY_free (pkey); EC_KEY_free (pkey);
BN_CTX_free (ctx); BN_CTX_free (ctx);
return nullptr; return ec_key::invalid;
} }
EC_POINT_free (pubKey); EC_POINT_free (pubKey);
@@ -148,13 +135,13 @@ EC_KEY* CKey::GenerateRootDeterministicKey (uint128 const& seed)
#ifdef EC_DEBUG #ifdef EC_DEBUG
assert (EC_KEY_check_key (pkey) == 1); // CAUTION: This check is *very* expensive assert (EC_KEY_check_key (pkey) == 1); // CAUTION: This check is *very* expensive
#endif #endif
return pkey; return ec_key::acquire ((ec_key::pointer_t) pkey);
} }
// Take ripple address. // Take ripple address.
// --> root public generator (consumes) // --> root public generator (consumes)
// <-- root public generator in EC format // <-- root public generator in EC format
EC_KEY* CKey::GenerateRootPubKey (BIGNUM* pubGenerator) static EC_KEY* GenerateRootPubKey (BIGNUM* pubGenerator)
{ {
if (pubGenerator == nullptr) if (pubGenerator == nullptr)
{ {
@@ -196,7 +183,7 @@ EC_KEY* CKey::GenerateRootPubKey (BIGNUM* pubGenerator)
} }
// --> public generator // --> public generator
static BIGNUM* makeHash (RippleAddress const& pubGen, int seq, BIGNUM const* order) static BIGNUM* makeHash (Blob const& pubGen, int seq, BIGNUM const* order)
{ {
int subSeq = 0; int subSeq = 0;
BIGNUM* ret = nullptr; BIGNUM* ret = nullptr;
@@ -204,7 +191,7 @@ static BIGNUM* makeHash (RippleAddress const& pubGen, int seq, BIGNUM const* ord
do do
{ {
Serializer s ((33 * 8 + 32 + 32) / 8); Serializer s ((33 * 8 + 32 + 32) / 8);
s.addRaw (pubGen.getGenerator ()); s.addRaw (pubGen);
s.add32 (seq); s.add32 (seq);
s.add32 (subSeq++); s.add32 (subSeq++);
uint256 root = s.getSHA512Half (); uint256 root = s.getSHA512Half ();
@@ -219,18 +206,18 @@ static BIGNUM* makeHash (RippleAddress const& pubGen, int seq, BIGNUM const* ord
} }
// --> public generator // --> public generator
EC_KEY* CKey::GeneratePublicDeterministicKey (RippleAddress const& pubGen, int seq) ec_key GeneratePublicDeterministicKey (Blob const& pubGen, int seq)
{ {
// publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point // publicKey(n) = rootPublicKey EC_POINT_+ Hash(pubHash|seq)*point
BIGNUM* generator = BN_bin2bn ( BIGNUM* generator = BN_bin2bn (
pubGen.getGenerator ().data (), pubGen.data(),
pubGen.getGenerator ().size (), pubGen.size(),
nullptr); nullptr);
if (generator == nullptr) if (generator == nullptr)
return nullptr; return ec_key::invalid;
EC_KEY* rootKey = CKey::GenerateRootPubKey (generator); EC_KEY* rootKey = GenerateRootPubKey (generator);
const EC_POINT* rootPubKey = EC_KEY_get0_public_key (rootKey); const EC_POINT* rootPubKey = EC_KEY_get0_public_key (rootKey);
BN_CTX* ctx = BN_CTX_new (); BN_CTX* ctx = BN_CTX_new ();
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1); EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
@@ -289,29 +276,23 @@ EC_KEY* CKey::GeneratePublicDeterministicKey (RippleAddress const& pubGen, int s
if (pkey && !success) EC_KEY_free (pkey); if (pkey && !success) EC_KEY_free (pkey);
return success ? pkey : nullptr; return success ? ec_key::acquire ((ec_key::pointer_t) pkey) : ec_key::invalid;
}
EC_KEY* CKey::GeneratePrivateDeterministicKey (RippleAddress const& pubGen, uint256 const& u, int seq)
{
CBigNum bn (u);
return GeneratePrivateDeterministicKey (pubGen, static_cast<BIGNUM*> (&bn), seq);
} }
// --> root private key // --> root private key
EC_KEY* CKey::GeneratePrivateDeterministicKey (RippleAddress const& pubGen, const BIGNUM* rootPrivKey, int seq) ec_key GeneratePrivateDeterministicKey (Blob const& pubGen, const BIGNUM* rootPrivKey, int seq)
{ {
// privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order // privateKey(n) = (rootPrivateKey + Hash(pubHash|seq)) % order
BN_CTX* ctx = BN_CTX_new (); BN_CTX* ctx = BN_CTX_new ();
if (ctx == nullptr) return nullptr; if (ctx == nullptr) return ec_key::invalid;
EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1); EC_KEY* pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
if (pkey == nullptr) if (pkey == nullptr)
{ {
BN_CTX_free (ctx); BN_CTX_free (ctx);
return nullptr; return ec_key::invalid;
} }
EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED); EC_KEY_set_conv_form (pkey, POINT_CONVERSION_COMPRESSED);
@@ -322,7 +303,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey (RippleAddress const& pubGen, cons
{ {
BN_CTX_free (ctx); BN_CTX_free (ctx);
EC_KEY_free (pkey); EC_KEY_free (pkey);
return nullptr; return ec_key::invalid;
} }
if (!EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx)) if (!EC_GROUP_get_order (EC_KEY_get0_group (pkey), order, ctx))
@@ -330,7 +311,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey (RippleAddress const& pubGen, cons
BN_free (order); BN_free (order);
BN_CTX_free (ctx); BN_CTX_free (ctx);
EC_KEY_free (pkey); EC_KEY_free (pkey);
return nullptr; return ec_key::invalid;
} }
// calculate the private additional key // calculate the private additional key
@@ -341,7 +322,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey (RippleAddress const& pubGen, cons
BN_free (order); BN_free (order);
BN_CTX_free (ctx); BN_CTX_free (ctx);
EC_KEY_free (pkey); EC_KEY_free (pkey);
return nullptr; return ec_key::invalid;
} }
// calculate the final private key // calculate the final private key
@@ -357,7 +338,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey (RippleAddress const& pubGen, cons
BN_clear_free (privKey); BN_clear_free (privKey);
BN_CTX_free (ctx); BN_CTX_free (ctx);
EC_KEY_free (pkey); EC_KEY_free (pkey);
return nullptr; return ec_key::invalid;
} }
if (EC_POINT_mul (EC_KEY_get0_group (pkey), pubKey, privKey, nullptr, nullptr, ctx) == 0) if (EC_POINT_mul (EC_KEY_get0_group (pkey), pubKey, privKey, nullptr, nullptr, ctx) == 0)
@@ -366,7 +347,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey (RippleAddress const& pubGen, cons
EC_POINT_free (pubKey); EC_POINT_free (pubKey);
EC_KEY_free (pkey); EC_KEY_free (pkey);
BN_CTX_free (ctx); BN_CTX_free (ctx);
return nullptr; return ec_key::invalid;
} }
BN_clear_free (privKey); BN_clear_free (privKey);
@@ -375,7 +356,7 @@ EC_KEY* CKey::GeneratePrivateDeterministicKey (RippleAddress const& pubGen, cons
EC_POINT_free (pubKey); EC_POINT_free (pubKey);
BN_CTX_free (ctx); BN_CTX_free (ctx);
return pkey; return ec_key::acquire ((ec_key::pointer_t) pkey);
} }
} // ripple } // ripple

View File

@@ -0,0 +1,114 @@
//------------------------------------------------------------------------------
/*
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/crypto/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();
}
const ec_key ec_key::invalid = ec_key::acquire (nullptr);
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;
}
}
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;
}
uint8_t ec_key::get_public_key (uint8* buffer) const
{
uint8_t* begin = buffer;
int const size = i2o_ECPublicKey (get_EC_KEY (*this), &begin);
assert (size == get_public_key_size());
return uint8_t (size);
}
} // openssl
} // ripple

View File

@@ -17,7 +17,8 @@
*/ */
//============================================================================== //==============================================================================
#include <ripple/crypto/CKey.h> #include <ripple/crypto/GenerateDeterministicKey.h>
#include <ripple/protocol/RippleAddress.h>
#include <ripple/types/base_uint.h> #include <ripple/types/base_uint.h>
#include <beast/unit_test/suite.h> #include <beast/unit_test/suite.h>
@@ -29,8 +30,6 @@ namespace ripple {
// file license.txt or http://www.opensource.org/licenses/mit-license.php. // file license.txt or http://www.opensource.org/licenses/mit-license.php.
// VFALCO TODO move inlined stuff from CKey into here
class CKey_test : public beast::unit_test::suite class CKey_test : public beast::unit_test::suite
{ {
public: public:
@@ -40,11 +39,12 @@ public:
uint128 seed1, seed2; uint128 seed1, seed2;
seed1.SetHex ("71ED064155FFADFA38782C5E0158CB26"); seed1.SetHex ("71ED064155FFADFA38782C5E0158CB26");
seed2.SetHex ("CF0C3BE4485961858C4198515AE5B965"); seed2.SetHex ("CF0C3BE4485961858C4198515AE5B965");
CKey root1 (seed1), root2 (seed2);
uint256 priv1, priv2; openssl::ec_key root1 = GenerateRootDeterministicKey (seed1);
root1.GetPrivateKeyU (priv1); openssl::ec_key root2 = GenerateRootDeterministicKey (seed2);
root2.GetPrivateKeyU (priv2);
uint256 const priv1 = root1.get_private_key();
uint256 const priv2 = root2.get_private_key();
unexpected (to_string (priv1) != "7CFBA64F771E93E817E15039215430B53F7401C34931D111EAB3510B22DBB0D8", unexpected (to_string (priv1) != "7CFBA64F771E93E817E15039215430B53F7401C34931D111EAB3510B22DBB0D8",
"Incorrect private key for generator"); "Incorrect private key for generator");

View File

@@ -67,8 +67,6 @@ public:
void clear (); void clear ();
bool isSet () const; bool isSet () const;
std::string humanAddressType () const;
// //
// Node Public - Also used for Validators // Node Public - Also used for Validators
// //

View File

@@ -20,6 +20,8 @@
#include <ripple/basics/Log.h> #include <ripple/basics/Log.h>
#include <ripple/basics/StringUtilities.h> #include <ripple/basics/StringUtilities.h>
#include <ripple/crypto/CKey.h> #include <ripple/crypto/CKey.h>
#include <ripple/crypto/ECDSA.h>
#include <ripple/crypto/ECIES.h>
#include <ripple/crypto/RandomNumbers.h> #include <ripple/crypto/RandomNumbers.h>
#include <ripple/crypto/RFC1751.h> #include <ripple/crypto/RFC1751.h>
#include <ripple/protocol/RippleAddress.h> #include <ripple/protocol/RippleAddress.h>
@@ -32,6 +34,48 @@
namespace ripple { 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)
{
Serializer s;
s.addRaw (passPhrase);
// NIKB TODO this caling sequence is a bit ugly; this should be improved.
uint256 hash256 = s.getSHA512Half ();
uint128 ret (uint128::fromVoid (hash256.data()));
s.secureErase ();
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))
{
return false;
}
openssl::ec_key key = ECDSAPublicKey (pubkey);
return key.valid() && ECDSAVerify (hash, sig, key);
}
RippleAddress::RippleAddress () RippleAddress::RippleAddress ()
: mIsValid (false) : mIsValid (false)
{ {
@@ -50,43 +94,11 @@ bool RippleAddress::isSet () const
return nVersion != VER_NONE; return nVersion != VER_NONE;
} }
std::string RippleAddress::humanAddressType () const
{
switch (nVersion)
{
case VER_NONE:
return "VER_NONE";
case VER_NODE_PUBLIC:
return "VER_NODE_PUBLIC";
case VER_NODE_PRIVATE:
return "VER_NODE_PRIVATE";
case VER_ACCOUNT_ID:
return "VER_ACCOUNT_ID";
case VER_ACCOUNT_PUBLIC:
return "VER_ACCOUNT_PUBLIC";
case VER_ACCOUNT_PRIVATE:
return "VER_ACCOUNT_PRIVATE";
case VER_FAMILY_GENERATOR:
return "VER_FAMILY_GENERATOR";
case VER_FAMILY_SEED:
return "VER_FAMILY_SEED";
}
return "unknown";
}
// //
// NodePublic // NodePublic
// //
uint160 Hash160 (Blob const& vch) static uint160 Hash160 (Blob const& vch)
{ {
uint256 hash1; uint256 hash1;
SHA256 (vch.data (), vch.size (), hash1.data ()); SHA256 (vch.data (), vch.size (), hash1.data ());
@@ -99,11 +111,10 @@ uint160 Hash160 (Blob const& vch)
RippleAddress RippleAddress::createNodePublic (RippleAddress const& naSeed) RippleAddress RippleAddress::createNodePublic (RippleAddress const& naSeed)
{ {
CKey ckSeed (naSeed.getSeed ());
RippleAddress naNew; RippleAddress naNew;
// YYY Should there be a GetPubKey() equiv that returns a uint256? // YYY Should there be a GetPubKey() equiv that returns a uint256?
naNew.setNodePublic (ckSeed.GetPubKey ()); naNew.setNodePublic (getPublicKey (GenerateRootDeterministicKey (naSeed.getSeed())));
return naNew; return naNew;
} }
@@ -191,22 +202,7 @@ void RippleAddress::setNodePublic (Blob const& vPublic)
bool RippleAddress::verifyNodePublic (uint256 const& hash, Blob const& vchSig, ECDSA fullyCanonical) const bool RippleAddress::verifyNodePublic (uint256 const& hash, Blob const& vchSig, ECDSA fullyCanonical) const
{ {
CKey pubkey = CKey (); return verifySignature (getNodePublic(), hash, vchSig, fullyCanonical);
bool bVerified;
bVerified = isCanonicalECDSASig (vchSig, fullyCanonical);
if (bVerified && !pubkey.SetPubKey (getNodePublic ()))
{
// Failed to set public key.
bVerified = false;
}
else
{
bVerified = pubkey.Verify (hash, vchSig);
}
return bVerified;
} }
bool RippleAddress::verifyNodePublic (uint256 const& hash, std::string const& strSig, ECDSA fullyCanonical) const bool RippleAddress::verifyNodePublic (uint256 const& hash, std::string const& strSig, ECDSA fullyCanonical) const
@@ -222,13 +218,9 @@ bool RippleAddress::verifyNodePublic (uint256 const& hash, std::string const& st
RippleAddress RippleAddress::createNodePrivate (RippleAddress const& naSeed) RippleAddress RippleAddress::createNodePrivate (RippleAddress const& naSeed)
{ {
uint256 uPrivKey;
RippleAddress naNew; RippleAddress naNew;
CKey ckSeed (naSeed.getSeed ());
ckSeed.GetPrivateKeyU (uPrivKey); naNew.setNodePrivate (GenerateRootDeterministicKey (naSeed.getSeed()).get_private_key());
naNew.setNodePrivate (uPrivKey);
return naNew; return naNew;
} }
@@ -301,11 +293,11 @@ void RippleAddress::setNodePrivate (uint256 hash256)
void RippleAddress::signNodePrivate (uint256 const& hash, Blob& vchSig) const void RippleAddress::signNodePrivate (uint256 const& hash, Blob& vchSig) const
{ {
CKey ckPrivKey; openssl::ec_key key = ECDSAPrivateKey (getNodePrivate());
vchSig = ECDSASign (hash, key);
ckPrivKey.SetPrivateKeyU (getNodePrivate ()); if (vchSig.empty())
if (!ckPrivKey.Sign (hash, vchSig))
throw std::runtime_error ("Signing failed."); throw std::runtime_error ("Signing failed.");
} }
@@ -412,10 +404,9 @@ void RippleAddress::setAccountID (Account const& hash160)
RippleAddress RippleAddress::createAccountPublic ( RippleAddress RippleAddress::createAccountPublic (
RippleAddress const& generator, int iSeq) RippleAddress const& generator, int iSeq)
{ {
CKey ckPub (generator, iSeq);
RippleAddress naNew; RippleAddress naNew;
naNew.setAccountPublic (ckPub.GetPubKey ()); naNew.setAccountPublic (getPublicKey (GeneratePublicDeterministicKey (generator.getGenerator(), iSeq)));
return naNew; return naNew;
} }
@@ -473,31 +464,13 @@ void RippleAddress::setAccountPublic (Blob const& vPublic)
void RippleAddress::setAccountPublic (RippleAddress const& generator, int seq) void RippleAddress::setAccountPublic (RippleAddress const& generator, int seq)
{ {
CKey pubkey = CKey (generator, seq); setAccountPublic (getPublicKey (GeneratePublicDeterministicKey (generator.getGenerator(), seq)));
setAccountPublic (pubkey.GetPubKey ());
} }
bool RippleAddress::accountPublicVerify ( bool RippleAddress::accountPublicVerify (
uint256 const& uHash, Blob const& vucSig, ECDSA fullyCanonical) const uint256 const& uHash, Blob const& vucSig, ECDSA fullyCanonical) const
{ {
CKey ckPublic; return verifySignature (getAccountPublic(), uHash, vucSig, fullyCanonical);
bool bVerified = isCanonicalECDSASig (vucSig, fullyCanonical);
if (bVerified && !ckPublic.SetPubKey (getAccountPublic ()))
{
// Bad private key.
WriteLog (lsWARNING, RippleAddress)
<< "accountPublicVerify: Bad private key.";
bVerified = false;
}
else
{
bVerified = ckPublic.Verify (uHash, vucSig);
}
return bVerified;
} }
RippleAddress RippleAddress::createAccountID (Account const& account) RippleAddress RippleAddress::createAccountID (Account const& account)
@@ -575,59 +548,58 @@ void RippleAddress::setAccountPrivate (uint256 hash256)
void RippleAddress::setAccountPrivate ( void RippleAddress::setAccountPrivate (
RippleAddress const& generator, RippleAddress const& naSeed, int seq) RippleAddress const& generator, RippleAddress const& naSeed, int seq)
{ {
CKey ckPubkey = CKey (naSeed.getSeed ()); openssl::ec_key publicKey = GenerateRootDeterministicKey (naSeed.getSeed());
CKey ckPrivkey = CKey (generator, ckPubkey.GetSecretBN (), seq); openssl::ec_key secretKey = GeneratePrivateDeterministicKey (generator.getGenerator(), GetSecretBN (publicKey), seq);
uint256 uPrivKey;
setAccountPrivate (secretKey.get_private_key());
ckPrivkey.GetPrivateKeyU (uPrivKey);
setAccountPrivate (uPrivKey);
} }
bool RippleAddress::accountPrivateSign (uint256 const& uHash, Blob& vucSig) const bool RippleAddress::accountPrivateSign (uint256 const& uHash, Blob& vucSig) const
{ {
CKey ckPrivate; openssl::ec_key key = ECDSAPrivateKey (getAccountPrivate());
bool bResult;
if (!key.valid())
if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
{ {
// Bad private key. // Bad private key.
WriteLog (lsWARNING, RippleAddress) WriteLog (lsWARNING, RippleAddress)
<< "accountPrivateSign: Bad private key."; << "accountPrivateSign: Bad private key.";
bResult = false;
} return false;
else
{
bResult = ckPrivate.Sign (uHash, vucSig);
CondLog (!bResult, lsWARNING, RippleAddress)
<< "accountPrivateSign: Signing failed.";
} }
vucSig = ECDSASign (uHash, key);
const bool ok = !vucSig.empty();
CondLog (!ok, lsWARNING, RippleAddress)
<< "accountPrivateSign: Signing failed.";
return bResult; return ok;
} }
Blob RippleAddress::accountPrivateEncrypt ( Blob RippleAddress::accountPrivateEncrypt (
RippleAddress const& naPublicTo, Blob const& vucPlainText) const RippleAddress const& naPublicTo, Blob const& vucPlainText) const
{ {
CKey ckPrivate; openssl::ec_key secretKey = ECDSAPrivateKey (getAccountPrivate());
CKey ckPublic; openssl::ec_key publicKey = ECDSAPublicKey (naPublicTo.getAccountPublic());
Blob vucCipherText; Blob vucCipherText;
if (!ckPublic.SetPubKey (naPublicTo.getAccountPublic ())) if (! publicKey.valid())
{ {
WriteLog (lsWARNING, RippleAddress) WriteLog (lsWARNING, RippleAddress)
<< "accountPrivateEncrypt: Bad public key."; << "accountPrivateEncrypt: Bad public key.";
} }
else if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
if (! secretKey.valid())
{ {
WriteLog (lsWARNING, RippleAddress) WriteLog (lsWARNING, RippleAddress)
<< "accountPrivateEncrypt: Bad private key."; << "accountPrivateEncrypt: Bad private key.";
} }
else
{ {
try try
{ {
vucCipherText = ckPrivate.encryptECIES (ckPublic, vucPlainText); vucCipherText = encryptECIES (secretKey, publicKey, vucPlainText);
} }
catch (...) catch (...)
{ {
@@ -640,25 +612,27 @@ Blob RippleAddress::accountPrivateEncrypt (
Blob RippleAddress::accountPrivateDecrypt ( Blob RippleAddress::accountPrivateDecrypt (
RippleAddress const& naPublicFrom, Blob const& vucCipherText) const RippleAddress const& naPublicFrom, Blob const& vucCipherText) const
{ {
CKey ckPrivate; openssl::ec_key secretKey = ECDSAPrivateKey (getAccountPrivate());
CKey ckPublic; openssl::ec_key publicKey = ECDSAPublicKey (naPublicFrom.getAccountPublic());
Blob vucPlainText; Blob vucPlainText;
if (!ckPublic.SetPubKey (naPublicFrom.getAccountPublic ())) if (! publicKey.valid())
{ {
WriteLog (lsWARNING, RippleAddress) WriteLog (lsWARNING, RippleAddress)
<< "accountPrivateDecrypt: Bad public key."; << "accountPrivateDecrypt: Bad public key.";
} }
else if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
if (! secretKey.valid())
{ {
WriteLog (lsWARNING, RippleAddress) WriteLog (lsWARNING, RippleAddress)
<< "accountPrivateDecrypt: Bad private key."; << "accountPrivateDecrypt: Bad private key.";
} }
else
{ {
try try
{ {
vucPlainText = ckPrivate.decryptECIES (ckPublic, vucCipherText); vucPlainText = decryptECIES (secretKey, publicKey, vucCipherText);
} }
catch (...) catch (...)
{ {
@@ -719,9 +693,8 @@ void RippleAddress::setGenerator (Blob const& vPublic)
RippleAddress RippleAddress::createGeneratorPublic (RippleAddress const& naSeed) RippleAddress RippleAddress::createGeneratorPublic (RippleAddress const& naSeed)
{ {
CKey ckSeed (naSeed.getSeed ());
RippleAddress naNew; RippleAddress naNew;
naNew.setGenerator (ckSeed.GetPubKey ()); naNew.setGenerator (getPublicKey (GenerateRootDeterministicKey (naSeed.getSeed())));
return naNew; return naNew;
} }
@@ -839,7 +812,7 @@ bool RippleAddress::setSeedGeneric (std::string const& strText)
} }
else else
{ {
setSeed (CKey::PassPhraseToKey (strText)); setSeed (PassPhraseToKey (strText));
} }
return bResult; return bResult;

View File

@@ -25,10 +25,12 @@
#include <ripple/crypto/impl/Base58Data.cpp> #include <ripple/crypto/impl/Base58Data.cpp>
#include <ripple/crypto/impl/CBigNum.cpp> #include <ripple/crypto/impl/CBigNum.cpp>
#include <ripple/crypto/impl/CKey.cpp>
#include <ripple/crypto/impl/CKeyDeterministic.cpp>
#include <ripple/crypto/impl/CKeyECIES.cpp>
#include <ripple/crypto/impl/DHUtil.cpp> #include <ripple/crypto/impl/DHUtil.cpp>
#include <ripple/crypto/impl/ec_key.cpp>
#include <ripple/crypto/impl/ECDSA.cpp>
#include <ripple/crypto/impl/ECDSACanonical.cpp> #include <ripple/crypto/impl/ECDSACanonical.cpp>
#include <ripple/crypto/impl/ECIES.cpp>
#include <ripple/crypto/impl/GenerateDeterministicKey.cpp>
#include <ripple/crypto/impl/RandomNumbers.cpp> #include <ripple/crypto/impl/RandomNumbers.cpp>
#include <ripple/crypto/impl/RFC1751.cpp> #include <ripple/crypto/impl/RFC1751.cpp>
#include <ripple/crypto/tests/CKey.test.cpp>