Gav Wood
10 years ago
8 changed files with 544 additions and 10 deletions
@ -0,0 +1,181 @@ |
|||
/*
|
|||
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; |
|||
|
|||
auto updateImport = [&](){ |
|||
u.import_2->setDisabled(u.addressOut->text().isEmpty() || u.name->text().isEmpty()); |
|||
}; |
|||
|
|||
auto updateAddress = [&](){ |
|||
string as = u.address->text().toStdString(); |
|||
try |
|||
{ |
|||
u.addressOut->setText(QString::fromStdString(main()->render(eth::toAddress(as)))); |
|||
} |
|||
catch (...) |
|||
{ |
|||
u.addressOut->setText(""); |
|||
} |
|||
updateImport(); |
|||
}; |
|||
|
|||
auto updatePassword = [&](){ |
|||
u.passwordHash->setText(QString::fromStdString(sha3(u.password->text().toStdString()).hex())); |
|||
}; |
|||
|
|||
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.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(); |
|||
}; |
|||
|
|||
connect(u.noPassword, &QRadioButton::clicked, [&](){ |
|||
u.passwordHash->clear(); |
|||
u.hint->setText("Same as master password."); |
|||
}); |
|||
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)); |
|||
}); |
|||
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.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 = ICAP::decoded(u.addressOut->text().toStdString()).direct(); |
|||
string n = u.name->text().toStdString(); |
|||
h256 ph; |
|||
DEV_IGNORE_EXCEPTIONS(ph = h256(u.passwordHash->text().toStdString())); |
|||
string h = u.hint->text().toStdString(); |
|||
bool mp = u.noPassword->isChecked(); |
|||
string p = mp ? string() : u.oldPassword ? lastPassword : u.password->text().toStdString(); |
|||
|
|||
// check for a brain wallet import
|
|||
if (lastKey.empty() && !lastSecret) |
|||
main()->keyManager().importExistingBrain(a, n, h); |
|||
else if (!lastKey.empty() && !lastSecret) |
|||
main()->keyManager().importExisting(main()->keyManager().store().importKey(lastKey), n, a, ph, h); |
|||
else 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,291 @@ |
|||
<?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>575</width> |
|||
<height>315</height> |
|||
</rect> |
|||
</property> |
|||
<property name="windowTitle"> |
|||
<string>Dialog</string> |
|||
</property> |
|||
<layout class="QVBoxLayout" name="verticalLayout"> |
|||
<item> |
|||
<layout class="QGridLayout" name="gridLayout"> |
|||
<item row="1" column="2" colspan="2"> |
|||
<widget class="QLineEdit" name="key"> |
|||
<property name="placeholderText"> |
|||
<string>Leave blank for a brain wallet</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="1" column="4"> |
|||
<widget class="QToolButton" name="openKey"> |
|||
<property name="text"> |
|||
<string>...</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<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="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="8" column="0" colspan="2"> |
|||
<widget class="QRadioButton" name="newPassword"> |
|||
<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="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="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> |
|||
<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 Hint:</string> |
|||
</property> |
|||
<property name="buddy"> |
|||
<cstring>hint</cstring> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="6" column="2" colspan="3"> |
|||
<widget class="QLabel" name="label_6"> |
|||
<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="1" 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="label_7"> |
|||
<property name="text"> |
|||
<string>Use the same password as in the key file.</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> |
|||
<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> |
|||
</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>key</tabstop> |
|||
<tabstop>openKey</tabstop> |
|||
<tabstop>name</tabstop> |
|||
<tabstop>address</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>564</x> |
|||
<y>304</y> |
|||
</hint> |
|||
<hint type="destinationlabel"> |
|||
<x>449</x> |
|||
<y>504</y> |
|||
</hint> |
|||
</hints> |
|||
</connection> |
|||
<connection> |
|||
<sender>cancel</sender> |
|||
<signal>clicked()</signal> |
|||
<receiver>ImportKey</receiver> |
|||
<slot>reject()</slot> |
|||
<hints> |
|||
<hint type="sourcelabel"> |
|||
<x>478</x> |
|||
<y>304</y> |
|||
</hint> |
|||
<hint type="destinationlabel"> |
|||
<x>351</x> |
|||
<y>506</y> |
|||
</hint> |
|||
</hints> |
|||
</connection> |
|||
</connections> |
|||
<buttongroups> |
|||
<buttongroup name="buttonGroup"/> |
|||
</buttongroups> |
|||
</ui> |
Loading…
Reference in new issue