Gav Wood
10 years ago
9 changed files with 639 additions and 14 deletions
@ -0,0 +1,222 @@ |
|||
/*
|
|||
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 ImportKey.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
#include "ImportKey.h" |
|||
#include <QFileDialog> |
|||
#include <QMessageBox> |
|||
#include <QInputDialog> |
|||
#include <libdevcore/Log.h> |
|||
#include <libethcore/KeyManager.h> |
|||
#include <libethcore/ICAP.h> |
|||
#include <libethereum/Client.h> |
|||
#include "ui_ImportKey.h" |
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace az; |
|||
using namespace eth; |
|||
|
|||
DEV_AZ_NOTE_PLUGIN(ImportKey); |
|||
|
|||
ImportKey::ImportKey(MainFace* _m): |
|||
Plugin(_m, "ImportKey") |
|||
{ |
|||
connect(addMenuItem("Import Key...", "menuTools", true), SIGNAL(triggered()), SLOT(import())); |
|||
} |
|||
|
|||
ImportKey::~ImportKey() |
|||
{ |
|||
} |
|||
|
|||
void ImportKey::import() |
|||
{ |
|||
QDialog d; |
|||
Ui_ImportKey u; |
|||
u.setupUi(&d); |
|||
d.setWindowTitle("Import Key"); |
|||
|
|||
string lastKey; |
|||
Secret lastSecret; |
|||
string lastPassword; |
|||
Address lastAddress; |
|||
|
|||
auto updateAction = [&](){ |
|||
if (!u.import_2->isEnabled()) |
|||
u.action->clear(); |
|||
else if (lastKey.empty() && !lastSecret) |
|||
u.action->setText("Import brainwallet with given address and hint"); |
|||
else if (!lastKey.empty() && !lastSecret) |
|||
{ |
|||
h256 ph; |
|||
DEV_IGNORE_EXCEPTIONS(ph = h256(u.passwordHash->text().toStdString())); |
|||
if (ph) |
|||
u.action->setText("Import untouched key with given address and hint"); |
|||
else |
|||
u.action->setText("Import untouched key with given address, password hash and hint"); |
|||
} |
|||
else |
|||
{ |
|||
bool mp = u.noPassword->isChecked(); |
|||
if (mp) |
|||
u.action->setText("Import recast key using master password and given hint"); |
|||
else |
|||
u.action->setText("Import recast key with given password and hint"); |
|||
} |
|||
}; |
|||
|
|||
auto updateImport = [&](){ |
|||
u.import_2->setDisabled(u.addressOut->text().isEmpty() || u.name->text().isEmpty() || !(u.oldPassword->isChecked() || u.newPassword->isChecked() || u.noPassword->isChecked())); |
|||
updateAction(); |
|||
}; |
|||
|
|||
auto updateAddress = [&](){ |
|||
lastAddress.clear(); |
|||
string as = u.address->text().toStdString(); |
|||
try |
|||
{ |
|||
lastAddress = eth::toAddress(as); |
|||
u.addressOut->setText(QString::fromStdString(main()->render(lastAddress))); |
|||
} |
|||
catch (...) |
|||
{ |
|||
u.addressOut->setText(""); |
|||
} |
|||
updateImport(); |
|||
}; |
|||
|
|||
auto updatePassword = [&](){ |
|||
u.passwordHash->setText(QString::fromStdString(sha3(u.password->text().toStdString()).hex())); |
|||
updateAction(); |
|||
}; |
|||
|
|||
function<void()> updateKey = [&](){ |
|||
// update according to key.
|
|||
if (lastKey == u.key->text().toStdString()) |
|||
return; |
|||
lastKey = u.key->text().toStdString(); |
|||
lastSecret.clear(); |
|||
u.address->clear(); |
|||
u.oldPassword->setEnabled(false); |
|||
u.oldPassword->setChecked(false); |
|||
bytes b; |
|||
DEV_IGNORE_EXCEPTIONS(b = fromHex(lastKey, WhenError::Throw)); |
|||
if (b.size() == 32) |
|||
{ |
|||
lastSecret = Secret(b); |
|||
bytesRef(&b).cleanse(); |
|||
} |
|||
while (!lastKey.empty() && !lastSecret) |
|||
{ |
|||
bool ok; |
|||
lastPassword = QInputDialog::getText(&d, "Open Key File", "Enter the password protecting this key file. Cancel if you do not want to provide te password.", QLineEdit::Password, QString(), &ok).toStdString(); |
|||
if (!ok) |
|||
{ |
|||
lastSecret.clear(); |
|||
break; |
|||
} |
|||
// Try to open as a file.
|
|||
lastSecret = KeyManager::presaleSecret(contentsString(lastKey), [&](bool first){ return first ? lastPassword : string(); }).secret(); |
|||
if (!lastSecret) |
|||
lastSecret = Secret(SecretStore::secret(contentsString(lastKey), lastPassword)); |
|||
if (!lastSecret && QMessageBox::warning(&d, "Invalid Password or Key File", "The given password could not be used to decrypt the key file given. Are you sure it is a valid key file and that the password is correct?", QMessageBox::Abort, QMessageBox::Retry) == QMessageBox::Abort) |
|||
{ |
|||
u.key->clear(); |
|||
updateKey(); |
|||
return; |
|||
} |
|||
} |
|||
u.oldPassword->setEnabled(!!lastSecret); |
|||
u.newPassword->setEnabled(!!lastSecret); |
|||
u.noPassword->setEnabled(!!lastSecret); |
|||
u.masterLabel->setEnabled(!!lastSecret); |
|||
u.oldLabel->setEnabled(!!lastSecret); |
|||
u.showPassword->setEnabled(!!lastSecret); |
|||
u.password->setEnabled(!!lastSecret); |
|||
u.passwordHash->setReadOnly(!!lastSecret); |
|||
u.address->setReadOnly(!!lastSecret); |
|||
if (lastSecret) |
|||
{ |
|||
u.oldPassword->setEnabled(!lastPassword.empty()); |
|||
if (lastPassword.empty()) |
|||
u.oldPassword->setChecked(false); |
|||
u.address->setText(QString::fromStdString(ICAP(toAddress(lastSecret)).encoded())); |
|||
updateAddress(); |
|||
} |
|||
else |
|||
u.address->clear(); |
|||
updateImport(); |
|||
}; |
|||
|
|||
connect(u.noPassword, &QRadioButton::clicked, [&](){ |
|||
u.passwordHash->clear(); |
|||
u.hint->setText("No additional password (same as master password)."); |
|||
updateAction(); |
|||
}); |
|||
connect(u.oldPassword, &QRadioButton::clicked, [&](){ |
|||
u.passwordHash->setText(QString::fromStdString(sha3(lastPassword).hex())); |
|||
u.hint->setText("Same as original password for file " + QString::fromStdString(lastKey)); |
|||
updateAction(); |
|||
}); |
|||
connect(u.newPassword, &QRadioButton::clicked, [&](){ |
|||
u.hint->setText(""); |
|||
updatePassword(); |
|||
}); |
|||
connect(u.password, &QLineEdit::textChanged, [&](){ updatePassword(); }); |
|||
connect(u.address, &QLineEdit::textChanged, [&](){ updateAddress(); }); |
|||
connect(u.key, &QLineEdit::textEdited, [&](){ updateKey(); }); |
|||
connect(u.name, &QLineEdit::textEdited, [&](){ updateImport(); }); |
|||
connect(u.showPassword, &QCheckBox::toggled, [&](bool show){ u.password->setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); }); |
|||
connect(u.openKey, &QToolButton::clicked, [&](){ |
|||
QString fn = QFileDialog::getOpenFileName(main(), "Open Key File", QDir::homePath(), "JSON Files (*.json);;All Files (*)"); |
|||
if (!fn.isEmpty()) |
|||
{ |
|||
u.key->setText(fn); |
|||
updateKey(); |
|||
} |
|||
}); |
|||
|
|||
if (d.exec() == QDialog::Accepted) |
|||
{ |
|||
Address a = lastAddress; |
|||
string n = u.name->text().toStdString(); |
|||
string h = u.hint->text().toStdString(); |
|||
|
|||
// check for a brain wallet import
|
|||
if (lastKey.empty() && !lastSecret) |
|||
main()->keyManager().importExistingBrain(a, n, h); |
|||
else if (!lastKey.empty() && !lastSecret) |
|||
{ |
|||
h256 ph; |
|||
DEV_IGNORE_EXCEPTIONS(ph = h256(u.passwordHash->text().toStdString())); |
|||
main()->keyManager().importExisting(main()->keyManager().store().importKey(lastKey), n, a, ph, h); |
|||
} |
|||
else |
|||
{ |
|||
bool mp = u.noPassword->isChecked(); |
|||
string p = mp ? string() : u.oldPassword ? lastPassword : u.password->text().toStdString(); |
|||
if (mp) |
|||
main()->keyManager().import(lastSecret, n); |
|||
else |
|||
main()->keyManager().import(lastSecret, n, p, h); |
|||
} |
|||
|
|||
main()->noteKeysChanged(); |
|||
} |
|||
} |
@ -0,0 +1,44 @@ |
|||
/*
|
|||
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 ImportKey.h
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include "MainFace.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace az |
|||
{ |
|||
|
|||
class ImportKey: public QObject, public Plugin |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
ImportKey(MainFace* _m); |
|||
~ImportKey(); |
|||
|
|||
private slots: |
|||
void import(); |
|||
}; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,336 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<ui version="4.0"> |
|||
<class>ImportKey</class> |
|||
<widget class="QDialog" name="ImportKey"> |
|||
<property name="geometry"> |
|||
<rect> |
|||
<x>0</x> |
|||
<y>0</y> |
|||
<width>530</width> |
|||
<height>389</height> |
|||
</rect> |
|||
</property> |
|||
<property name="windowTitle"> |
|||
<string>Dialog</string> |
|||
</property> |
|||
<layout class="QVBoxLayout" name="verticalLayout"> |
|||
<item> |
|||
<layout class="QGridLayout" name="gridLayout"> |
|||
<item row="10" column="2" colspan="3"> |
|||
<widget class="QLineEdit" name="passwordHash"> |
|||
<property name="readOnly"> |
|||
<bool>true</bool> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="8" column="3" colspan="2"> |
|||
<widget class="QCheckBox" name="showPassword"> |
|||
<property name="enabled"> |
|||
<bool>false</bool> |
|||
</property> |
|||
<property name="text"> |
|||
<string>Show</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="4" column="0" colspan="2"> |
|||
<widget class="QLabel" name="label_2"> |
|||
<property name="text"> |
|||
<string>&Address:</string> |
|||
</property> |
|||
<property name="buddy"> |
|||
<cstring>address</cstring> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="3" column="4"> |
|||
<widget class="QToolButton" name="openKey"> |
|||
<property name="text"> |
|||
<string>...</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="8" column="0" colspan="2"> |
|||
<widget class="QRadioButton" name="newPassword"> |
|||
<property name="enabled"> |
|||
<bool>false</bool> |
|||
</property> |
|||
<property name="text"> |
|||
<string>New &Password:</string> |
|||
</property> |
|||
<attribute name="buttonGroup"> |
|||
<string notr="true">buttonGroup</string> |
|||
</attribute> |
|||
</widget> |
|||
</item> |
|||
<item row="4" column="2" colspan="3"> |
|||
<widget class="QLineEdit" name="address"> |
|||
<property name="placeholderText"> |
|||
<string>Place the address of the key here</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="2" column="0" colspan="2"> |
|||
<widget class="QLabel" name="label_4"> |
|||
<property name="text"> |
|||
<string>&Name:</string> |
|||
</property> |
|||
<property name="buddy"> |
|||
<cstring>name</cstring> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="6" column="0" colspan="2"> |
|||
<widget class="QRadioButton" name="noPassword"> |
|||
<property name="enabled"> |
|||
<bool>false</bool> |
|||
</property> |
|||
<property name="text"> |
|||
<string>&Master password</string> |
|||
</property> |
|||
<property name="checked"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<attribute name="buttonGroup"> |
|||
<string notr="true">buttonGroup</string> |
|||
</attribute> |
|||
</widget> |
|||
</item> |
|||
<item row="11" column="2" colspan="3"> |
|||
<widget class="QLineEdit" name="hint"/> |
|||
</item> |
|||
<item row="7" column="0" colspan="2"> |
|||
<widget class="QRadioButton" name="oldPassword"> |
|||
<property name="enabled"> |
|||
<bool>false</bool> |
|||
</property> |
|||
<property name="text"> |
|||
<string>&Old password</string> |
|||
</property> |
|||
<attribute name="buttonGroup"> |
|||
<string notr="true">buttonGroup</string> |
|||
</attribute> |
|||
</widget> |
|||
</item> |
|||
<item row="8" column="2"> |
|||
<widget class="QLineEdit" name="password"> |
|||
<property name="placeholderText"> |
|||
<string>Enter the password you wish to use for the key here</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="2" column="2" colspan="3"> |
|||
<widget class="QLineEdit" name="name"> |
|||
<property name="placeholderText"> |
|||
<string>Enter this key's name here</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="10" column="0" colspan="2"> |
|||
<widget class="QLabel" name="label_3"> |
|||
<property name="text"> |
|||
<string>Password &Hash:</string> |
|||
</property> |
|||
<property name="buddy"> |
|||
<cstring>passwordHash</cstring> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="11" column="0" colspan="2"> |
|||
<widget class="QLabel" name="label_5"> |
|||
<property name="text"> |
|||
<string>Password Hin&t:</string> |
|||
</property> |
|||
<property name="buddy"> |
|||
<cstring>hint</cstring> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="6" column="2" colspan="3"> |
|||
<widget class="QLabel" name="masterLabel"> |
|||
<property name="enabled"> |
|||
<bool>false</bool> |
|||
</property> |
|||
<property name="text"> |
|||
<string>Use same password for the key as for the master.</string> |
|||
</property> |
|||
<property name="wordWrap"> |
|||
<bool>false</bool> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="3" column="2" colspan="2"> |
|||
<widget class="QLineEdit" name="key"> |
|||
<property name="placeholderText"> |
|||
<string>Brain wallet (no key file)</string> |
|||
</property> |
|||
<property name="clearButtonEnabled"> |
|||
<bool>true</bool> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="3" column="0" colspan="2"> |
|||
<widget class="QLabel" name="label"> |
|||
<property name="text"> |
|||
<string>&Key:</string> |
|||
</property> |
|||
<property name="buddy"> |
|||
<cstring>key</cstring> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="7" column="2" colspan="3"> |
|||
<widget class="QLabel" name="oldLabel"> |
|||
<property name="enabled"> |
|||
<bool>false</bool> |
|||
</property> |
|||
<property name="text"> |
|||
<string>Use the same password as in the key file.</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="5" column="2" colspan="3"> |
|||
<widget class="QLineEdit" name="addressOut"> |
|||
<property name="readOnly"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<property name="placeholderText"> |
|||
<string>Unknown Address</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</item> |
|||
<item> |
|||
<spacer name="verticalSpacer"> |
|||
<property name="orientation"> |
|||
<enum>Qt::Vertical</enum> |
|||
</property> |
|||
<property name="sizeHint" stdset="0"> |
|||
<size> |
|||
<width>20</width> |
|||
<height>5</height> |
|||
</size> |
|||
</property> |
|||
</spacer> |
|||
</item> |
|||
<item> |
|||
<layout class="QHBoxLayout" name="horizontalLayout"> |
|||
<item> |
|||
<widget class="QLabel" name="action"> |
|||
<property name="text"> |
|||
<string/> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<spacer name="horizontalSpacer"> |
|||
<property name="orientation"> |
|||
<enum>Qt::Horizontal</enum> |
|||
</property> |
|||
<property name="sizeHint" stdset="0"> |
|||
<size> |
|||
<width>40</width> |
|||
<height>20</height> |
|||
</size> |
|||
</property> |
|||
</spacer> |
|||
</item> |
|||
<item> |
|||
<widget class="QPushButton" name="cancel"> |
|||
<property name="text"> |
|||
<string>Cancel</string> |
|||
</property> |
|||
<property name="shortcut"> |
|||
<string>Esc</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QPushButton" name="import_2"> |
|||
<property name="enabled"> |
|||
<bool>false</bool> |
|||
</property> |
|||
<property name="text"> |
|||
<string>&Import</string> |
|||
</property> |
|||
<property name="default"> |
|||
<bool>true</bool> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
<tabstops> |
|||
<tabstop>name</tabstop> |
|||
<tabstop>key</tabstop> |
|||
<tabstop>openKey</tabstop> |
|||
<tabstop>address</tabstop> |
|||
<tabstop>addressOut</tabstop> |
|||
<tabstop>noPassword</tabstop> |
|||
<tabstop>oldPassword</tabstop> |
|||
<tabstop>newPassword</tabstop> |
|||
<tabstop>password</tabstop> |
|||
<tabstop>showPassword</tabstop> |
|||
<tabstop>passwordHash</tabstop> |
|||
<tabstop>hint</tabstop> |
|||
<tabstop>cancel</tabstop> |
|||
<tabstop>import_2</tabstop> |
|||
</tabstops> |
|||
<resources/> |
|||
<connections> |
|||
<connection> |
|||
<sender>import_2</sender> |
|||
<signal>clicked()</signal> |
|||
<receiver>ImportKey</receiver> |
|||
<slot>accept()</slot> |
|||
<hints> |
|||
<hint type="sourcelabel"> |
|||
<x>519</x> |
|||
<y>378</y> |
|||
</hint> |
|||
<hint type="destinationlabel"> |
|||
<x>449</x> |
|||
<y>388</y> |
|||
</hint> |
|||
</hints> |
|||
</connection> |
|||
<connection> |
|||
<sender>cancel</sender> |
|||
<signal>clicked()</signal> |
|||
<receiver>ImportKey</receiver> |
|||
<slot>reject()</slot> |
|||
<hints> |
|||
<hint type="sourcelabel"> |
|||
<x>433</x> |
|||
<y>378</y> |
|||
</hint> |
|||
<hint type="destinationlabel"> |
|||
<x>351</x> |
|||
<y>388</y> |
|||
</hint> |
|||
</hints> |
|||
</connection> |
|||
<connection> |
|||
<sender>newPassword</sender> |
|||
<signal>pressed()</signal> |
|||
<receiver>password</receiver> |
|||
<slot>setFocus()</slot> |
|||
<hints> |
|||
<hint type="sourcelabel"> |
|||
<x>80</x> |
|||
<y>211</y> |
|||
</hint> |
|||
<hint type="destinationlabel"> |
|||
<x>185</x> |
|||
<y>215</y> |
|||
</hint> |
|||
</hints> |
|||
</connection> |
|||
</connections> |
|||
<buttongroups> |
|||
<buttongroup name="buttonGroup"/> |
|||
</buttongroups> |
|||
</ui> |
Loading…
Reference in new issue