Line data Source code
1 : // Copyright (c) 2011-2013 The Bitcoin Core developers
2 : // Distributed under the MIT software license, see the accompanying
3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 :
5 : #include "signverifymessagedialog.h"
6 : #include "ui_signverifymessagedialog.h"
7 :
8 : #include "addressbookpage.h"
9 : #include "guiutil.h"
10 : #include "platformstyle.h"
11 : #include "walletmodel.h"
12 :
13 : #include "base58.h"
14 : #include "init.h"
15 : #include "main.h" // For strMessageMagic
16 : #include "wallet/wallet.h"
17 :
18 : #include <string>
19 : #include <vector>
20 :
21 : #include <QClipboard>
22 :
23 0 : SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *platformStyle, QWidget *parent) :
24 : QDialog(parent),
25 0 : ui(new Ui::SignVerifyMessageDialog),
26 : model(0),
27 0 : platformStyle(platformStyle)
28 : {
29 0 : ui->setupUi(this);
30 :
31 0 : ui->addressBookButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
32 0 : ui->pasteButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editpaste"));
33 0 : ui->copySignatureButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editcopy"));
34 0 : ui->signMessageButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/edit"));
35 0 : ui->clearButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
36 0 : ui->addressBookButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
37 0 : ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/transaction_0"));
38 0 : ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
39 :
40 : #if QT_VERSION >= 0x040700
41 0 : ui->signatureOut_SM->setPlaceholderText(tr("Click \"Sign Message\" to generate signature"));
42 : #endif
43 :
44 0 : GUIUtil::setupAddressWidget(ui->addressIn_SM, this);
45 0 : GUIUtil::setupAddressWidget(ui->addressIn_VM, this);
46 :
47 0 : ui->addressIn_SM->installEventFilter(this);
48 0 : ui->messageIn_SM->installEventFilter(this);
49 0 : ui->signatureOut_SM->installEventFilter(this);
50 0 : ui->addressIn_VM->installEventFilter(this);
51 0 : ui->messageIn_VM->installEventFilter(this);
52 0 : ui->signatureIn_VM->installEventFilter(this);
53 :
54 0 : ui->signatureOut_SM->setFont(GUIUtil::bitcoinAddressFont());
55 0 : ui->signatureIn_VM->setFont(GUIUtil::bitcoinAddressFont());
56 0 : }
57 :
58 0 : SignVerifyMessageDialog::~SignVerifyMessageDialog()
59 : {
60 0 : delete ui;
61 0 : }
62 :
63 0 : void SignVerifyMessageDialog::setModel(WalletModel *model)
64 : {
65 0 : this->model = model;
66 0 : }
67 :
68 0 : void SignVerifyMessageDialog::setAddress_SM(const QString &address)
69 : {
70 0 : ui->addressIn_SM->setText(address);
71 0 : ui->messageIn_SM->setFocus();
72 0 : }
73 :
74 0 : void SignVerifyMessageDialog::setAddress_VM(const QString &address)
75 : {
76 0 : ui->addressIn_VM->setText(address);
77 0 : ui->messageIn_VM->setFocus();
78 0 : }
79 :
80 0 : void SignVerifyMessageDialog::showTab_SM(bool fShow)
81 : {
82 0 : ui->tabWidget->setCurrentIndex(0);
83 0 : if (fShow)
84 0 : this->show();
85 0 : }
86 :
87 0 : void SignVerifyMessageDialog::showTab_VM(bool fShow)
88 : {
89 0 : ui->tabWidget->setCurrentIndex(1);
90 0 : if (fShow)
91 0 : this->show();
92 0 : }
93 :
94 0 : void SignVerifyMessageDialog::on_addressBookButton_SM_clicked()
95 : {
96 0 : if (model && model->getAddressTableModel())
97 : {
98 0 : AddressBookPage dlg(platformStyle, AddressBookPage::ForSelection, AddressBookPage::ReceivingTab, this);
99 0 : dlg.setModel(model->getAddressTableModel());
100 0 : if (dlg.exec())
101 : {
102 0 : setAddress_SM(dlg.getReturnValue());
103 0 : }
104 : }
105 0 : }
106 :
107 0 : void SignVerifyMessageDialog::on_pasteButton_SM_clicked()
108 : {
109 0 : setAddress_SM(QApplication::clipboard()->text());
110 0 : }
111 :
112 0 : void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
113 : {
114 0 : if (!model)
115 0 : return;
116 :
117 : /* Clear old signature to ensure users don't get confused on error with an old signature displayed */
118 0 : ui->signatureOut_SM->clear();
119 :
120 0 : CBitcoinAddress addr(ui->addressIn_SM->text().toStdString());
121 0 : if (!addr.IsValid())
122 : {
123 0 : ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
124 0 : ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
125 0 : return;
126 : }
127 : CKeyID keyID;
128 0 : if (!addr.GetKeyID(keyID))
129 : {
130 0 : ui->addressIn_SM->setValid(false);
131 0 : ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
132 0 : ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
133 0 : return;
134 : }
135 :
136 0 : WalletModel::UnlockContext ctx(model->requestUnlock());
137 0 : if (!ctx.isValid())
138 : {
139 0 : ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
140 0 : ui->statusLabel_SM->setText(tr("Wallet unlock was cancelled."));
141 0 : return;
142 : }
143 :
144 : CKey key;
145 0 : if (!pwalletMain->GetKey(keyID, key))
146 : {
147 0 : ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
148 0 : ui->statusLabel_SM->setText(tr("Private key for the entered address is not available."));
149 0 : return;
150 : }
151 :
152 : CHashWriter ss(SER_GETHASH, 0);
153 : ss << strMessageMagic;
154 0 : ss << ui->messageIn_SM->document()->toPlainText().toStdString();
155 :
156 : std::vector<unsigned char> vchSig;
157 0 : if (!key.SignCompact(ss.GetHash(), vchSig))
158 : {
159 0 : ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
160 0 : ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signing failed.") + QString("</nobr>"));
161 : return;
162 : }
163 :
164 0 : ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
165 0 : ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>"));
166 :
167 0 : ui->signatureOut_SM->setText(QString::fromStdString(EncodeBase64(&vchSig[0], vchSig.size())));
168 : }
169 :
170 0 : void SignVerifyMessageDialog::on_copySignatureButton_SM_clicked()
171 : {
172 0 : GUIUtil::setClipboard(ui->signatureOut_SM->text());
173 0 : }
174 :
175 0 : void SignVerifyMessageDialog::on_clearButton_SM_clicked()
176 : {
177 0 : ui->addressIn_SM->clear();
178 0 : ui->messageIn_SM->clear();
179 0 : ui->signatureOut_SM->clear();
180 0 : ui->statusLabel_SM->clear();
181 :
182 0 : ui->addressIn_SM->setFocus();
183 0 : }
184 :
185 0 : void SignVerifyMessageDialog::on_addressBookButton_VM_clicked()
186 : {
187 0 : if (model && model->getAddressTableModel())
188 : {
189 0 : AddressBookPage dlg(platformStyle, AddressBookPage::ForSelection, AddressBookPage::SendingTab, this);
190 0 : dlg.setModel(model->getAddressTableModel());
191 0 : if (dlg.exec())
192 : {
193 0 : setAddress_VM(dlg.getReturnValue());
194 0 : }
195 : }
196 0 : }
197 :
198 0 : void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
199 : {
200 0 : CBitcoinAddress addr(ui->addressIn_VM->text().toStdString());
201 0 : if (!addr.IsValid())
202 : {
203 0 : ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
204 0 : ui->statusLabel_VM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
205 0 : return;
206 : }
207 : CKeyID keyID;
208 0 : if (!addr.GetKeyID(keyID))
209 : {
210 0 : ui->addressIn_VM->setValid(false);
211 0 : ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
212 0 : ui->statusLabel_VM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
213 0 : return;
214 : }
215 :
216 0 : bool fInvalid = false;
217 0 : std::vector<unsigned char> vchSig = DecodeBase64(ui->signatureIn_VM->text().toStdString().c_str(), &fInvalid);
218 :
219 0 : if (fInvalid)
220 : {
221 0 : ui->signatureIn_VM->setValid(false);
222 0 : ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
223 0 : ui->statusLabel_VM->setText(tr("The signature could not be decoded.") + QString(" ") + tr("Please check the signature and try again."));
224 0 : return;
225 : }
226 :
227 : CHashWriter ss(SER_GETHASH, 0);
228 : ss << strMessageMagic;
229 0 : ss << ui->messageIn_VM->document()->toPlainText().toStdString();
230 :
231 : CPubKey pubkey;
232 0 : if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
233 : {
234 0 : ui->signatureIn_VM->setValid(false);
235 0 : ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
236 0 : ui->statusLabel_VM->setText(tr("The signature did not match the message digest.") + QString(" ") + tr("Please check the signature and try again."));
237 0 : return;
238 : }
239 :
240 0 : if (!(CBitcoinAddress(pubkey.GetID()) == addr))
241 : {
242 0 : ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
243 0 : ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>"));
244 0 : return;
245 : }
246 :
247 0 : ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }");
248 0 : ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verified.") + QString("</nobr>"));
249 : }
250 :
251 0 : void SignVerifyMessageDialog::on_clearButton_VM_clicked()
252 : {
253 0 : ui->addressIn_VM->clear();
254 0 : ui->signatureIn_VM->clear();
255 0 : ui->messageIn_VM->clear();
256 0 : ui->statusLabel_VM->clear();
257 :
258 0 : ui->addressIn_VM->setFocus();
259 0 : }
260 :
261 0 : bool SignVerifyMessageDialog::eventFilter(QObject *object, QEvent *event)
262 : {
263 0 : if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::FocusIn)
264 : {
265 0 : if (ui->tabWidget->currentIndex() == 0)
266 : {
267 : /* Clear status message on focus change */
268 0 : ui->statusLabel_SM->clear();
269 :
270 : /* Select generated signature */
271 0 : if (object == ui->signatureOut_SM)
272 : {
273 0 : ui->signatureOut_SM->selectAll();
274 0 : return true;
275 : }
276 : }
277 0 : else if (ui->tabWidget->currentIndex() == 1)
278 : {
279 : /* Clear status message on focus change */
280 0 : ui->statusLabel_VM->clear();
281 : }
282 : }
283 0 : return QDialog::eventFilter(object, event);
284 0 : }
|