diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj old mode 100755 new mode 100644 index 04d7bd7c79..0254c344e2 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -1945,8 +1945,6 @@ - - @@ -1967,15 +1965,27 @@ True + + True + + + True True + + True + + True + + + True diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index efdcd71671..6560fd77ca 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -2871,9 +2871,6 @@ ripple\crypto - - ripple\crypto - ripple\crypto @@ -2895,15 +2892,30 @@ ripple\crypto\impl + + ripple\crypto\impl + + + ripple\crypto\impl + ripple\crypto\impl ripple\crypto\impl + + ripple\crypto\impl + ripple\crypto\impl + + ripple\crypto\impl + + + ripple\crypto\impl + ripple\crypto\impl diff --git a/src/ripple/app/paths/Pathfinder.cpp b/src/ripple/app/paths/Pathfinder.cpp index 55495a10e8..7966f079a9 100644 --- a/src/ripple/app/paths/Pathfinder.cpp +++ b/src/ripple/app/paths/Pathfinder.cpp @@ -568,7 +568,7 @@ STPathSet Pathfinder::getBestPaths ( bool useExtraPath = false; if (pathsIterator == mPathRanks.end()) - useExtraPath = true; + useExtraPath = true; else if (extraPathsIterator == extraPathRanks.end()) usePath = true; else if (extraPathsIterator->quality < pathsIterator->quality) diff --git a/src/ripple/crypto/ECDSA.h b/src/ripple/crypto/ECDSA.h index fa0fda349a..76af170416 100644 --- a/src/ripple/crypto/ECDSA.h +++ b/src/ripple/crypto/ECDSA.h @@ -20,18 +20,17 @@ #ifndef RIPPLE_CRYPTO_ECDSA_H_INCLUDED #define RIPPLE_CRYPTO_ECDSA_H_INCLUDED -#include #include #include 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 diff --git a/src/ripple/crypto/ECIES.h b/src/ripple/crypto/ECIES.h index d6f66c725f..5e73657ab1 100644 --- a/src/ripple/crypto/ECIES.h +++ b/src/ripple/crypto/ECIES.h @@ -20,7 +20,7 @@ #ifndef RIPPLE_CRYPTO_ECIES_H_INCLUDED #define RIPPLE_CRYPTO_ECIES_H_INCLUDED -#include +#include #include 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 diff --git a/src/ripple/crypto/GenerateDeterministicKey.h b/src/ripple/crypto/GenerateDeterministicKey.h index 92f4e60762..6070d45bb2 100644 --- a/src/ripple/crypto/GenerateDeterministicKey.h +++ b/src/ripple/crypto/GenerateDeterministicKey.h @@ -25,15 +25,15 @@ #ifndef RIPPLE_CRYPTO_GENERATEDETERMINISTICKEY_H_INCLUDED #define RIPPLE_CRYPTO_GENERATEDETERMINISTICKEY_H_INCLUDED -#include #include -#include 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 diff --git a/src/ripple/crypto/impl/ECDSA.cpp b/src/ripple/crypto/impl/ECDSA.cpp index 2dd02b2b12..671ef044d0 100644 --- a/src/ripple/crypto/impl/ECDSA.cpp +++ b/src/ripple/crypto/impl/ECDSA.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -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 diff --git a/src/ripple/crypto/impl/ECDSAKey.cpp b/src/ripple/crypto/impl/ECDSAKey.cpp new file mode 100644 index 0000000000..96dd06209d --- /dev/null +++ b/src/ripple/crypto/impl/ECDSAKey.cpp @@ -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 +#include +#include +#include + +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 diff --git a/src/ripple/crypto/impl/ECDSAKey.h b/src/ripple/crypto/impl/ECDSAKey.h new file mode 100644 index 0000000000..78b8070261 --- /dev/null +++ b/src/ripple/crypto/impl/ECDSAKey.h @@ -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 +#include +#include + +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 diff --git a/src/ripple/crypto/impl/ECIES.cpp b/src/ripple/crypto/impl/ECIES.cpp index 6b8bb974f5..f5deb444b1 100644 --- a/src/ripple/crypto/impl/ECIES.cpp +++ b/src/ripple/crypto/impl/ECIES.cpp @@ -19,6 +19,8 @@ #include #include +#include +#include #include #include #include @@ -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) ) diff --git a/src/ripple/crypto/impl/GenerateDeterministicKey.cpp b/src/ripple/crypto/impl/GenerateDeterministicKey.cpp index 33d59814c3..8b10f76e99 100644 --- a/src/ripple/crypto/impl/GenerateDeterministicKey.cpp +++ b/src/ripple/crypto/impl/GenerateDeterministicKey.cpp @@ -19,23 +19,38 @@ #include #include -#include -#include +#include +#include #include #include -#include #include #include 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) { uint256 j[2]; - SHA512 (reinterpret_cast(data), bytes, + SHA512 (reinterpret_cast(data), bytes, reinterpret_cast (j)); return j[0]; } @@ -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); + return privKey; +} - 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; - } +// --> seed +// <-- private root generator + public root generator +Blob GenerateRootDeterministicPublicKey (uint128 const& seed) +{ + bn_ctx ctx; - EC_POINT* pubKey = EC_POINT_new (EC_KEY_get0_group (pkey)); + bignum privKey = GenerateRootDeterministicKey (seed); - if (!EC_POINT_mul (EC_KEY_get0_group (pkey), pubKey, privKey, nullptr, nullptr, ctx)) - { - // 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; - } + // compute the corresponding public key point + ec_point pubKey = multiply (secp256k1_group, privKey, ctx); - BN_clear_free (privKey); + privKey.clear(); // security erase - if (!EC_KEY_set_public_key (pkey, pubKey)) - { - assert (false); - EC_POINT_free (pubKey); - EC_KEY_free (pkey); - BN_CTX_free (ctx); - return ec_key::invalid; - } + return serialize_ec_point (pubKey); +} - EC_POINT_free (pubKey); +uint256 GenerateRootDeterministicPrivateKey (uint128 const& seed) +{ + bignum key = GenerateRootDeterministicKey (seed); - 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; - } + // Calculate the corresponding public key. + ec_point newPoint = multiply (secp256k1_group, hash, ctx); - if (success) - { - // Calculate the corresponding public key. - EC_POINT_mul (EC_KEY_get0_group (pkey), newPoint, hash, nullptr, nullptr, ctx); + // Add the master public key and set. + add_to (secp256k1_group, rootPubKey, newPoint, 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); - } - - 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 diff --git a/src/ripple/crypto/impl/ec_key.cpp b/src/ripple/crypto/impl/ec_key.cpp index d903582eca..6b8fc985a0 100644 --- a/src/ripple/crypto/impl/ec_key.cpp +++ b/src/ripple/crypto/impl/ec_key.cpp @@ -23,7 +23,7 @@ // file license.txt or http://www.opensource.org/licenses/mit-license.php. #include -#include +#include #include 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 diff --git a/src/ripple/crypto/ec_key.h b/src/ripple/crypto/impl/ec_key.h similarity index 89% rename from src/ripple/crypto/ec_key.h rename to src/ripple/crypto/impl/ec_key.h index e1f21e1098..2698d4ed62 100644 --- a/src/ripple/crypto/ec_key.h +++ b/src/ripple/crypto/impl/ec_key.h @@ -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 diff --git a/src/ripple/crypto/impl/openssl.cpp b/src/ripple/crypto/impl/openssl.cpp new file mode 100644 index 0000000000..ecb4d46c40 --- /dev/null +++ b/src/ripple/crypto/impl/openssl.cpp @@ -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 +#include + +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 diff --git a/src/ripple/crypto/impl/openssl.h b/src/ripple/crypto/impl/openssl.h new file mode 100644 index 0000000000..f79bd0d2e7 --- /dev/null +++ b/src/ripple/crypto/impl/openssl.h @@ -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 +#include +#include +#include + +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 + 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 diff --git a/src/ripple/crypto/tests/CKey.test.cpp b/src/ripple/crypto/tests/CKey.test.cpp index 877e2cfcd7..20b9455995 100644 --- a/src/ripple/crypto/tests/CKey.test.cpp +++ b/src/ripple/crypto/tests/CKey.test.cpp @@ -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 - diff --git a/src/ripple/protocol/STTx.h b/src/ripple/protocol/STTx.h index df9c9f5b18..995e00c2a0 100644 --- a/src/ripple/protocol/STTx.h +++ b/src/ripple/protocol/STTx.h @@ -52,7 +52,7 @@ public: explicit STTx (SerialIter& sit); explicit STTx (TxType type); - + // Only called from ripple::RPC::transactionSign - can we eliminate this? explicit STTx (STObject const& object); diff --git a/src/ripple/protocol/impl/RippleAddress.cpp b/src/ripple/protocol/impl/RippleAddress.cpp index 393e63a9b1..7109a59f91 100644 --- a/src/ripple/protocol/impl/RippleAddress.cpp +++ b/src/ripple/protocol/impl/RippleAddress.cpp @@ -30,18 +30,11 @@ #include #include #include -#include #include #include 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,25 +50,14 @@ 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)) - { - return false; - } - - openssl::ec_key key = ECDSAPublicKey (pubkey); - - return key.valid() && ECDSAVerify (hash, sig, key); + if (! isCanonicalECDSASig (sig, fullyCanonical)) + { + return false; + } + + 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,30 +551,18 @@ 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); - - setAccountPrivate (secretKey.get_private_key()); + uint256 secretKey = GeneratePrivateDeterministicKey (generator.getGenerator(), naSeed.getSeed(), seq); + + 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) - << "accountPrivateSign: Signing failed."; + + CondLog (!ok, lsWARNING, RippleAddress) + << "accountPrivateSign: Signing failed."; return ok; } @@ -602,22 +570,10 @@ 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()); - - Blob vucCipherText; + uint256 secretKey = getAccountPrivate(); + Blob publicKey = naPublicTo.getAccountPublic(); - if (! publicKey.valid()) - { - WriteLog (lsWARNING, RippleAddress) - << "accountPrivateEncrypt: Bad public key."; - } - - if (! secretKey.valid()) - { - WriteLog (lsWARNING, RippleAddress) - << "accountPrivateEncrypt: Bad private key."; - } + Blob vucCipherText; { try @@ -635,22 +591,10 @@ 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()); - - Blob vucPlainText; + uint256 secretKey = getAccountPrivate(); + Blob publicKey = naPublicFrom.getAccountPublic(); - if (! publicKey.valid()) - { - WriteLog (lsWARNING, RippleAddress) - << "accountPrivateDecrypt: Bad public key."; - } - - if (! secretKey.valid()) - { - WriteLog (lsWARNING, RippleAddress) - << "accountPrivateDecrypt: Bad private key."; - } + Blob vucPlainText; { 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; } diff --git a/src/ripple/unity/crypto.cpp b/src/ripple/unity/crypto.cpp index aaa0e58547..b5eca920e0 100644 --- a/src/ripple/unity/crypto.cpp +++ b/src/ripple/unity/crypto.cpp @@ -26,8 +26,10 @@ #include #include #include +#include #include #include +#include #include #include