Browse Source

ethkey utility with bare key tools.

cl-refactor
Gav Wood 10 years ago
parent
commit
fcb629acda
  1. 19
      CMakeLists.txt
  2. 2
      alethzero/MainWin.h
  3. 3
      alethzero/Transact.cpp
  4. 3
      eth/main.cpp
  5. 33
      ethkey/CMakeLists.txt
  6. 351
      ethkey/KeyAux.h
  7. 84
      ethkey/main.cpp
  8. 4
      ethminer/MinerAux.h
  9. 3
      exp/main.cpp
  10. 9
      libdevcore/CommonData.h
  11. 2
      libdevcrypto/SecretStore.cpp
  12. 14
      libdevcrypto/SecretStore.h
  13. 7
      libethcore/KeyManager.cpp
  14. 8
      libethcore/KeyManager.h
  15. 3
      libweb3jsonrpc/AccountHolder.cpp

19
CMakeLists.txt

@ -251,6 +251,17 @@ elseif (BUNDLE STREQUAL "user")
set(NCURSES ${DECENT_PLATFORM})
set(TOOLS ON)
set(TESTS OFF)
elseif (BUNDLE STREQUAL "wallet")
set(SERPENT OFF)
set(SOLIDITY OFF)
set(USENPM OFF)
set(GUI OFF)
set(NCURSES OFF)
set(TOOLS OFF)
set(TESTS OFF)
set(ETHKEY ON)
set(MINER OFF)
set(ETHASHCL ON)
elseif (BUNDLE STREQUAL "miner")
set(SERPENT OFF)
set(SOLIDITY OFF)
@ -259,6 +270,7 @@ elseif (BUNDLE STREQUAL "miner")
set(NCURSES OFF)
set(TOOLS OFF)
set(TESTS OFF)
set(ETHKEY OFF)
set(MINER ON)
set(ETHASHCL ON)
endif ()
@ -296,6 +308,7 @@ message("-- JSONRPC JSON-RPC support ${JSONRPC}
message("-- USENPM Javascript source building ${USENPM}")
message("------------------------------------------------------------- components")
message("-- MINER Build miner ${MINER}")
message("-- ETHKEY Build wallet tools ${ETHKEY}")
message("-- TOOLS Build basic tools ${TOOLS}")
message("-- SOLIDITY Build Solidity language components ${SOLIDITY}")
message("-- SERPENT Build Serpent language components ${SERPENT}")
@ -387,10 +400,14 @@ if (GENERAL)
add_subdirectory(libwebthree)
endif ()
if (MINER)
if (MINER OR TOOLS)
add_subdirectory(ethminer)
endif ()
if (ETHKEY OR TOOLS)
add_subdirectory(ethkey)
endif ()
if (TESTS)
add_subdirectory(libtestutils)
add_subdirectory(test)

2
alethzero/MainWin.h

@ -33,9 +33,9 @@
#include <QtWidgets/QMainWindow>
#include <libdevcore/RLP.h>
#include <libethcore/Common.h>
#include <libethcore/KeyManager.h>
#include <libethereum/State.h>
#include <libethereum/Executive.h>
#include <libethereum/KeyManager.h>
#include <libwebthree/WebThree.h>
#include <libsolidity/CompilerStack.h>
#include "Context.h"

3
alethzero/Transact.cpp

@ -39,7 +39,8 @@
#include <libnatspec/NatspecExpressionEvaluator.h>
#include <libethereum/Client.h>
#include <libethereum/Utility.h>
#include <libethereum/KeyManager.h>
#include <libethcore/KeyManager.h>
#if ETH_SERPENT
#include <libserpent/funcs.h>
#include <libserpent/util.h>

3
eth/main.cpp

@ -37,7 +37,8 @@
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
#include <libethereum/All.h>
#include <libethereum/KeyManager.h>
#include <libethcore/KeyManager.h>
#include <libwebthree/WebThree.h>
#if ETH_JSCONSOLE || !ETH_TRUE
#include <libjsconsole/JSConsole.h>

33
ethkey/CMakeLists.txt

@ -0,0 +1,33 @@
cmake_policy(SET CMP0015 NEW)
set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
if (JSCONSOLE)
include_directories(${V8_INCLUDE_DIRS})
endif()
set(EXECUTABLE ethkey)
file(GLOB HEADERS "*.h")
add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_dependencies(${EXECUTABLE} BuildInfo.h)
target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} ethcore)
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
eth_copy_dlls("${EXECUTABLE}" MHD_DLLS)
endif()
if (APPLE)
install(TARGETS ${EXECUTABLE} DESTINATION bin)
else()
eth_install_executable(${EXECUTABLE})
endif()

