Paweł Bylica
10 years ago
92 changed files with 3598 additions and 344 deletions
@ -0,0 +1,123 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>GetPassword</class> |
||||
|
<widget class="QDialog" name="GetPassword"> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>400</width> |
||||
|
<height>187</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="windowTitle"> |
||||
|
<string>Enter Password</string> |
||||
|
</property> |
||||
|
<layout class="QVBoxLayout" name="verticalLayout"> |
||||
|
<item> |
||||
|
<spacer name="verticalSpacer_3"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Vertical</enum> |
||||
|
</property> |
||||
|
<property name="sizeHint" stdset="0"> |
||||
|
<size> |
||||
|
<width>20</width> |
||||
|
<height>40</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</spacer> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QLabel" name="label"> |
||||
|
<property name="text"> |
||||
|
<string/> |
||||
|
</property> |
||||
|
<property name="textFormat"> |
||||
|
<enum>Qt::RichText</enum> |
||||
|
</property> |
||||
|
<property name="wordWrap"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<spacer name="verticalSpacer_2"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Vertical</enum> |
||||
|
</property> |
||||
|
<property name="sizeHint" stdset="0"> |
||||
|
<size> |
||||
|
<width>20</width> |
||||
|
<height>40</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</spacer> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QLineEdit" name="entry"> |
||||
|
<property name="echoMode"> |
||||
|
<enum>QLineEdit::Password</enum> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<spacer name="verticalSpacer"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Vertical</enum> |
||||
|
</property> |
||||
|
<property name="sizeHint" stdset="0"> |
||||
|
<size> |
||||
|
<width>20</width> |
||||
|
<height>40</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</spacer> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QDialogButtonBox" name="buttonBox"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Horizontal</enum> |
||||
|
</property> |
||||
|
<property name="standardButtons"> |
||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<resources/> |
||||
|
<connections> |
||||
|
<connection> |
||||
|
<sender>buttonBox</sender> |
||||
|
<signal>accepted()</signal> |
||||
|
<receiver>GetPassword</receiver> |
||||
|
<slot>accept()</slot> |
||||
|
<hints> |
||||
|
<hint type="sourcelabel"> |
||||
|
<x>248</x> |
||||
|
<y>254</y> |
||||
|
</hint> |
||||
|
<hint type="destinationlabel"> |
||||
|
<x>157</x> |
||||
|
<y>274</y> |
||||
|
</hint> |
||||
|
</hints> |
||||
|
</connection> |
||||
|
<connection> |
||||
|
<sender>buttonBox</sender> |
||||
|
<signal>rejected()</signal> |
||||
|
<receiver>GetPassword</receiver> |
||||
|
<slot>reject()</slot> |
||||
|
<hints> |
||||
|
<hint type="sourcelabel"> |
||||
|
<x>316</x> |
||||
|
<y>260</y> |
||||
|
</hint> |
||||
|
<hint type="destinationlabel"> |
||||
|
<x>286</x> |
||||
|
<y>274</y> |
||||
|
</hint> |
||||
|
</hints> |
||||
|
</connection> |
||||
|
</connections> |
||||
|
</ui> |
@ -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() |
@ -0,0 +1,413 @@ |
|||||
|
#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, std::string const& _pass = std::string(), std::string const& _hint = std::string()) |
||||
|
{ |
||||
|
string pass = _pass; |
||||
|
if (pass.empty()) |
||||
|
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 = _hint; |
||||
|
if (hint.empty() && !pass.empty() && !_keyManager.haveHint(pass)) |
||||
|
{ |
||||
|
cout << "Enter a hint to help you remember this password: " << flush; |
||||
|
getline(cin, hint); |
||||
|
} |
||||
|
return make_pair(pass, hint); |
||||
|
} |
||||
|
|
||||
|
class KeyCLI |
||||
|
{ |
||||
|
public: |
||||
|
enum class OperationMode |
||||
|
{ |
||||
|
None, |
||||
|
ListBare, |
||||
|
NewBare, |
||||
|
ImportBare, |
||||
|
ExportBare, |
||||
|
RecodeBare, |
||||
|
KillBare, |
||||
|
CreateWallet, |
||||
|
List, |
||||
|
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 == "--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 == "--kill-bare") |
||||
|
m_mode = OperationMode::KillBare; |
||||
|
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::KillBare || 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::CreateWallet) |
||||
|
{ |
||||
|
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(); |
||||
|
h128 u = store.importSecret(k.secret().asBytes(), m_lock); |
||||
|
cout << "Created key " << toUUID(u) << 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; |
||||
|
} |
||||
|
case OperationMode::KillBare: |
||||
|
for (auto const& i: m_inputs) |
||||
|
{ |
||||
|
h128 u = fromUUID(i); |
||||
|
if (u) |
||||
|
store.kill(u); |
||||
|
else |
||||
|
cerr << "Couldn't kill " << toUUID(u) << "; not found." << endl; |
||||
|
} |
||||
|
break; |
||||
|
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); |
||||
|
} |
||||
|
switch (m_mode) |
||||
|
{ |
||||
|
case OperationMode::New: |
||||
|
{ |
||||
|
tie(m_lock, m_lockHint) = createPassword(wallet, "Enter a password with which to secure this account (or nothing to use the master password): ", m_lock, m_lockHint); |
||||
|
auto k = makeKey(); |
||||
|
bool usesMaster = m_lock.empty(); |
||||
|
h128 u = usesMaster ? wallet.import(k.secret(), m_name) : wallet.import(k.secret(), m_name, m_lock, m_lockHint); |
||||
|
cout << "Created key " << toUUID(u) << endl; |
||||
|
cout << " Name: " << m_name << endl; |
||||
|
if (usesMaster) |
||||
|
cout << " Uses master password." << endl; |
||||
|
else |
||||
|
cout << " Password hint: " << m_lockHint << endl; |
||||
|
cout << " Address: " << k.address().hex() << endl; |
||||
|
cout << " ICAP: " << ICAP(k.address()).encoded() << endl; |
||||
|
break; |
||||
|
} |
||||
|
case OperationMode::List: |
||||
|
{ |
||||
|
vector<u128> bare; |
||||
|
vector<u128> nonIcap; |
||||
|
for (auto const& u: wallet.store().keys()) |
||||
|
if (Address a = wallet.address(u)) |
||||
|
if (a[0]) |
||||
|
nonIcap.push_back(u); |
||||
|
else |
||||
|
{ |
||||
|
std::pair<std::string, std::string> info = wallet.accountDetails()[a]; |
||||
|
cout << toUUID(u) << " " << a.abridged(); |
||||
|
cout << " " << ICAP(a).encoded(); |
||||
|
cout << " " << info.first << endl; |
||||
|
} |
||||
|
else |
||||
|
bare.push_back(u); |
||||
|
for (auto const& u: nonIcap) |
||||
|
if (Address a = wallet.address(u)) |
||||
|
{ |
||||
|
std::pair<std::string, std::string> info = wallet.accountDetails()[a]; |
||||
|
cout << toUUID(u) << " " << a.abridged(); |
||||
|
cout << " (Not ICAP) "; |
||||
|
cout << " " << info.first << endl; |
||||
|
} |
||||
|
for (auto const& u: bare) |
||||
|
cout << toUUID(u) << " (Bare)" << endl; |
||||
|
} |
||||
|
default: break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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
|
||||
|
<< " --kill-bare [ <uuid> , ... ] Delete 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> Specify password for when encrypting a (the) key." << endl |
||||
|
<< " --hint <hint> Specify hint for the --lock password." << 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; |
||||
|
string m_lockHint; |
||||
|
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;
|
||||
|
}; |
@ -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; |
||||
|
} |
||||
|
|
@ -0,0 +1,24 @@ |
|||||
|
cmake_policy(SET CMP0015 NEW) |
||||
|
# this policy was introduced in cmake 3.0 |
||||
|
# remove if, once 3.0 will be used on unix |
||||
|
if (${CMAKE_MAJOR_VERSION} GREATER 2) |
||||
|
# old policy do not use MACOSX_RPATH |
||||
|
cmake_policy(SET CMP0042 OLD) |
||||
|
endif() |
||||
|
set(CMAKE_AUTOMOC OFF) |
||||
|
|
||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") |
||||
|
|
||||
|
aux_source_directory(. SRC_LIST) |
||||
|
|
||||
|
include_directories(BEFORE ..) |
||||
|
|
||||
|
set(EXECUTABLE scrypt) |
||||
|
|
||||
|
file(GLOB HEADERS "*.h") |
||||
|
|
||||
|
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) |
||||
|
|
||||
|
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) |
||||
|
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) |
||||
|
|
@ -0,0 +1,9 @@ |
|||||
|
Copyright (c) 2013, Joshua Small |
||||
|
All rights reserved. |
||||
|
|
||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
||||
|
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
||||
|
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
||||
|
|
||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
|
@ -0,0 +1,313 @@ |
|||||
|
/*
|
||||
|
* Copyright (c) 1996 by Internet Software Consortium. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS |
||||
|
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES |
||||
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE |
||||
|
* CONSORTIUM 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. |
||||
|
*/ |
||||
|
|
||||
|
/*
|
||||
|
* Portions Copyright (c) 1995 by International Business Machines, Inc. |
||||
|
* |
||||
|
* International Business Machines, Inc. (hereinafter called IBM) grants |
||||
|
* permission under its copyrights to use, copy, modify, and distribute this |
||||
|
* Software with or without fee, provided that the above copyright notice and |
||||
|
* all paragraphs of this notice appear in all copies, and that the name of IBM |
||||
|
* not be used in connection with the marketing of any product incorporating |
||||
|
* the Software or modifications thereof, without specific, written prior |
||||
|
* permission. |
||||
|
* |
||||
|
* To the extent it has a right to do so, IBM grants an immunity from suit |
||||
|
* under its patents, if any, for the use, sale or manufacture of products to |
||||
|
* the extent that such products are used for performing Domain Name System |
||||
|
* dynamic updates in TCP/IP networks by means of the Software. No immunity is |
||||
|
* granted for any product per se or for any other function of any product. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, |
||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||||
|
* PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, |
||||
|
* DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING |
||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN |
||||
|
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. |
||||
|
*/ |
||||
|
|
||||
|
/*
|
||||
|
* Base64 encode/decode functions from OpenBSD (src/lib/libc/net/base64.c). |
||||
|
*/ |
||||
|
#include <stdio.h> |
||||
|
#include <string.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <ctype.h> |
||||
|
#include <sys/types.h> |
||||
|
|
||||
|
#include "b64.h" |
||||
|
|
||||
|
|
||||
|
static const char Base64[] = |
||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
||||
|
static const char Pad64 = '='; |
||||
|
|
||||
|
/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
|
||||
|
The following encoding technique is taken from RFC 1521 by Borenstein |
||||
|
and Freed. It is reproduced here in a slightly edited form for |
||||
|
convenience. |
||||
|
|
||||
|
A 65-character subset of US-ASCII is used, enabling 6 bits to be |
||||
|
represented per printable character. (The extra 65th character, "=", |
||||
|
is used to signify a special processing function.) |
||||
|
|
||||
|
The encoding process represents 24-bit groups of input bits as output |
||||
|
strings of 4 encoded characters. Proceeding from left to right, a |
||||
|
24-bit input group is formed by concatenating 3 8-bit input groups. |
||||
|
These 24 bits are then treated as 4 concatenated 6-bit groups, each |
||||
|
of which is translated into a single digit in the base64 alphabet. |
||||
|
|
||||
|
Each 6-bit group is used as an index into an array of 64 printable |
||||
|
characters. The character referenced by the index is placed in the |
||||
|
output string. |
||||
|
|
||||
|
Table 1: The Base64 Alphabet |
||||
|
|
||||
|
Value Encoding Value Encoding Value Encoding Value Encoding |
||||
|
0 A 17 R 34 i 51 z |
||||
|
1 B 18 S 35 j 52 0 |
||||
|
2 C 19 T 36 k 53 1 |
||||
|
3 D 20 U 37 l 54 2 |
||||
|
4 E 21 V 38 m 55 3 |
||||
|
5 F 22 W 39 n 56 4 |
||||
|
6 G 23 X 40 o 57 5 |
||||
|
7 H 24 Y 41 p 58 6 |
||||
|
8 I 25 Z 42 q 59 7 |
||||
|
9 J 26 a 43 r 60 8 |
||||
|
10 K 27 b 44 s 61 9 |
||||
|
11 L 28 c 45 t 62 + |
||||
|
12 M 29 d 46 u 63 / |
||||
|
13 N 30 e 47 v |
||||
|
14 O 31 f 48 w (pad) = |
||||
|
15 P 32 g 49 x |
||||
|
16 Q 33 h 50 y |
||||
|
|
||||
|
Special processing is performed if fewer than 24 bits are available |
||||
|
at the end of the data being encoded. A full encoding quantum is |
||||
|
always completed at the end of a quantity. When fewer than 24 input |
||||
|
bits are available in an input group, zero bits are added (on the |
||||
|
right) to form an integral number of 6-bit groups. Padding at the |
||||
|
end of the data is performed using the '=' character. |
||||
|
|
||||
|
Since all base64 input is an integral number of octets, only the |
||||
|
------------------------------------------------- |
||||
|
following cases can arise: |
||||
|
|
||||
|
(1) the final quantum of encoding input is an integral |
||||
|
multiple of 24 bits; here, the final unit of encoded |
||||
|
output will be an integral multiple of 4 characters |
||||
|
with no "=" padding, |
||||
|
(2) the final quantum of encoding input is exactly 8 bits; |
||||
|
here, the final unit of encoded output will be two |
||||
|
characters followed by two "=" padding characters, or |
||||
|
(3) the final quantum of encoding input is exactly 16 bits; |
||||
|
here, the final unit of encoded output will be three |
||||
|
characters followed by one "=" padding character. |
||||
|
*/ |
||||
|
|
||||
|
int |
||||
|
libscrypt_b64_encode(src, srclength, target, targsize) |
||||
|
unsigned char const *src; |
||||
|
size_t srclength; |
||||
|
char *target; |
||||
|
size_t targsize; |
||||
|
{ |
||||
|
size_t datalength = 0; |
||||
|
unsigned char input[3]; |
||||
|
unsigned char output[4]; |
||||
|
unsigned int i; |
||||
|
|
||||
|
while (2 < srclength) { |
||||
|
input[0] = *src++; |
||||
|
input[1] = *src++; |
||||
|
input[2] = *src++; |
||||
|
srclength -= 3; |
||||
|
|
||||
|
output[0] = input[0] >> 2; |
||||
|
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); |
||||
|
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); |
||||
|
output[3] = input[2] & 0x3f; |
||||
|
|
||||
|
if (datalength + 4 > targsize) |
||||
|
return (-1); |
||||
|
target[datalength++] = Base64[output[0]]; |
||||
|
target[datalength++] = Base64[output[1]]; |
||||
|
target[datalength++] = Base64[output[2]]; |
||||
|
target[datalength++] = Base64[output[3]]; |
||||
|
} |
||||
|
|
||||
|
/* Now we worry about padding. */ |
||||
|
if (0 != srclength) { |
||||
|
/* Get what's left. */ |
||||
|
input[0] = input[1] = input[2] = '\0'; |
||||
|
for (i = 0; i < srclength; i++) |
||||
|
input[i] = *src++; |
||||
|
|
||||
|
output[0] = input[0] >> 2; |
||||
|
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); |
||||
|
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); |
||||
|
|
||||
|
if (datalength + 4 > targsize) |
||||
|
return (-1); |
||||
|
target[datalength++] = Base64[output[0]]; |
||||
|
target[datalength++] = Base64[output[1]]; |
||||
|
if (srclength == 1) |
||||
|
target[datalength++] = Pad64; |
||||
|
else |
||||
|
target[datalength++] = Base64[output[2]]; |
||||
|
target[datalength++] = Pad64; |
||||
|
} |
||||
|
if (datalength >= targsize) |
||||
|
return (-1); |
||||
|
target[datalength] = '\0'; /* Returned value doesn't count \0. */ |
||||
|
return (int)(datalength); |
||||
|
} |
||||
|
|
||||
|
/* skips all whitespace anywhere.
|
||||
|
converts characters, four at a time, starting at (or after) |
||||
|
src from base - 64 numbers into three 8 bit bytes in the target area. |
||||
|
it returns the number of data bytes stored at the target, or -1 on error. |
||||
|
*/ |
||||
|
|
||||
|
int |
||||
|
libscrypt_b64_decode(src, target, targsize) |
||||
|
char const *src; |
||||
|
unsigned char *target; |
||||
|
size_t targsize; |
||||
|
{ |
||||
|
int state, ch; |
||||
|
unsigned int tarindex; |
||||
|
unsigned char nextbyte; |
||||
|
char *pos; |
||||
|
|
||||
|
state = 0; |
||||
|
tarindex = 0; |
||||
|
|
||||
|
while ((ch = (unsigned char)*src++) != '\0') { |
||||
|
if (isspace(ch)) /* Skip whitespace anywhere. */ |
||||
|
continue; |
||||
|
|
||||
|
if (ch == Pad64) |
||||
|
break; |
||||
|
|
||||
|
pos = strchr(Base64, ch); |
||||
|
if (pos == 0) /* A non-base64 character. */ |
||||
|
return (-1); |
||||
|
|
||||
|
switch (state) { |
||||
|
case 0: |
||||
|
if (target) { |
||||
|
if (tarindex >= targsize) |
||||
|
return (-1); |
||||
|
target[tarindex] = (pos - Base64) << 2; |
||||
|
} |
||||
|
state = 1; |
||||
|
break; |
||||
|
case 1: |
||||
|
if (target) { |
||||
|
if (tarindex >= targsize) |
||||
|
return (-1); |
||||
|
target[tarindex] |= (pos - Base64) >> 4; |
||||
|
nextbyte = ((pos - Base64) & 0x0f) << 4; |
||||
|
if (tarindex + 1 < targsize) |
||||
|
target[tarindex+1] = nextbyte; |
||||
|
else if (nextbyte) |
||||
|
return (-1); |
||||
|
} |
||||
|
tarindex++; |
||||
|
state = 2; |
||||
|
break; |
||||
|
case 2: |
||||
|
if (target) { |
||||
|
if (tarindex >= targsize) |
||||
|
return (-1); |
||||
|
target[tarindex] |= (pos - Base64) >> 2; |
||||
|
nextbyte = ((pos - Base64) & 0x03) << 6; |
||||
|
if (tarindex + 1 < targsize) |
||||
|
target[tarindex+1] = nextbyte; |
||||
|
else if (nextbyte) |
||||
|
return (-1); |
||||
|
} |
||||
|
tarindex++; |
||||
|
state = 3; |
||||
|
break; |
||||
|
case 3: |
||||
|
if (target) { |
||||
|
if (tarindex >= targsize) |
||||
|
return (-1); |
||||
|
target[tarindex] |= (pos - Base64); |
||||
|
} |
||||
|
tarindex++; |
||||
|
state = 0; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
* We are done decoding Base-64 chars. Let's see if we ended |
||||
|
* on a byte boundary, and/or with erroneous trailing characters. |
||||
|
*/ |
||||
|
|
||||
|
if (ch == Pad64) { /* We got a pad char. */ |
||||
|
ch = (unsigned char)*src++; /* Skip it, get next. */ |
||||
|
switch (state) { |
||||
|
case 0: /* Invalid = in first position */ |
||||
|
case 1: /* Invalid = in second position */ |
||||
|
return (-1); |
||||
|
|
||||
|
case 2: /* Valid, means one byte of info */ |
||||
|
/* Skip any number of spaces. */ |
||||
|
for (; ch != '\0'; ch = (unsigned char)*src++) |
||||
|
if (!isspace(ch)) |
||||
|
break; |
||||
|
/* Make sure there is another trailing = sign. */ |
||||
|
if (ch != Pad64) |
||||
|
return (-1); |
||||
|
ch = (unsigned char)*src++; /* Skip the = */ |
||||
|
/* Fall through to "single trailing =" case. */ |
||||
|
/* FALLTHROUGH */ |
||||
|
|
||||
|
case 3: /* Valid, means two bytes of info */ |
||||
|
/*
|
||||
|
* We know this char is an =. Is there anything but |
||||
|
* whitespace after it? |
||||
|
*/ |
||||
|
for (; ch != '\0'; ch = (unsigned char)*src++) |
||||
|
if (!isspace(ch)) |
||||
|
return (-1); |
||||
|
|
||||
|
/*
|
||||
|
* Now make sure for cases 2 and 3 that the "extra" |
||||
|
* bits that slopped past the last full byte were |
||||
|
* zeros. If we don't check them, they become a |
||||
|
* subliminal channel. |
||||
|
*/ |
||||
|
if (target && tarindex < targsize && |
||||
|
target[tarindex] != 0) |
||||
|
return (-1); |
||||
|
} |
||||
|
} else { |
||||
|
/*
|
||||
|
* We ended by seeing the end of the string. Make sure we |
||||
|
* have no partial bytes lying around. |
||||
|
*/ |
||||
|
if (state != 0) |
||||
|
return (-1); |
||||
|
} |
||||
|
|
||||
|
return (tarindex); |
||||
|
} |
@ -0,0 +1,10 @@ |
|||||
|
|
||||
|
/* BASE64 libraries used internally - should not need to be packaged */ |
||||
|
|
||||
|
#define b64_encode_len(A) ((A+2)/3 * 4 + 1) |
||||
|
#define b64_decode_len(A) (A / 4 * 3 + 2) |
||||
|
|
||||
|
int libscrypt_b64_encode(unsigned char const *src, size_t srclength, |
||||
|
/*@out@*/ char *target, size_t targetsize); |
||||
|
int libscrypt_b64_decode(char const *src, /*@out@*/ unsigned char *target, |
||||
|
size_t targetsize); |
@ -0,0 +1,73 @@ |
|||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
#include <stdio.h> |
||||
|
#include <stdint.h> |
||||
|
#include <float.h> |
||||
|
#include <stdint.h> |
||||
|
#include <math.h> |
||||
|
|
||||
|
#ifndef S_SPLINT_S /* Including this here triggers a known bug in splint */ |
||||
|
//#include <unistd.h>
|
||||
|
#endif |
||||
|
|
||||
|
#include "libscrypt.h" |
||||
|
|
||||
|
/* ilog2 for powers of two */ |
||||
|
static uint32_t scrypt_ilog2(uint32_t n) |
||||
|
{ |
||||
|
#ifndef S_SPLINT_S |
||||
|
|
||||
|
/* Check for a valid power of two */ |
||||
|
if (n < 2 || (n & (n - 1))) |
||||
|
return -1; |
||||
|
#endif |
||||
|
uint32_t t = 1; |
||||
|
while (((uint32_t)1 << t) < n) |
||||
|
{ |
||||
|
if(t > SCRYPT_SAFE_N) |
||||
|
return (uint32_t) -1; /* Check for insanity */ |
||||
|
t++; |
||||
|
} |
||||
|
|
||||
|
return t; |
||||
|
} |
||||
|
|
||||
|
#ifdef _MSC_VER |
||||
|
#define SNPRINTF _snprintf |
||||
|
#else |
||||
|
#define SNPRINTF snprintf |
||||
|
#endif |
||||
|
|
||||
|
int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, const char *salt, |
||||
|
const char *hash, char *mcf) |
||||
|
{ |
||||
|
|
||||
|
uint32_t t, params; |
||||
|
int s; |
||||
|
|
||||
|
if(!mcf || !hash) |
||||
|
return 0; |
||||
|
/* Although larger values of r, p are valid in scrypt, this mcf format
|
||||
|
* limits to 8 bits. If your number is larger, current computers will |
||||
|
* struggle |
||||
|
*/ |
||||
|
if(r > (uint8_t)(-1) || p > (uint8_t)(-1)) |
||||
|
return 0; |
||||
|
|
||||
|
t = scrypt_ilog2(N); |
||||
|
if (t < 1) |
||||
|
return 0; |
||||
|
|
||||
|
params = (r << 8) + p; |
||||
|
params += (uint32_t)t << 16; |
||||
|
|
||||
|
/* Using snprintf - not checking for overflows. We've already
|
||||
|
* determined that mcf should be defined as at least SCRYPT_MCF_LEN |
||||
|
* in length |
||||
|
*/ |
||||
|
s = SNPRINTF(mcf, SCRYPT_MCF_LEN, SCRYPT_MCF_ID "$%06x$%s$%s", (unsigned int)params, salt, hash); |
||||
|
if (s > SCRYPT_MCF_LEN) |
||||
|
return 0; |
||||
|
|
||||
|
return 1; |
||||
|
} |
@ -0,0 +1,100 @@ |
|||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
#include <stdio.h> |
||||
|
#include <math.h> |
||||
|
|
||||
|
#include "b64.h" |
||||
|
#include "slowequals.h" |
||||
|
#include "libscrypt.h" |
||||
|
|
||||
|
#ifdef _WIN32 |
||||
|
/* On windows, strtok uses a thread-local static variable in strtok to
|
||||
|
* make strtok thread-safe. It also neglects to provide a strtok_r. */ |
||||
|
#define strtok_r(str, val, saveptr) strtok((str), (val)) |
||||
|
#endif |
||||
|
|
||||
|
int libscrypt_check(char *mcf, const char *password) |
||||
|
{ |
||||
|
/* Return values:
|
||||
|
* <0 error |
||||
|
* == 0 password incorrect |
||||
|
* >0 correct password |
||||
|
*/ |
||||
|
|
||||
|
#ifndef _WIN32 |
||||
|
char *saveptr = NULL; |
||||
|
#endif |
||||
|
uint32_t params; |
||||
|
uint64_t N; |
||||
|
uint8_t r, p; |
||||
|
int retval; |
||||
|
uint8_t hashbuf[64]; |
||||
|
char outbuf[128]; |
||||
|
uint8_t salt[32]; |
||||
|
char *tok; |
||||
|
|
||||
|
if(memcmp(mcf, SCRYPT_MCF_ID, 3) != 0) |
||||
|
{ |
||||
|
/* Only version 0 supported */ |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
tok = strtok_r(mcf, "$", &saveptr); |
||||
|
if ( !tok ) |
||||
|
return -1; |
||||
|
|
||||
|
tok = strtok_r(NULL, "$", &saveptr); |
||||
|
|
||||
|
if ( !tok ) |
||||
|
return -1; |
||||
|
|
||||
|
params = (uint32_t)strtoul(tok, NULL, 16); |
||||
|
if ( params == 0 ) |
||||
|
return -1; |
||||
|
|
||||
|
tok = strtok_r(NULL, "$", &saveptr); |
||||
|
|
||||
|
if ( !tok ) |
||||
|
return -1; |
||||
|
|
||||
|
p = params & 0xff; |
||||
|
r = (params >> 8) & 0xff; |
||||
|
N = params >> 16; |
||||
|
|
||||
|
if (N > SCRYPT_SAFE_N) |
||||
|
return -1; |
||||
|
|
||||
|
N = (uint64_t)1 << N; |
||||
|
|
||||
|
/* Useful debugging:
|
||||
|
printf("We've obtained salt 'N' r p of '%s' %d %d %d\n", tok, N,r,p); |
||||
|
*/ |
||||
|
|
||||
|
memset(salt, 0, sizeof(salt)); /* Keeps splint happy */ |
||||
|
retval = libscrypt_b64_decode(tok, (unsigned char*)salt, sizeof(salt)); |
||||
|
if (retval < 1) |
||||
|
return -1; |
||||
|
|
||||
|
retval = libscrypt_scrypt((uint8_t*)password, strlen(password), salt, |
||||
|
(uint32_t)retval, N, r, p, hashbuf, sizeof(hashbuf)); |
||||
|
|
||||
|
if (retval != 0) |
||||
|
return -1; |
||||
|
|
||||
|
retval = libscrypt_b64_encode((unsigned char*)hashbuf, sizeof(hashbuf), |
||||
|
outbuf, sizeof(outbuf)); |
||||
|
|
||||
|
if (retval == 0) |
||||
|
return -1; |
||||
|
|
||||
|
tok = strtok_r(NULL, "$", &saveptr); |
||||
|
|
||||
|
if ( !tok ) |
||||
|
return -1; |
||||
|
|
||||
|
if(slow_equals(tok, outbuf) == 0) |
||||
|
return 0; |
||||
|
|
||||
|
return 1; /* This is the "else" condition */ |
||||
|
} |
||||
|
|
@ -0,0 +1,35 @@ |
|||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
#include <stdio.h> |
||||
|
#include <stdint.h> |
||||
|
|
||||
|
/* The hexconvert function is only used to test reference vectors against
|
||||
|
* known answers. The contents of this file are therefore a component |
||||
|
* to assist with test harnesses only |
||||
|
*/ |
||||
|
|
||||
|
int libscrypt_hexconvert(uint8_t *buf, size_t s, char *outbuf, size_t obs) |
||||
|
{ |
||||
|
|
||||
|
size_t i; |
||||
|
int len = 0; |
||||
|
|
||||
|
if (!buf || s < 1 || obs < (s * 2 + 1)) |
||||
|
return 0; |
||||
|
|
||||
|
memset(outbuf, 0, obs); |
||||
|
|
||||
|
|
||||
|
for(i=0; i<=(s-1); i++) |
||||
|
{ |
||||
|
/* snprintf(outbuf, s,"%s...", outbuf....) has undefined results
|
||||
|
* and can't be used. Using offests like this makes snprintf |
||||
|
* nontrivial. we therefore have use inescure sprintf() and |
||||
|
* lengths checked elsewhere (start of function) */ |
||||
|
/*@ -bufferoverflowhigh @*/ |
||||
|
len += sprintf(outbuf+len, "%02x", (unsigned int) buf[i]); |
||||
|
} |
||||
|
|
||||
|
return 1; |
||||
|
} |
||||
|
|
@ -0,0 +1,9 @@ |
|||||
|
|
||||
|
#include <stdint.h> |
||||
|
|
||||
|
/**
|
||||
|
* Converts a binary string to a hex representation of that string |
||||
|
* outbuf must have size of at least buf * 2 + 1. |
||||
|
*/ |
||||
|
int libscrypt_hexconvert(const uint8_t *buf, size_t s, char *outbuf, |
||||
|
size_t obs); |
@ -0,0 +1,342 @@ |
|||||
|
/*-
|
||||
|
* Copyright 2009 Colin Percival |
||||
|
* All rights reserved. |
||||
|
* |
||||
|
* Redistribution and use in source and binary forms, with or without |
||||
|
* modification, are permitted provided that the following conditions |
||||
|
* are met: |
||||
|
* 1. Redistributions of source code must retain the above copyright |
||||
|
* notice, this list of conditions and the following disclaimer. |
||||
|
* 2. Redistributions in binary form must reproduce the above copyright |
||||
|
* notice, this list of conditions and the following disclaimer in the |
||||
|
* documentation and/or other materials provided with the distribution. |
||||
|
* |
||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
|
* SUCH DAMAGE. |
||||
|
* |
||||
|
* This file was originally written by Colin Percival as part of the Tarsnap |
||||
|
* online backup system. |
||||
|
*/ |
||||
|
|
||||
|
#include <sys/types.h> |
||||
|
#ifndef _WIN32 |
||||
|
#include <sys/mman.h> |
||||
|
#endif |
||||
|
#include <errno.h> |
||||
|
#include <stdint.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
#include "sha256.h" |
||||
|
#include "sysendian.h" |
||||
|
|
||||
|
#include "libscrypt.h" |
||||
|
|
||||
|
static void blkcpy(void *, void *, size_t); |
||||
|
static void blkxor(void *, void *, size_t); |
||||
|
static void salsa20_8(uint32_t[16]); |
||||
|
static void blockmix_salsa8(uint32_t *, uint32_t *, uint32_t *, size_t); |
||||
|
static uint64_t integerify(void *, size_t); |
||||
|
static void smix(uint8_t *, size_t, uint64_t, uint32_t *, uint32_t *); |
||||
|
|
||||
|
static void |
||||
|
blkcpy(void * dest, void * src, size_t len) |
||||
|
{ |
||||
|
size_t * D = dest; |
||||
|
size_t * S = src; |
||||
|
size_t L = len / sizeof(size_t); |
||||
|
size_t i; |
||||
|
|
||||
|
for (i = 0; i < L; i++) |
||||
|
D[i] = S[i]; |
||||
|
} |
||||
|
|
||||
|
static void |
||||
|
blkxor(void * dest, void * src, size_t len) |
||||
|
{ |
||||
|
size_t * D = dest; |
||||
|
size_t * S = src; |
||||
|
size_t L = len / sizeof(size_t); |
||||
|
size_t i; |
||||
|
|
||||
|
for (i = 0; i < L; i++) |
||||
|
D[i] ^= S[i]; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* salsa20_8(B): |
||||
|
* Apply the salsa20/8 core to the provided block. |
||||
|
*/ |
||||
|
static void |
||||
|
salsa20_8(uint32_t B[16]) |
||||
|
{ |
||||
|
uint32_t x[16]; |
||||
|
size_t i; |
||||
|
|
||||
|
blkcpy(x, B, 64); |
||||
|
for (i = 0; i < 8; i += 2) { |
||||
|
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) |
||||
|
/* Operate on columns. */ |
||||
|
x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); |
||||
|
x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); |
||||
|
|
||||
|
x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); |
||||
|
x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); |
||||
|
|
||||
|
x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); |
||||
|
x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); |
||||
|
|
||||
|
x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); |
||||
|
x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); |
||||
|
|
||||
|
/* Operate on rows. */ |
||||
|
x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); |
||||
|
x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); |
||||
|
|
||||
|
x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); |
||||
|
x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); |
||||
|
|
||||
|
x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); |
||||
|
x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); |
||||
|
|
||||
|
x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); |
||||
|
x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); |
||||
|
#undef R |
||||
|
} |
||||
|
for (i = 0; i < 16; i++) |
||||
|
B[i] += x[i]; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* blockmix_salsa8(Bin, Bout, X, r): |
||||
|
* Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r |
||||
|
* bytes in length; the output Bout must also be the same size. The |
||||
|
* temporary space X must be 64 bytes. |
||||
|
*/ |
||||
|
static void |
||||
|
blockmix_salsa8(uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r) |
||||
|
{ |
||||
|
size_t i; |
||||
|
|
||||
|
/* 1: X <-- B_{2r - 1} */ |
||||
|
blkcpy(X, &Bin[(2 * r - 1) * 16], 64); |
||||
|
|
||||
|
/* 2: for i = 0 to 2r - 1 do */ |
||||
|
for (i = 0; i < 2 * r; i += 2) { |
||||
|
/* 3: X <-- H(X \xor B_i) */ |
||||
|
blkxor(X, &Bin[i * 16], 64); |
||||
|
salsa20_8(X); |
||||
|
|
||||
|
/* 4: Y_i <-- X */ |
||||
|
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ |
||||
|
blkcpy(&Bout[i * 8], X, 64); |
||||
|
|
||||
|
/* 3: X <-- H(X \xor B_i) */ |
||||
|
blkxor(X, &Bin[i * 16 + 16], 64); |
||||
|
salsa20_8(X); |
||||
|
|
||||
|
/* 4: Y_i <-- X */ |
||||
|
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ |
||||
|
blkcpy(&Bout[i * 8 + r * 16], X, 64); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* integerify(B, r): |
||||
|
* Return the result of parsing B_{2r-1} as a little-endian integer. |
||||
|
*/ |
||||
|
static uint64_t |
||||
|
integerify(void * B, size_t r) |
||||
|
{ |
||||
|
uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64); |
||||
|
|
||||
|
return (((uint64_t)(X[1]) << 32) + X[0]); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* smix(B, r, N, V, XY): |
||||
|
* Compute B = SMix_r(B, N). The input B must be 128r bytes in length; |
||||
|
* the temporary storage V must be 128rN bytes in length; the temporary |
||||
|
* storage XY must be 256r + 64 bytes in length. The value N must be a |
||||
|
* power of 2 greater than 1. The arrays B, V, and XY must be aligned to a |
||||
|
* multiple of 64 bytes. |
||||
|
*/ |
||||
|
static void |
||||
|
smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY) |
||||
|
{ |
||||
|
uint32_t * X = XY; |
||||
|
uint32_t * Y = &XY[32 * r]; |
||||
|
uint32_t * Z = &XY[64 * r]; |
||||
|
uint64_t i; |
||||
|
uint64_t j; |
||||
|
size_t k; |
||||
|
|
||||
|
/* 1: X <-- B */ |
||||
|
for (k = 0; k < 32 * r; k++) |
||||
|
X[k] = le32dec(&B[4 * k]); |
||||
|
|
||||
|
/* 2: for i = 0 to N - 1 do */ |
||||
|
for (i = 0; i < N; i += 2) { |
||||
|
/* 3: V_i <-- X */ |
||||
|
blkcpy(&V[i * (32 * r)], X, 128 * r); |
||||
|
|
||||
|
/* 4: X <-- H(X) */ |
||||
|
blockmix_salsa8(X, Y, Z, r); |
||||
|
|
||||
|
/* 3: V_i <-- X */ |
||||
|
blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r); |
||||
|
|
||||
|
/* 4: X <-- H(X) */ |
||||
|
blockmix_salsa8(Y, X, Z, r); |
||||
|
} |
||||
|
|
||||
|
/* 6: for i = 0 to N - 1 do */ |
||||
|
for (i = 0; i < N; i += 2) { |
||||
|
/* 7: j <-- Integerify(X) mod N */ |
||||
|
j = integerify(X, r) & (N - 1); |
||||
|
|
||||
|
/* 8: X <-- H(X \xor V_j) */ |
||||
|
blkxor(X, &V[j * (32 * r)], 128 * r); |
||||
|
blockmix_salsa8(X, Y, Z, r); |
||||
|
|
||||
|
/* 7: j <-- Integerify(X) mod N */ |
||||
|
j = integerify(Y, r) & (N - 1); |
||||
|
|
||||
|
/* 8: X <-- H(X \xor V_j) */ |
||||
|
blkxor(Y, &V[j * (32 * r)], 128 * r); |
||||
|
blockmix_salsa8(Y, X, Z, r); |
||||
|
} |
||||
|
|
||||
|
/* 10: B' <-- X */ |
||||
|
for (k = 0; k < 32 * r; k++) |
||||
|
le32enc(&B[4 * k], X[k]); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): |
||||
|
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, |
||||
|
* p, buflen) and write the result into buf. The parameters r, p, and buflen |
||||
|
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N |
||||
|
* must be a power of 2 greater than 1. |
||||
|
* |
||||
|
* Return 0 on success; or -1 on error |
||||
|
*/ |
||||
|
int |
||||
|
libscrypt_scrypt(const uint8_t * passwd, size_t passwdlen, |
||||
|
const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p, |
||||
|
uint8_t * buf, size_t buflen) |
||||
|
{ |
||||
|
void * B0, * V0, * XY0; |
||||
|
uint8_t * B; |
||||
|
uint32_t * V; |
||||
|
uint32_t * XY; |
||||
|
uint32_t i; |
||||
|
|
||||
|
/* Sanity-check parameters. */ |
||||
|
#if SIZE_MAX > UINT32_MAX |
||||
|
if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { |
||||
|
errno = EFBIG; |
||||
|
goto err0; |
||||
|
} |
||||
|
#endif |
||||
|
if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { |
||||
|
errno = EFBIG; |
||||
|
goto err0; |
||||
|
} |
||||
|
if (r == 0 || p == 0) { |
||||
|
errno = EINVAL; |
||||
|
goto err0; |
||||
|
} |
||||
|
if (((N & (N - 1)) != 0) || (N < 2)) { |
||||
|
errno = EINVAL; |
||||
|
goto err0; |
||||
|
} |
||||
|
if ((r > SIZE_MAX / 128 / p) || |
||||
|
#if SIZE_MAX / 256 <= UINT32_MAX |
||||
|
(r > SIZE_MAX / 256) || |
||||
|
#endif |
||||
|
(N > SIZE_MAX / 128 / r)) { |
||||
|
errno = ENOMEM; |
||||
|
goto err0; |
||||
|
} |
||||
|
|
||||
|
/* Allocate memory. */ |
||||
|
#ifdef HAVE_POSIX_MEMALIGN |
||||
|
if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0) |
||||
|
goto err0; |
||||
|
B = (uint8_t *)(B0); |
||||
|
if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0) |
||||
|
goto err1; |
||||
|
XY = (uint32_t *)(XY0); |
||||
|
#ifndef MAP_ANON |
||||
|
if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0) |
||||
|
goto err2; |
||||
|
V = (uint32_t *)(V0); |
||||
|
#endif |
||||
|
#else |
||||
|
if ((B0 = malloc(128 * r * p + 63)) == NULL) |
||||
|
goto err0; |
||||
|
B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63)); |
||||
|
if ((XY0 = malloc(256 * r + 64 + 63)) == NULL) |
||||
|
goto err1; |
||||
|
XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63)); |
||||
|
#ifndef MAP_ANON |
||||
|
if ((V0 = malloc(128 * r * N + 63)) == NULL) |
||||
|
goto err2; |
||||
|
V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63)); |
||||
|
#endif |
||||
|
#endif |
||||
|
#ifdef MAP_ANON |
||||
|
if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE, |
||||
|
#ifdef MAP_NOCORE |
||||
|
MAP_ANON | MAP_PRIVATE | MAP_NOCORE, |
||||
|
#else |
||||
|
MAP_ANON | MAP_PRIVATE, |
||||
|
#endif |
||||
|
-1, 0)) == MAP_FAILED) |
||||
|
goto err2; |
||||
|
V = (uint32_t *)(V0); |
||||
|
#endif |
||||
|
|
||||
|
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ |
||||
|
libscrypt_PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r); |
||||
|
|
||||
|
/* 2: for i = 0 to p - 1 do */ |
||||
|
for (i = 0; i < p; i++) { |
||||
|
/* 3: B_i <-- MF(B_i, N) */ |
||||
|
smix(&B[i * 128 * r], r, N, V, XY); |
||||
|
} |
||||
|
|
||||
|
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ |
||||
|
libscrypt_PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen); |
||||
|
|
||||
|
/* Free memory. */ |
||||
|
#ifdef MAP_ANON |
||||
|
if (munmap(V0, 128 * r * N)) |
||||
|
goto err2; |
||||
|
#else |
||||
|
free(V0); |
||||
|
#endif |
||||
|
free(XY0); |
||||
|
free(B0); |
||||
|
|
||||
|
/* Success! */ |
||||
|
return (0); |
||||
|
|
||||
|
err2: |
||||
|
free(XY0); |
||||
|
err1: |
||||
|
free(B0); |
||||
|
err0: |
||||
|
/* Failure! */ |
||||
|
return (-1); |
||||
|
} |
@ -0,0 +1,56 @@ |
|||||
|
/*-
|
||||
|
*/ |
||||
|
#ifndef _CRYPTO_SCRYPT_H_ |
||||
|
#define _CRYPTO_SCRYPT_H_ |
||||
|
|
||||
|
|
||||
|
#include <stdint.h> |
||||
|
|
||||
|
#ifdef __cplusplus |
||||
|
extern "C"{ |
||||
|
#endif |
||||
|
|
||||
|
/**
|
||||
|
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): |
||||
|
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, |
||||
|
* p, buflen) and write the result into buf. The parameters r, p, and buflen |
||||
|
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N |
||||
|
* must be a power of 2 greater than 1. |
||||
|
* |
||||
|
* libscrypt_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): |
||||
|
* password; duh |
||||
|
* N: CPU AND RAM cost (first modifier) |
||||
|
* r: RAM Cost |
||||
|
* p: CPU cost (parallelisation) |
||||
|
* In short, N is your main performance modifier. Values of r = 8, p = 1 are |
||||
|
* standard unless you want to modify the CPU/RAM ratio. |
||||
|
* Return 0 on success; or -1 on error. |
||||
|
*/ |
||||
|
int libscrypt_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, |
||||
|
uint32_t, uint32_t, /*@out@*/ uint8_t *, size_t); |
||||
|
|
||||
|
/* Converts a series of input parameters to a MCF form for storage */ |
||||
|
int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, const char *salt, |
||||
|
const char *hash, char *mcf); |
||||
|
|
||||
|
/* Checks a given MCF against a password */ |
||||
|
int libscrypt_check(char *mcf, const char *password); |
||||
|
|
||||
|
#ifdef __cplusplus |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
/* Sane default values */ |
||||
|
#define SCRYPT_HASH_LEN 64 /* This can be user defined - |
||||
|
*but 64 is the reference size |
||||
|
*/ |
||||
|
#define SCRYPT_SAFE_N 30 /* This is much higher than you want. It's just |
||||
|
* a blocker for insane defines |
||||
|
*/ |
||||
|
#define SCRYPT_SALT_LEN 16 /* This is just a recommended size */ |
||||
|
#define SCRYPT_MCF_LEN 125 /* mcf is 120 byte + nul */ |
||||
|
#define SCRYPT_MCF_ID "$s1" |
||||
|
#define SCRYPT_N 16384 |
||||
|
#define SCRYPT_r 8 |
||||
|
#define SCRYPT_p 16 |
||||
|
#endif /* !_CRYPTO_SCRYPT_H_ */ |
@ -0,0 +1,8 @@ |
|||||
|
libscrypt { |
||||
|
global: libscrypt_check; |
||||
|
libscrypt_hash; |
||||
|
libscrypt_mcf; |
||||
|
libscrypt_salt_gen; |
||||
|
libscrypt_scrypt; |
||||
|
local: *; |
||||
|
}; |
@ -0,0 +1,411 @@ |
|||||
|
/*-
|
||||
|
* Copyright 2005,2007,2009 Colin Percival |
||||
|
* All rights reserved. |
||||
|
* |
||||
|
* Redistribution and use in source and binary forms, with or without |
||||
|
* modification, are permitted provided that the following conditions |
||||
|
* are met: |
||||
|
* 1. Redistributions of source code must retain the above copyright |
||||
|
* notice, this list of conditions and the following disclaimer. |
||||
|
* 2. Redistributions in binary form must reproduce the above copyright |
||||
|
* notice, this list of conditions and the following disclaimer in the |
||||
|
* documentation and/or other materials provided with the distribution. |
||||
|
* |
||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
|
* SUCH DAMAGE. |
||||
|
*/ |
||||
|
|
||||
|
#include <sys/types.h> |
||||
|
|
||||
|
#include <stdint.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
#include "sysendian.h" |
||||
|
|
||||
|
#include "sha256.h" |
||||
|
|
||||
|
/*
|
||||
|
* Encode a length len/4 vector of (uint32_t) into a length len vector of |
||||
|
* (unsigned char) in big-endian form. Assumes len is a multiple of 4. |
||||
|
*/ |
||||
|
static void |
||||
|
be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len) |
||||
|
{ |
||||
|
size_t i; |
||||
|
|
||||
|
for (i = 0; i < len / 4; i++) |
||||
|
be32enc(dst + i * 4, src[i]); |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
* Decode a big-endian length len vector of (unsigned char) into a length |
||||
|
* len/4 vector of (uint32_t). Assumes len is a multiple of 4. |
||||
|
*/ |
||||
|
static void |
||||
|
be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len) |
||||
|
{ |
||||
|
size_t i; |
||||
|
|
||||
|
for (i = 0; i < len / 4; i++) |
||||
|
dst[i] = be32dec(src + i * 4); |
||||
|
} |
||||
|
|
||||
|
/* Elementary functions used by SHA256 */ |
||||
|
#define Ch(x, y, z) ((x & (y ^ z)) ^ z) |
||||
|
#define Maj(x, y, z) ((x & (y | z)) | (y & z)) |
||||
|
#define SHR(x, n) (x >> n) |
||||
|
#define ROTR(x, n) ((x >> n) | (x << (32 - n))) |
||||
|
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) |
||||
|
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) |
||||
|
#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) |
||||
|
#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) |
||||
|
|
||||
|
/* SHA256 round function */ |
||||
|
#define RND(a, b, c, d, e, f, g, h, k) \ |
||||
|
t0 = h + S1(e) + Ch(e, f, g) + k; \ |
||||
|
t1 = S0(a) + Maj(a, b, c); \ |
||||
|
d += t0; \ |
||||
|
h = t0 + t1; |
||||
|
|
||||
|
/* Adjusted round function for rotating state */ |
||||
|
#define RNDr(S, W, i, k) \ |
||||
|
RND(S[(64 - i) % 8], S[(65 - i) % 8], \ |
||||
|
S[(66 - i) % 8], S[(67 - i) % 8], \ |
||||
|
S[(68 - i) % 8], S[(69 - i) % 8], \ |
||||
|
S[(70 - i) % 8], S[(71 - i) % 8], \ |
||||
|
W[i] + k) |
||||
|
|
||||
|
/*
|
||||
|
* SHA256 block compression function. The 256-bit state is transformed via |
||||
|
* the 512-bit input block to produce a new state. |
||||
|
*/ |
||||
|
static void |
||||
|
SHA256_Transform(uint32_t * state, const unsigned char block[64]) |
||||
|
{ |
||||
|
uint32_t W[64]; |
||||
|
uint32_t S[8]; |
||||
|
uint32_t t0, t1; |
||||
|
int i; |
||||
|
|
||||
|
/* 1. Prepare message schedule W. */ |
||||
|
be32dec_vect(W, block, 64); |
||||
|
for (i = 16; i < 64; i++) |
||||
|
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; |
||||
|
|
||||
|
/* 2. Initialize working variables. */ |
||||
|
memcpy(S, state, 32); |
||||
|
|
||||
|
/* 3. Mix. */ |
||||
|
RNDr(S, W, 0, 0x428a2f98); |
||||
|
RNDr(S, W, 1, 0x71374491); |
||||
|
RNDr(S, W, 2, 0xb5c0fbcf); |
||||
|
RNDr(S, W, 3, 0xe9b5dba5); |
||||
|
RNDr(S, W, 4, 0x3956c25b); |
||||
|
RNDr(S, W, 5, 0x59f111f1); |
||||
|
RNDr(S, W, 6, 0x923f82a4); |
||||
|
RNDr(S, W, 7, 0xab1c5ed5); |
||||
|
RNDr(S, W, 8, 0xd807aa98); |
||||
|
RNDr(S, W, 9, 0x12835b01); |
||||
|
RNDr(S, W, 10, 0x243185be); |
||||
|
RNDr(S, W, 11, 0x550c7dc3); |
||||
|
RNDr(S, W, 12, 0x72be5d74); |
||||
|
RNDr(S, W, 13, 0x80deb1fe); |
||||
|
RNDr(S, W, 14, 0x9bdc06a7); |
||||
|
RNDr(S, W, 15, 0xc19bf174); |
||||
|
RNDr(S, W, 16, 0xe49b69c1); |
||||
|
RNDr(S, W, 17, 0xefbe4786); |
||||
|
RNDr(S, W, 18, 0x0fc19dc6); |
||||
|
RNDr(S, W, 19, 0x240ca1cc); |
||||
|
RNDr(S, W, 20, 0x2de92c6f); |
||||
|
RNDr(S, W, 21, 0x4a7484aa); |
||||
|
RNDr(S, W, 22, 0x5cb0a9dc); |
||||
|
RNDr(S, W, 23, 0x76f988da); |
||||
|
RNDr(S, W, 24, 0x983e5152); |
||||
|
RNDr(S, W, 25, 0xa831c66d); |
||||
|
RNDr(S, W, 26, 0xb00327c8); |
||||
|
RNDr(S, W, 27, 0xbf597fc7); |
||||
|
RNDr(S, W, 28, 0xc6e00bf3); |
||||
|
RNDr(S, W, 29, 0xd5a79147); |
||||
|
RNDr(S, W, 30, 0x06ca6351); |
||||
|
RNDr(S, W, 31, 0x14292967); |
||||
|
RNDr(S, W, 32, 0x27b70a85); |
||||
|
RNDr(S, W, 33, 0x2e1b2138); |
||||
|
RNDr(S, W, 34, 0x4d2c6dfc); |
||||
|
RNDr(S, W, 35, 0x53380d13); |
||||
|
RNDr(S, W, 36, 0x650a7354); |
||||
|
RNDr(S, W, 37, 0x766a0abb); |
||||
|
RNDr(S, W, 38, 0x81c2c92e); |
||||
|
RNDr(S, W, 39, 0x92722c85); |
||||
|
RNDr(S, W, 40, 0xa2bfe8a1); |
||||
|
RNDr(S, W, 41, 0xa81a664b); |
||||
|
RNDr(S, W, 42, 0xc24b8b70); |
||||
|
RNDr(S, W, 43, 0xc76c51a3); |
||||
|
RNDr(S, W, 44, 0xd192e819); |
||||
|
RNDr(S, W, 45, 0xd6990624); |
||||
|
RNDr(S, W, 46, 0xf40e3585); |
||||
|
RNDr(S, W, 47, 0x106aa070); |
||||
|
RNDr(S, W, 48, 0x19a4c116); |
||||
|
RNDr(S, W, 49, 0x1e376c08); |
||||
|
RNDr(S, W, 50, 0x2748774c); |
||||
|
RNDr(S, W, 51, 0x34b0bcb5); |
||||
|
RNDr(S, W, 52, 0x391c0cb3); |
||||
|
RNDr(S, W, 53, 0x4ed8aa4a); |
||||
|
RNDr(S, W, 54, 0x5b9cca4f); |
||||
|
RNDr(S, W, 55, 0x682e6ff3); |
||||
|
RNDr(S, W, 56, 0x748f82ee); |
||||
|
RNDr(S, W, 57, 0x78a5636f); |
||||
|
RNDr(S, W, 58, 0x84c87814); |
||||
|
RNDr(S, W, 59, 0x8cc70208); |
||||
|
RNDr(S, W, 60, 0x90befffa); |
||||
|
RNDr(S, W, 61, 0xa4506ceb); |
||||
|
RNDr(S, W, 62, 0xbef9a3f7); |
||||
|
RNDr(S, W, 63, 0xc67178f2); |
||||
|
|
||||
|
/* 4. Mix local working variables into global state */ |
||||
|
for (i = 0; i < 8; i++) |
||||
|
state[i] += S[i]; |
||||
|
|
||||
|
/* Clean the stack. */ |
||||
|
memset(W, 0, 256); |
||||
|
memset(S, 0, 32); |
||||
|
t0 = t1 = 0; |
||||
|
} |
||||
|
|
||||
|
static unsigned char PAD[64] = { |
||||
|
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
||||
|
}; |
||||
|
|
||||
|
/* Add padding and terminating bit-count. */ |
||||
|
static void |
||||
|
SHA256_Pad(SHA256_CTX * ctx) |
||||
|
{ |
||||
|
unsigned char len[8]; |
||||
|
uint32_t r, plen; |
||||
|
|
||||
|
/*
|
||||
|
* Convert length to a vector of bytes -- we do this now rather |
||||
|
* than later because the length will change after we pad. |
||||
|
*/ |
||||
|
be32enc_vect(len, ctx->count, 8); |
||||
|
|
||||
|
/* Add 1--64 bytes so that the resulting length is 56 mod 64 */ |
||||
|
r = (ctx->count[1] >> 3) & 0x3f; |
||||
|
plen = (r < 56) ? (56 - r) : (120 - r); |
||||
|
libscrypt_SHA256_Update(ctx, PAD, (size_t)plen); |
||||
|
|
||||
|
/* Add the terminating bit-count */ |
||||
|
libscrypt_SHA256_Update(ctx, len, 8); |
||||
|
} |
||||
|
|
||||
|
/* SHA-256 initialization. Begins a SHA-256 operation. */ |
||||
|
void |
||||
|
libscrypt_SHA256_Init(SHA256_CTX * ctx) |
||||
|
{ |
||||
|
|
||||
|
/* Zero bits processed so far */ |
||||
|
ctx->count[0] = ctx->count[1] = 0; |
||||
|
|
||||
|
/* Magic initialization constants */ |
||||
|
ctx->state[0] = 0x6A09E667; |
||||
|
ctx->state[1] = 0xBB67AE85; |
||||
|
ctx->state[2] = 0x3C6EF372; |
||||
|
ctx->state[3] = 0xA54FF53A; |
||||
|
ctx->state[4] = 0x510E527F; |
||||
|
ctx->state[5] = 0x9B05688C; |
||||
|
ctx->state[6] = 0x1F83D9AB; |
||||
|
ctx->state[7] = 0x5BE0CD19; |
||||
|
} |
||||
|
|
||||
|
/* Add bytes into the hash */ |
||||
|
void |
||||
|
libscrypt_SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len) |
||||
|
{ |
||||
|
uint32_t bitlen[2]; |
||||
|
uint32_t r; |
||||
|
const unsigned char *src = in; |
||||
|
|
||||
|
/* Number of bytes left in the buffer from previous updates */ |
||||
|
r = (ctx->count[1] >> 3) & 0x3f; |
||||
|
|
||||
|
/* Convert the length into a number of bits */ |
||||
|
bitlen[1] = ((uint32_t)len) << 3; |
||||
|
bitlen[0] = (uint32_t)(len >> 29); |
||||
|
|
||||
|
/* Update number of bits */ |
||||
|
if ((ctx->count[1] += bitlen[1]) < bitlen[1]) |
||||
|
ctx->count[0]++; |
||||
|
ctx->count[0] += bitlen[0]; |
||||
|
|
||||
|
/* Handle the case where we don't need to perform any transforms */ |
||||
|
if (len < 64 - r) { |
||||
|
memcpy(&ctx->buf[r], src, len); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
/* Finish the current block */ |
||||
|
memcpy(&ctx->buf[r], src, 64 - r); |
||||
|
SHA256_Transform(ctx->state, ctx->buf); |
||||
|
src += 64 - r; |
||||
|
len -= 64 - r; |
||||
|
|
||||
|
/* Perform complete blocks */ |
||||
|
while (len >= 64) { |
||||
|
SHA256_Transform(ctx->state, src); |
||||
|
src += 64; |
||||
|
len -= 64; |
||||
|
} |
||||
|
|
||||
|
/* Copy left over data into buffer */ |
||||
|
memcpy(ctx->buf, src, len); |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
* SHA-256 finalization. Pads the input data, exports the hash value, |
||||
|
* and clears the context state. |
||||
|
*/ |
||||
|
void |
||||
|
libscrypt_SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx) |
||||
|
{ |
||||
|
|
||||
|
/* Add padding */ |
||||
|
SHA256_Pad(ctx); |
||||
|
|
||||
|
/* Write the hash */ |
||||
|
be32enc_vect(digest, ctx->state, 32); |
||||
|
|
||||
|
/* Clear the context state */ |
||||
|
memset((void *)ctx, 0, sizeof(*ctx)); |
||||
|
} |
||||
|
|
||||
|
/* Initialize an HMAC-SHA256 operation with the given key. */ |
||||
|
void |
||||
|
libscrypt_HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) |
||||
|
{ |
||||
|
unsigned char pad[64]; |
||||
|
unsigned char khash[32]; |
||||
|
const unsigned char * K = _K; |
||||
|
size_t i; |
||||
|
|
||||
|
/* If Klen > 64, the key is really SHA256(K). */ |
||||
|
if (Klen > 64) { |
||||
|
libscrypt_SHA256_Init(&ctx->ictx); |
||||
|
libscrypt_SHA256_Update(&ctx->ictx, K, Klen); |
||||
|
libscrypt_SHA256_Final(khash, &ctx->ictx); |
||||
|
K = khash; |
||||
|
Klen = 32; |
||||
|
} |
||||
|
|
||||
|
/* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ |
||||
|
libscrypt_SHA256_Init(&ctx->ictx); |
||||
|
memset(pad, 0x36, 64); |
||||
|
for (i = 0; i < Klen; i++) |
||||
|
pad[i] ^= K[i]; |
||||
|
libscrypt_SHA256_Update(&ctx->ictx, pad, 64); |
||||
|
|
||||
|
/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ |
||||
|
libscrypt_SHA256_Init(&ctx->octx); |
||||
|
memset(pad, 0x5c, 64); |
||||
|
for (i = 0; i < Klen; i++) |
||||
|
pad[i] ^= K[i]; |
||||
|
libscrypt_SHA256_Update(&ctx->octx, pad, 64); |
||||
|
|
||||
|
/* Clean the stack. */ |
||||
|
memset(khash, 0, 32); |
||||
|
} |
||||
|
|
||||
|
/* Add bytes to the HMAC-SHA256 operation. */ |
||||
|
void |
||||
|
libscrypt_HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len) |
||||
|
{ |
||||
|
|
||||
|
/* Feed data to the inner SHA256 operation. */ |
||||
|
libscrypt_SHA256_Update(&ctx->ictx, in, len); |
||||
|
} |
||||
|
|
||||
|
/* Finish an HMAC-SHA256 operation. */ |
||||
|
void |
||||
|
libscrypt_HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx) |
||||
|
{ |
||||
|
unsigned char ihash[32]; |
||||
|
|
||||
|
/* Finish the inner SHA256 operation. */ |
||||
|
libscrypt_SHA256_Final(ihash, &ctx->ictx); |
||||
|
|
||||
|
/* Feed the inner hash to the outer SHA256 operation. */ |
||||
|
libscrypt_SHA256_Update(&ctx->octx, ihash, 32); |
||||
|
|
||||
|
/* Finish the outer SHA256 operation. */ |
||||
|
libscrypt_SHA256_Final(digest, &ctx->octx); |
||||
|
|
||||
|
/* Clean the stack. */ |
||||
|
memset(ihash, 0, 32); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): |
||||
|
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and |
||||
|
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). |
||||
|
*/ |
||||
|
void |
||||
|
libscrypt_PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, |
||||
|
size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) |
||||
|
{ |
||||
|
HMAC_SHA256_CTX PShctx, hctx; |
||||
|
size_t i; |
||||
|
uint8_t ivec[4]; |
||||
|
uint8_t U[32]; |
||||
|
uint8_t T[32]; |
||||
|
uint64_t j; |
||||
|
int k; |
||||
|
size_t clen; |
||||
|
|
||||
|
/* Compute HMAC state after processing P and S. */ |
||||
|
libscrypt_HMAC_SHA256_Init(&PShctx, passwd, passwdlen); |
||||
|
libscrypt_HMAC_SHA256_Update(&PShctx, salt, saltlen); |
||||
|
|
||||
|
/* Iterate through the blocks. */ |
||||
|
for (i = 0; i * 32 < dkLen; i++) { |
||||
|
/* Generate INT(i + 1). */ |
||||
|
be32enc(ivec, (uint32_t)(i + 1)); |
||||
|
|
||||
|
/* Compute U_1 = PRF(P, S || INT(i)). */ |
||||
|
memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); |
||||
|
libscrypt_HMAC_SHA256_Update(&hctx, ivec, 4); |
||||
|
libscrypt_HMAC_SHA256_Final(U, &hctx); |
||||
|
|
||||
|
/* T_i = U_1 ... */ |
||||
|
memcpy(T, U, 32); |
||||
|
|
||||
|
for (j = 2; j <= c; j++) { |
||||
|
/* Compute U_j. */ |
||||
|
libscrypt_HMAC_SHA256_Init(&hctx, passwd, passwdlen); |
||||
|
libscrypt_HMAC_SHA256_Update(&hctx, U, 32); |
||||
|
libscrypt_HMAC_SHA256_Final(U, &hctx); |
||||
|
|
||||
|
/* ... xor U_j ... */ |
||||
|
for (k = 0; k < 32; k++) |
||||
|
T[k] ^= U[k]; |
||||
|
} |
||||
|
|
||||
|
/* Copy as many bytes as necessary into buf. */ |
||||
|
clen = dkLen - i * 32; |
||||
|
if (clen > 32) |
||||
|
clen = 32; |
||||
|
memcpy(&buf[i * 32], T, clen); |
||||
|
} |
||||
|
|
||||
|
/* Clean PShctx, since we never called _Final on it. */ |
||||
|
memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX)); |
||||
|
} |
@ -0,0 +1,70 @@ |
|||||
|
/*-
|
||||
|
* Copyright 2005,2007,2009 Colin Percival |
||||
|
* All rights reserved. |
||||
|
* |
||||
|
* Redistribution and use in source and binary forms, with or without |
||||
|
* modification, are permitted provided that the following conditions |
||||
|
* are met: |
||||
|
* 1. Redistributions of source code must retain the above copyright |
||||
|
* notice, this list of conditions and the following disclaimer. |
||||
|
* 2. Redistributions in binary form must reproduce the above copyright |
||||
|
* notice, this list of conditions and the following disclaimer in the |
||||
|
* documentation and/or other materials provided with the distribution. |
||||
|
* |
||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
|
* SUCH DAMAGE. |
||||
|
* |
||||
|
* $FreeBSD: src/lib/libmd/sha256.h,v 1.2 2006/01/17 15:35:56 phk Exp $ |
||||
|
*/ |
||||
|
|
||||
|
#ifndef _SHA256_H_ |
||||
|
#define _SHA256_H_ |
||||
|
|
||||
|
#include <sys/types.h> |
||||
|
|
||||
|
#include <stdint.h> |
||||
|
|
||||
|
typedef struct libscrypt_SHA256Context { |
||||
|
uint32_t state[8]; |
||||
|
uint32_t count[2]; |
||||
|
unsigned char buf[64]; |
||||
|
} SHA256_CTX; |
||||
|
|
||||
|
typedef struct libscrypt_HMAC_SHA256Context { |
||||
|
SHA256_CTX ictx; |
||||
|
SHA256_CTX octx; |
||||
|
} HMAC_SHA256_CTX; |
||||
|
|
||||
|
void libscrypt_SHA256_Init(/*@out@*/ SHA256_CTX *); |
||||
|
void libscrypt_SHA256_Update(SHA256_CTX *, const void *, size_t); |
||||
|
|
||||
|
/* Original declaration:
|
||||
|
* void SHA256_Final(unsigned char [32], SHA256_CTX *); |
||||
|
*/ |
||||
|
void libscrypt_SHA256_Final(/*@out@*/ unsigned char [], SHA256_CTX *); |
||||
|
void libscrypt_HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t); |
||||
|
void libscrypt_HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t); |
||||
|
|
||||
|
/* Original declaration:
|
||||
|
* void HMAC_SHA256_Final(unsigned char [32], HMAC_SHA256_CTX *); |
||||
|
*/ |
||||
|
void libscrypt_HMAC_SHA256_Final(unsigned char [], HMAC_SHA256_CTX *); |
||||
|
|
||||
|
/**
|
||||
|
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): |
||||
|
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and |
||||
|
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). |
||||
|
*/ |
||||
|
void libscrypt_PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, |
||||
|
uint64_t, uint8_t *, size_t); |
||||
|
|
||||
|
#endif /* !_SHA256_H_ */ |
@ -0,0 +1,26 @@ |
|||||
|
#include <string.h> |
||||
|
|
||||
|
/* Implements a constant time version of strcmp()
|
||||
|
* Will return 1 if a and b are equal, 0 if they are not */ |
||||
|
int slow_equals(const char* a, const char* b) |
||||
|
{ |
||||
|
size_t lena, lenb, diff, i; |
||||
|
lena = strlen(a); |
||||
|
lenb = strlen(b); |
||||
|
diff = strlen(a) ^ strlen(b); |
||||
|
|
||||
|
for(i=0; i<lena && i<lenb; i++) |
||||
|
{ |
||||
|
diff |= a[i] ^ b[i]; |
||||
|
} |
||||
|
if (diff == 0) |
||||
|
{ |
||||
|
return 1; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
@ -0,0 +1,5 @@ |
|||||
|
|
||||
|
/* Implements a constant time version of strcmp()
|
||||
|
* Will return 1 if a and b are equal, 0 if they are not */ |
||||
|
int slow_equals(const char* a, const char* b); |
||||
|
|
@ -0,0 +1,144 @@ |
|||||
|
/*-
|
||||
|
* Copyright 2007-2009 Colin Percival |
||||
|
* All rights reserved. |
||||
|
* |
||||
|
* Redistribution and use in source and binary forms, with or without |
||||
|
* modification, are permitted provided that the following conditions |
||||
|
* are met: |
||||
|
* 1. Redistributions of source code must retain the above copyright |
||||
|
* notice, this list of conditions and the following disclaimer. |
||||
|
* 2. Redistributions in binary form must reproduce the above copyright |
||||
|
* notice, this list of conditions and the following disclaimer in the |
||||
|
* documentation and/or other materials provided with the distribution. |
||||
|
* |
||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
|
* SUCH DAMAGE. |
||||
|
* |
||||
|
* This file was originally written by Colin Percival as part of the Tarsnap |
||||
|
* online backup system. |
||||
|
*/ |
||||
|
#ifndef _SYSENDIAN_H_ |
||||
|
#define _SYSENDIAN_H_ |
||||
|
|
||||
|
|
||||
|
/* If we don't have be64enc, the <sys/endian.h> we have isn't usable. */ |
||||
|
#if !HAVE_DECL_BE64ENC |
||||
|
#undef HAVE_SYS_ENDIAN_H |
||||
|
#endif |
||||
|
|
||||
|
#ifdef HAVE_SYS_ENDIAN_H |
||||
|
|
||||
|
#include <sys/endian.h> |
||||
|
|
||||
|
#else |
||||
|
|
||||
|
#include <stdint.h> |
||||
|
#ifdef _MSC_VER |
||||
|
#define INLINE __inline |
||||
|
#else |
||||
|
#define INLINE inline |
||||
|
#endif |
||||
|
|
||||
|
static INLINE uint32_t |
||||
|
be32dec(const void *pp) |
||||
|
{ |
||||
|
const uint8_t *p = (uint8_t const *)pp; |
||||
|
|
||||
|
return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + |
||||
|
((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); |
||||
|
} |
||||
|
|
||||
|
static INLINE void |
||||
|
be32enc(void *pp, uint32_t x) |
||||
|
{ |
||||
|
uint8_t * p = (uint8_t *)pp; |
||||
|
|
||||
|
p[3] = x & 0xff; |
||||
|
p[2] = (x >> 8) & 0xff; |
||||
|
p[1] = (x >> 16) & 0xff; |
||||
|
p[0] = (x >> 24) & 0xff; |
||||
|
} |
||||
|
|
||||
|
static INLINE uint64_t |
||||
|
be64dec(const void *pp) |
||||
|
{ |
||||
|
const uint8_t *p = (uint8_t const *)pp; |
||||
|
|
||||
|
return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) + |
||||
|
((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) + |
||||
|
((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) + |
||||
|
((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56)); |
||||
|
} |
||||
|
|
||||
|
static INLINE void |
||||
|
be64enc(void *pp, uint64_t x) |
||||
|
{ |
||||
|
uint8_t * p = (uint8_t *)pp; |
||||
|
|
||||
|
p[7] = x & 0xff; |
||||
|
p[6] = (x >> 8) & 0xff; |
||||
|
p[5] = (x >> 16) & 0xff; |
||||
|
p[4] = (x >> 24) & 0xff; |
||||
|
p[3] = (x >> 32) & 0xff; |
||||
|
p[2] = (x >> 40) & 0xff; |
||||
|
p[1] = (x >> 48) & 0xff; |
||||
|
p[0] = (x >> 56) & 0xff; |
||||
|
} |
||||
|
|
||||
|
static INLINE uint32_t |
||||
|
le32dec(const void *pp) |
||||
|
{ |
||||
|
const uint8_t *p = (uint8_t const *)pp; |
||||
|
|
||||
|
return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) + |
||||
|
((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24)); |
||||
|
} |
||||
|
|
||||
|
static INLINE void |
||||
|
le32enc(void *pp, uint32_t x) |
||||
|
{ |
||||
|
uint8_t * p = (uint8_t *)pp; |
||||
|
|
||||
|
p[0] = x & 0xff; |
||||
|
p[1] = (x >> 8) & 0xff; |
||||
|
p[2] = (x >> 16) & 0xff; |
||||
|
p[3] = (x >> 24) & 0xff; |
||||
|
} |
||||
|
|
||||
|
static INLINE uint64_t |
||||
|
le64dec(const void *pp) |
||||
|
{ |
||||
|
const uint8_t *p = (uint8_t const *)pp; |
||||
|
|
||||
|
return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) + |
||||
|
((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) + |
||||
|
((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) + |
||||
|
((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56)); |
||||
|
} |
||||
|
|
||||
|
static INLINE void |
||||
|
le64enc(void *pp, uint64_t x) |
||||
|
{ |
||||
|
uint8_t * p = (uint8_t *)pp; |
||||
|
|
||||
|
p[0] = x & 0xff; |
||||
|
p[1] = (x >> 8) & 0xff; |
||||
|
p[2] = (x >> 16) & 0xff; |
||||
|
p[3] = (x >> 24) & 0xff; |
||||
|
p[4] = (x >> 32) & 0xff; |
||||
|
p[5] = (x >> 40) & 0xff; |
||||
|
p[6] = (x >> 48) & 0xff; |
||||
|
p[7] = (x >> 56) & 0xff; |
||||
|
} |
||||
|
#endif /* !HAVE_SYS_ENDIAN_H */ |
||||
|
|
||||
|
#endif /* !_SYSENDIAN_H_ */ |
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file SecretStore.cpp
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2015 |
||||
|
* Secret store test functions. |
||||
|
*/ |
||||
|
|
||||
|
#include <fstream> |
||||
|
#include <random> |
||||
|
#include <boost/test/unit_test.hpp> |
||||
|
#include "../JsonSpiritHeaders.h" |
||||
|
#include <libdevcrypto/SecretStore.h> |
||||
|
#include <libdevcore/CommonIO.h> |
||||
|
#include <libdevcore/TrieDB.h> |
||||
|
#include <libdevcore/TrieHash.h> |
||||
|
#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() |
Loading…
Reference in new issue