diff --git a/CMakeLists.txt b/CMakeLists.txt index e7461eb1c..a5c4fe930 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,8 @@ option(USENPM "Use npm to recompile ethereum.js if it was changed" OFF) option(PROFILING "Build in support for profiling" OFF) set(BUNDLE "none" CACHE STRING "Predefined bundle of software to build (none, full, user, tests, minimal).") -option(MINER "Build the miner component" ON) +option(MINER "Build the CLI miner component" ON) +option(ETHKEY "Build the CLI key manager component" ON) option(SOLIDITY "Build the Solidity language components" ON) option(SERPENT "Build the Serpent language components" ON) option(TOOLS "Build the tools components" ON) diff --git a/libdevcrypto/SecretStore.cpp b/libdevcrypto/SecretStore.cpp index c6f9803fa..11ff98bf6 100644 --- a/libdevcrypto/SecretStore.cpp +++ b/libdevcrypto/SecretStore.cpp @@ -165,12 +165,17 @@ void SecretStore::load(std::string const& _keysPath) h128 SecretStore::readKey(std::string const& _file, bool _deleteFile) { cdebug << "Reading" << _file; - js::mValue u = upgraded(contentsString(_file)); + return readKeyContent(contentsString(_file), _deleteFile ? _file : string()); +} + +h128 SecretStore::readKeyContent(std::string const& _content, std::string const& _file) +{ + js::mValue u = upgraded(_content); if (u.type() == js::obj_type) { js::mObject& o = u.get_obj(); auto uuid = fromUUID(o["id"].get_str()); - m_keys[uuid] = make_pair(js::write_string(o["crypto"], false), _deleteFile ? _file : string()); + m_keys[uuid] = make_pair(js::write_string(o["crypto"], false), _file); return uuid; } else diff --git a/libdevcrypto/SecretStore.h b/libdevcrypto/SecretStore.h index c4e5d5cf7..4474212b1 100644 --- a/libdevcrypto/SecretStore.h +++ b/libdevcrypto/SecretStore.h @@ -43,6 +43,7 @@ public: bytes secret(h128 const& _uuid, std::function const& _pass, bool _useCache = true) const; h128 importKey(std::string const& _file) { auto ret = readKey(_file, false); if (ret) save(); return ret; } + h128 importKeyContent(std::string const& _content) { auto ret = readKeyContent(_content, std::string()); if (ret) save(); return ret; } h128 importSecret(bytes const& _s, std::string const& _pass); bool recode(h128 const& _uuid, std::string const& _newPass, std::function const& _pass, KDF _kdf = KDF::Scrypt); void kill(h128 const& _uuid); @@ -52,16 +53,20 @@ public: // Clear any cached keys. void clearCache() const; + // Doesn't save(). + h128 readKey(std::string const& _file, bool _deleteFile); + h128 readKeyContent(std::string const& _content, std::string const& _file = std::string()); + + void save(std::string const& _keysPath); + void save() { save(m_path); } + static std::string defaultPath() { return getDataDir("web3") + "/keys"; } private: - void save(std::string const& _keysPath); void load(std::string const& _keysPath); - void save() { save(m_path); } void load() { load(m_path); } static std::string encrypt(bytes const& _v, std::string const& _pass, KDF _kdf = KDF::Scrypt); static bytes decrypt(std::string const& _v, std::string const& _pass); - h128 readKey(std::string const& _file, bool _deleteFile); mutable std::unordered_map m_cached; std::unordered_map> m_keys; diff --git a/libscrypt/crypto-scrypt-saltgen.c b/libscrypt/crypto-scrypt-saltgen.c index 998a1abcb..e69de29bb 100644 --- a/libscrypt/crypto-scrypt-saltgen.c +++ b/libscrypt/crypto-scrypt-saltgen.c @@ -1,50 +0,0 @@ -#ifndef _MSC_VER -#include -#include -#include -#include -#include - -#ifndef S_SPLINT_S /* Including this here triggers a known bug in splint */ -//#include -#endif - -#define RNGDEV "/dev/urandom" - -int libscrypt_salt_gen(uint8_t *salt, size_t len) -{ - unsigned char buf[len]; - size_t data_read = 0; - int urandom = open(RNGDEV, O_RDONLY); - - if (urandom < 0) - { - return -1; - } - - while (data_read < len) { - ssize_t result = read(urandom, buf + data_read, len - data_read); - - if (result < 0) - { - if (errno == EINTR || errno == EAGAIN) { - continue; - } - - else { - (void)close(urandom); - return -1; - } - } - - data_read += result; - } - - /* Failures on close() shouldn't occur with O_RDONLY */ - (void)close(urandom); - - memcpy(salt, buf, len); - - return 0; -} -#endif diff --git a/libscrypt/crypto_scrypt-hash.c b/libscrypt/crypto_scrypt-hash.c index 4b41007db..e69de29bb 100644 --- a/libscrypt/crypto_scrypt-hash.c +++ b/libscrypt/crypto_scrypt-hash.c @@ -1,44 +0,0 @@ -#include -#include -#include -#include - -#include "b64.h" -#include "libscrypt.h" - -int libscrypt_hash(char *dst, const char *passphrase, uint32_t N, uint8_t r, - uint8_t p) -{ - - int retval; - uint8_t salt[SCRYPT_SALT_LEN]; - uint8_t hashbuf[SCRYPT_HASH_LEN]; - char outbuf[256]; - char saltbuf[256]; - - if(libscrypt_salt_gen(salt, SCRYPT_SALT_LEN) == -1) - { - return 0; - } - - retval = libscrypt_scrypt((const uint8_t*)passphrase, strlen(passphrase), - (uint8_t*)salt, SCRYPT_SALT_LEN, N, r, p, hashbuf, sizeof(hashbuf)); - if(retval == -1) - return 0; - - retval = libscrypt_b64_encode((unsigned char*)hashbuf, sizeof(hashbuf), - outbuf, sizeof(outbuf)); - if(retval == -1) - return 0; - - retval = libscrypt_b64_encode((unsigned char *)salt, sizeof(salt), - saltbuf, sizeof(saltbuf)); - if(retval == -1) - return 0; - - retval = libscrypt_mcf(N, r, p, saltbuf, outbuf, dst); - if(retval != 1) - return 0; - - return 1; -} diff --git a/libscrypt/libscrypt.h b/libscrypt/libscrypt.h index b7141f5f5..889ba13aa 100644 --- a/libscrypt/libscrypt.h +++ b/libscrypt/libscrypt.h @@ -33,17 +33,6 @@ int libscrypt_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, const char *salt, const char *hash, char *mcf); -#ifndef _MSC_VER -/* Generates a salt. Uses /dev/urandom/ - */ -int libscrypt_salt_gen(/*@out@*/ uint8_t *rand, size_t len); - -/* Creates a hash of a passphrase using a randomly generated salt */ -/* Returns >0 on success, or 0 for fail */ -int libscrypt_hash(char *dst, const char* passphrase, uint32_t N, uint8_t r, - uint8_t p); -#endif - /* Checks a given MCF against a password */ int libscrypt_check(char *mcf, const char *password); diff --git a/test/libdevcrypto/SecretStore.cpp b/test/libdevcrypto/SecretStore.cpp new file mode 100644 index 000000000..1f927db5d --- /dev/null +++ b/test/libdevcrypto/SecretStore.cpp @@ -0,0 +1,64 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file SecretStore.cpp + * @author Gav Wood + * @date 2015 + * Secret store test functions. + */ + +#include +#include +#include +#include "../JsonSpiritHeaders.h" +#include +#include +#include +#include +#include "MemTrie.h" +#include "../TestHelper.h" +using namespace std; +using namespace dev; + +namespace js = json_spirit; + +BOOST_AUTO_TEST_SUITE(KeyStore) + +BOOST_AUTO_TEST_CASE(basic_tests) +{ + string testPath = test::getTestPath(); + + testPath += "/KeyStoreTests"; + + cnote << "Testing Key Store..."; + js::mValue v; + string s = asString(contents(testPath + "/basic_tests.json")); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'KeyStoreTests/basic_tests.json' is empty. Have you cloned the 'tests' repo branch develop?"); + js::read_string(s, v); + for (auto& i: v.get_obj()) + { + cnote << i.first; + js::mObject& o = i.second.get_obj(); + SecretStore store("."); + h128 u = store.readKeyContent(js::write_string(o["json"], false)); + cdebug << "read uuid" << u; + bytes s = store.secret(u, [&](){ return o["password"].get_str(); }); + cdebug << "got secret" << toHex(s); + BOOST_REQUIRE_EQUAL(toHex(s), o["priv"].get_str()); + } +} + +BOOST_AUTO_TEST_SUITE_END()