351
ethkey/KeyAux.h

@ -0,0 +1,351 @@
#pragma once
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file KeyAux.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* CLI module for key management.
*/
#include <thread>
#include <chrono>
#include <fstream>
#include <iostream>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/trim_all.hpp>
#include <libdevcore/SHA3.h>
#include <libdevcore/FileSystem.h>
#include <libethcore/KeyManager.h>
#include <libethcore/ICAP.h>
#include "BuildInfo.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace boost::algorithm;
#undef RETURN
class BadArgument: public Exception {};
string getAccountPassword(KeyManager& keyManager, Address const& a)
{
return getPassword("Enter password for address " + keyManager.accountDetails()[a].first + " (" + a.abridged() + "; hint:" + keyManager.accountDetails()[a].second + "): ");
}
string createPassword(std::string const& _prompt)
{
string ret;
while (true)
{
ret = getPassword(_prompt);
string confirm = getPassword("Please confirm the password by entering it again: ");
if (ret == confirm)
break;
cout << "Passwords were different. Try again." << endl;
}
return ret;
// cout << "Enter a hint to help you remember this password: " << flush;
// cin >> hint;
// return make_pair(ret, hint);
}
pair<string, string> createPassword(KeyManager& _keyManager, std::string const& _prompt)
{
string pass;
while (true)
{
pass = getPassword(_prompt);
string confirm = getPassword("Please confirm the password by entering it again: ");
if (pass == confirm)
break;
cout << "Passwords were different. Try again." << endl;
}
string hint;
if (!_keyManager.haveHint(pass))
{
cout << "Enter a hint to help you remember this password: " << flush;
cin >> hint;
}
return make_pair(pass, hint);
}
class KeyCLI
{
public:
enum class OperationMode
{
None,
ListBare,
NewBare,
ImportBare,
ExportBare,
RecodeBare,
FirstWallet,
CreateWallet,
List = FirstWallet,
New,
Import,
Export,
Recode,
Kill
};
KeyCLI(OperationMode _mode = OperationMode::None): m_mode(_mode) {}
bool interpretOption(int& i, int argc, char** argv)
{
string arg = argv[i];
if (arg == "-n" || arg == "--new")
m_mode = OperationMode::New;
else if (arg == "--wallet-path" && i + 1 < argc)
m_walletPath = argv[++i];
else if (arg == "--secrets-path" && i + 1 < argc)
m_secretsPath = argv[++i];
else if ((arg == "-m" || arg == "--master") && i + 1 < argc)
m_masterPassword = argv[++i];
else if (arg == "--unlock" && i + 1 < argc)
m_unlocks.push_back(argv[++i]);
else if (arg == "--lock" && i + 1 < argc)
m_lock = argv[++i];
else if (arg == "--kdf" && i + 1 < argc)
m_kdf = argv[++i];
else if (arg == "--kdf-param" && i + 2 < argc)
{
auto n = argv[++i];
auto v = argv[++i];
m_kdfParams[n] = v;
}
else if (arg == "--new-bare")
m_mode = OperationMode::NewBare;
else if (arg == "--import-bare")
m_mode = OperationMode::ImportBare;
else if (arg == "--list-bare")
m_mode = OperationMode::ListBare;
else if (arg == "--export-bare")
m_mode = OperationMode::ExportBare;
else if (arg == "--recode-bare")
m_mode = OperationMode::RecodeBare;
else if (arg == "--create-wallet")
m_mode = OperationMode::CreateWallet;
else if (arg == "--list")
m_mode = OperationMode::List;
else if ((arg == "-n" || arg == "--new") && i + 1 < argc)
{
m_mode = OperationMode::New;
m_name = argv[++i];
}
else if ((arg == "-i" || arg == "--import") && i + 2 < argc)
{
m_mode = OperationMode::Import;
m_inputs = strings(1, argv[++i]);
m_name = argv[++i];
}
else if (arg == "--export")
m_mode = OperationMode::Export;
else if (arg == "--recode")
m_mode = OperationMode::Recode;
else if (arg == "--no-icap")
m_icap = false;
else if (m_mode == OperationMode::ImportBare || m_mode == OperationMode::Recode || m_mode == OperationMode::Export || m_mode == OperationMode::RecodeBare || m_mode == OperationMode::ExportBare)
m_inputs.push_back(arg);
else
return false;
return true;
}
KeyPair makeKey() const
{
KeyPair k(Secret::random());
while (m_icap && k.address()[0])
k = KeyPair(sha3(k.secret()));
return k;
}
void execute()
{
if (m_mode == OperationMode::CreateWallet)
{
KeyManager wallet(m_walletPath, m_secretsPath);
if (m_masterPassword.empty())
m_masterPassword = createPassword("Please enter a MASTER password to protect your key store (make it strong!): ");
if (m_masterPassword.empty())
cerr << "Aborted (empty password not allowed)." << endl;
else
wallet.create(m_masterPassword);
}
else if (m_mode < OperationMode::FirstWallet)
{
SecretStore store(m_secretsPath);
switch (m_mode)
{
case OperationMode::ListBare:
for (h128 const& u: std::set<h128>() + store.keys())
cout << toUUID(u) << endl;
break;
case OperationMode::NewBare:
{
if (m_lock.empty())
m_lock = createPassword("Enter a password with which to secure this account: ");
auto k = makeKey();
store.importSecret(k.secret().asBytes(), m_lock);
cout << "Created key " << k.address().abridged() << endl;
cout << "Address: " << k.address().hex() << endl;
cout << "ICAP: " << ICAP(k.address()).encoded() << endl;
break;
}
case OperationMode::ImportBare:
for (string const& i: m_inputs)
{
h128 u;
bytes b;
b = fromHex(i);
if (b.size() != 32)
{
std::string s = contentsString(i);
b = fromHex(s);
if (b.size() != 32)
u = store.importKey(i);
}
if (!u && b.size() == 32)
u = store.importSecret(b, lockPassword(toAddress(Secret(b)).abridged()));
else
{
cerr << "Cannot import " << i << " not a file or secret." << endl;
continue;
}
cout << "Successfully imported " << i << " as " << toUUID(u);
}
break;
case OperationMode::ExportBare: break;
case OperationMode::RecodeBare:
for (auto const& i: m_inputs)
{
h128 u = fromUUID(i);
if (u)
if (store.recode(u, lockPassword(toUUID(u)), [&](){ return getPassword("Enter password for key " + toUUID(u) + ": "); }, kdf()))
cerr << "Re-encoded " << toUUID(u) << endl;
else
cerr << "Couldn't re-encode " << toUUID(u) << "; key corrupt or incorrect password supplied." << endl;
else
cerr << "Couldn't re-encode " << toUUID(u) << "; not found." << endl;
}
default: break;
}
}
else
{
KeyManager wallet(m_walletPath, m_secretsPath);
if (wallet.exists())
while (true)
{
if (wallet.load(m_masterPassword))
break;
if (!m_masterPassword.empty())
{
cout << "Password invalid. Try again." << endl;
m_masterPassword.clear();
}
m_masterPassword = getPassword("Please enter your MASTER password: ");
}
else
{
cerr << "Couldn't open wallet. Does it exist?" << endl;
exit(-1);
}
}
}
std::string lockPassword(std::string const& _accountName)
{
return m_lock.empty() ? createPassword("Enter a password with which to secure account " + _accountName + ": ") : m_lock;
}
static void streamHelp(ostream& _out)
{
_out
<< "Secret-store (\"bare\") operation modes:" << endl
<< " --list-bare List all secret available in secret-store." << endl
<< " --new-bare Generate and output a key without interacting with wallet and dump the JSON." << endl
<< " --import-bare [ <file>|<secret-hex> , ... ] Import keys from given sources." << endl
<< " --recode-bare [ <uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl
// << " --export-bare [ <uuid> , ... ] Export given keys." << endl
<< "Secret-store configuration:" << endl
<< " --secrets-path <path> Specify Web3 secret-store path (default: " << SecretStore::defaultPath() << ")" << endl
<< endl
<< "Wallet operating modes:" << endl
<< " -l,--list List all keys available in wallet." << endl
<< " -n,--new <name> Create a new key with given name and add it in the wallet." << endl
<< " -i,--import [<uuid>|<file>|<secret-hex>] <name> Import keys from given source and place in wallet." << endl
<< " -e,--export [ <address>|<uuid> , ... ] Export given keys." << endl
<< " -r,--recode [ <address>|<uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl
<< "Wallet configuration:" << endl
<< " --create-wallet Create an Ethereum master wallet." << endl
<< " --wallet-path <path> Specify Ethereum wallet path (default: " << KeyManager::defaultPath() << ")" << endl
<< " -m, --master <password> Specify wallet (master) password." << endl
<< endl
<< "Encryption configuration:" << endl
<< " --kdf <kdfname> Specify KDF to use when encrypting (default: sc rypt)" << endl
<< " --kdf-param <name> <value> Specify a parameter for the KDF." << endl
// << " --cipher <ciphername> Specify cipher to use when encrypting (default: aes-128-ctr)" << endl
// << " --cipher-param <name> <value> Specify a parameter for the cipher." << endl
<< " --lock <password> <hint> Specify password for when encrypting a (the) key." << endl
<< endl
<< "Decryption configuration:" << endl
<< " --unlock <password> Specify password for a (the) key." << endl
<< "Key generation configuration:" << endl
<< " --no-icap Don't bother to make a direct-ICAP capable key." << endl
;
}
static bool isTrue(std::string const& _m)
{
return _m == "on" || _m == "yes" || _m == "true" || _m == "1";
}
static bool isFalse(std::string const& _m)
{
return _m == "off" || _m == "no" || _m == "false" || _m == "0";
}
private:
KDF kdf() const { return m_kdf == "pbkdf2" ? KDF::PBKDF2_SHA256 : KDF::Scrypt; }
/// Operating mode.
OperationMode m_mode;
/// Wallet stuff
string m_secretsPath = SecretStore::defaultPath();
string m_walletPath = KeyManager::defaultPath();
/// Wallet password stuff
string m_masterPassword;
strings m_unlocks;
string m_lock;
bool m_icap = true;
/// Creating
string m_name;
/// Importing
strings m_inputs;
string m_kdf = "scrypt";
map<string, string> m_kdfParams;
// string m_cipher;
// map<string, string> m_cipherParams;
};

84
ethkey/main.cpp

@ -0,0 +1,84 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* Ethereum client.
*/
#include <thread>
#include <chrono>
#include <fstream>
#include <iostream>
#include <libdevcore/FileSystem.h>
#include <libdevcore/Log.h>
#include <libethcore/KeyManager.h>
#include "BuildInfo.h"
#include "KeyAux.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
void help()
{
cout
<< "Usage ethkey [OPTIONS]" << endl
<< "Options:" << endl << endl;
KeyCLI::streamHelp(cout);
cout
<< "General Options:" << endl
<< " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl
<< " -V,--version Show the version and exit." << endl
<< " -h,--help Show this help message and exit." << endl
;
exit(0);
}
void version()
{
cout << "ethkey version " << dev::Version << endl;
cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl;
exit(0);
}
int main(int argc, char** argv)
{
KeyCLI m(KeyCLI::OperationMode::ListBare);
g_logVerbosity = 0;
for (int i = 1; i < argc; ++i)
{
string arg = argv[i];
if (m.interpretOption(i, argc, argv)) {}
else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc)
g_logVerbosity = atoi(argv[++i]);
else if (arg == "-h" || arg == "--help")
help();
else if (arg == "-V" || arg == "--version")
version();
else
{
cerr << "Invalid argument: " << arg << endl;
exit(-1);
}
}
m.execute();
return 0;
}

4
ethminer/MinerAux.h

@ -16,10 +16,10 @@
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
/** @file MinerAux.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* Ethereum client.
* CLI module for mining.
*/
#include <thread>

3
exp/main.cpp

@ -49,7 +49,8 @@
#include <libethcore/Farm.h>
#include <libdevcore/FileSystem.h>
#include <libethereum/All.h>
#include <libethereum/KeyManager.h>
#include <libethcore/KeyManager.h>
#include <libethereum/AccountDiff.h>
#include <libethereum/DownloadMan.h>
#include <libethereum/Client.h>

9
libdevcore/CommonData.h

@ -323,4 +323,13 @@ std::vector<T> keysOf(std::map<T, U> const& _m)
return ret;
}
template<class T, class U>
std::vector<T> keysOf(std::unordered_map<T, U> const& _m)
{
std::vector<T> ret;
for (auto const& i: _m)
ret.push_back(i.first);
return ret;
}
}

2
libdevcrypto/SecretStore.cpp

@ -84,7 +84,7 @@ static js::mValue upgraded(std::string const& _s)
return js::mValue();
}
SecretStore::SecretStore()
SecretStore::SecretStore(std::string const& _path): m_path(_path)
{
load();
}

14
libdevcrypto/SecretStore.h

@ -38,7 +38,7 @@ enum class KDF {
class SecretStore
{
public:
SecretStore();
SecretStore(std::string const& _path = defaultPath());
~SecretStore();
bytes secret(h128 const& _uuid, std::function<std::string()> const& _pass, bool _useCache = true) const;
@ -47,18 +47,26 @@ public:
bool recode(h128 const& _uuid, std::string const& _newPass, std::function<std::string()> const& _pass, KDF _kdf = KDF::Scrypt);
void kill(h128 const& _uuid);
std::vector<h128> keys() const { return keysOf(m_keys); }
// Clear any cached keys.
void clearCache() const;
static std::string defaultPath() { return getDataDir("web3") + "/keys"; }
private:
void save(std::string const& _keysPath = getDataDir("web3") + "/keys");
void load(std::string const& _keysPath = getDataDir("web3") + "/keys");
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<h128, bytes> m_cached;
std::unordered_map<h128, std::pair<std::string, std::string>> m_keys;
std::string m_path;
};
}

7
libethereum/KeyManager.cpp → libethcore/KeyManager.cpp

@ -31,8 +31,8 @@ using namespace dev;
using namespace eth;
namespace fs = boost::filesystem;
KeyManager::KeyManager(std::string const& _keysFile):
m_keysFile(_keysFile)
KeyManager::KeyManager(std::string const& _keysFile, std::string const& _secretsPath):
m_keysFile(_keysFile), m_store(_secretsPath)
{}
KeyManager::~KeyManager()
@ -96,8 +96,11 @@ bool KeyManager::load(std::string const& _pass)
m_passwordInfo[(h256)i[0]] = (std::string)i[1];
m_password = (string)s[3];
}
cdebug << hashPassword(m_password) << toHex(m_password);
m_cachedPasswords[hashPassword(m_password)] = m_password;
cdebug << hashPassword(asString(m_key.ref())) << m_key.hex();
m_cachedPasswords[hashPassword(asString(m_key.ref()))] = asString(m_key.ref());
cdebug << hashPassword(_pass) << _pass;
m_cachedPasswords[m_master = hashPassword(_pass)] = _pass;
return true;
}

8
libethereum/KeyManager.h → libethcore/KeyManager.h

@ -61,7 +61,7 @@ enum class SemanticPassword
class KeyManager
{
public:
KeyManager(std::string const& _keysFile = getDataDir("ethereum") + "/keys.info");
KeyManager(std::string const& _keysFile = defaultPath(), std::string const& _secretsPath = SecretStore::defaultPath());
~KeyManager();
void setKeysFile(std::string const& _keysFile) { m_keysFile = _keysFile; }
@ -99,6 +99,8 @@ public:
void kill(h128 const& _id) { kill(address(_id)); }
void kill(Address const& _a);
static std::string defaultPath() { return getDataDir("ethereum") + "/keys.info"; }
private:
std::string getPassword(h128 const& _uuid, std::function<std::string()> const& _pass = DontKnowThrow) const;
std::string getPassword(h256 const& _passHash, std::function<std::string()> const& _pass = DontKnowThrow) const;
@ -127,10 +129,10 @@ private:
// we have an upgrade strategy.
std::string m_password;
SecretStore m_store;
mutable std::string m_keysFile;
mutable h128 m_key;
mutable h256 m_master;
mutable std::string m_keysFile;
SecretStore m_store;
};
}

3
libweb3jsonrpc/AccountHolder.cpp

@ -26,7 +26,8 @@
#include <ctime>
#include <libdevcore/Guards.h>
#include <libethereum/Client.h>
#include <libethereum/KeyManager.h>
#include <libethcore/KeyManager.h>
using namespace std;
using namespace dev;

Loading…
Cancel
Save