Bitcoin Core  0.18.99
P2P Digital Currency
signverifymessagedialog.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2018 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 
6 #include <qt/forms/ui_signverifymessagedialog.h>
7 
8 #include <qt/addressbookpage.h>
9 #include <qt/guiutil.h>
10 #include <qt/platformstyle.h>
11 #include <qt/walletmodel.h>
12 
13 #include <key_io.h>
14 #include <util/validation.h> // For strMessageMagic
15 #include <wallet/wallet.h>
16 
17 #include <string>
18 #include <vector>
19 
20 #include <QClipboard>
21 
22 SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
23  QDialog(parent),
24  ui(new Ui::SignVerifyMessageDialog),
25  model(nullptr),
26  platformStyle(_platformStyle)
27 {
28  ui->setupUi(this);
29 
30  ui->addressBookButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
31  ui->pasteButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editpaste"));
32  ui->copySignatureButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editcopy"));
33  ui->signMessageButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/edit"));
34  ui->clearButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
35  ui->addressBookButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
36  ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/transaction_0"));
37  ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
38 
39  ui->signatureOut_SM->setPlaceholderText(tr("Click \"Sign Message\" to generate signature"));
40 
41  GUIUtil::setupAddressWidget(ui->addressIn_SM, this);
42  GUIUtil::setupAddressWidget(ui->addressIn_VM, this);
43 
44  ui->addressIn_SM->installEventFilter(this);
45  ui->messageIn_SM->installEventFilter(this);
46  ui->signatureOut_SM->installEventFilter(this);
47  ui->addressIn_VM->installEventFilter(this);
48  ui->messageIn_VM->installEventFilter(this);
49  ui->signatureIn_VM->installEventFilter(this);
50 
51  ui->signatureOut_SM->setFont(GUIUtil::fixedPitchFont());
52  ui->signatureIn_VM->setFont(GUIUtil::fixedPitchFont());
53 }
54 
56 {
57  delete ui;
58 }
59 
61 {
62  this->model = _model;
63 }
64 
65 void SignVerifyMessageDialog::setAddress_SM(const QString &address)
66 {
67  ui->addressIn_SM->setText(address);
68  ui->messageIn_SM->setFocus();
69 }
70 
71 void SignVerifyMessageDialog::setAddress_VM(const QString &address)
72 {
73  ui->addressIn_VM->setText(address);
74  ui->messageIn_VM->setFocus();
75 }
76 
78 {
79  ui->tabWidget->setCurrentIndex(0);
80  if (fShow)
81  this->show();
82 }
83 
85 {
86  ui->tabWidget->setCurrentIndex(1);
87  if (fShow)
88  this->show();
89 }
90 
92 {
94  {
97  if (dlg.exec())
98  {
100  }
101  }
102 }
103 
105 {
106  setAddress_SM(QApplication::clipboard()->text());
107 }
108 
110 {
111  if (!model)
112  return;
113 
114  /* Clear old signature to ensure users don't get confused on error with an old signature displayed */
115  ui->signatureOut_SM->clear();
116 
117  CTxDestination destination = DecodeDestination(ui->addressIn_SM->text().toStdString());
118  if (!IsValidDestination(destination)) {
119  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
120  ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
121  return;
122  }
123  const PKHash* pkhash = boost::get<PKHash>(&destination);
124  if (!pkhash) {
125  ui->addressIn_SM->setValid(false);
126  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
127  ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
128  return;
129  }
130 
132  if (!ctx.isValid())
133  {
134  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
135  ui->statusLabel_SM->setText(tr("Wallet unlock was cancelled."));
136  return;
137  }
138 
139  CKey key;
140  if (!model->wallet().getPrivKey(CKeyID(*pkhash), key))
141  {
142  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
143  ui->statusLabel_SM->setText(tr("Private key for the entered address is not available."));
144  return;
145  }
146 
147  CHashWriter ss(SER_GETHASH, 0);
148  ss << strMessageMagic;
149  ss << ui->messageIn_SM->document()->toPlainText().toStdString();
150 
151  std::vector<unsigned char> vchSig;
152  if (!key.SignCompact(ss.GetHash(), vchSig))
153  {
154  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
155  ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signing failed.") + QString("</nobr>"));
156  return;
157  }
158 
159  ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
160  ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>"));
161 
162  ui->signatureOut_SM->setText(QString::fromStdString(EncodeBase64(vchSig.data(), vchSig.size())));
163 }
164 
166 {
167  GUIUtil::setClipboard(ui->signatureOut_SM->text());
168 }
169 
171 {
172  ui->addressIn_SM->clear();
173  ui->messageIn_SM->clear();
174  ui->signatureOut_SM->clear();
175  ui->statusLabel_SM->clear();
176 
177  ui->addressIn_SM->setFocus();
178 }
179 
181 {
182  if (model && model->getAddressTableModel())
183  {
186  if (dlg.exec())
187  {
189  }
190  }
191 }
192 
194 {
195  CTxDestination destination = DecodeDestination(ui->addressIn_VM->text().toStdString());
196  if (!IsValidDestination(destination)) {
197  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
198  ui->statusLabel_VM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
199  return;
200  }
201  if (!boost::get<PKHash>(&destination)) {
202  ui->addressIn_VM->setValid(false);
203  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
204  ui->statusLabel_VM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
205  return;
206  }
207 
208  bool fInvalid = false;
209  std::vector<unsigned char> vchSig = DecodeBase64(ui->signatureIn_VM->text().toStdString().c_str(), &fInvalid);
210 
211  if (fInvalid)
212  {
213  ui->signatureIn_VM->setValid(false);
214  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
215  ui->statusLabel_VM->setText(tr("The signature could not be decoded.") + QString(" ") + tr("Please check the signature and try again."));
216  return;
217  }
218 
219  CHashWriter ss(SER_GETHASH, 0);
220  ss << strMessageMagic;
221  ss << ui->messageIn_VM->document()->toPlainText().toStdString();
222 
223  CPubKey pubkey;
224  if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
225  {
226  ui->signatureIn_VM->setValid(false);
227  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
228  ui->statusLabel_VM->setText(tr("The signature did not match the message digest.") + QString(" ") + tr("Please check the signature and try again."));
229  return;
230  }
231 
232  if (!(CTxDestination(PKHash(pubkey)) == destination)) {
233  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
234  ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>"));
235  return;
236  }
237 
238  ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }");
239  ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verified.") + QString("</nobr>"));
240 }
241 
243 {
244  ui->addressIn_VM->clear();
245  ui->signatureIn_VM->clear();
246  ui->messageIn_VM->clear();
247  ui->statusLabel_VM->clear();
248 
249  ui->addressIn_VM->setFocus();
250 }
251 
252 bool SignVerifyMessageDialog::eventFilter(QObject *object, QEvent *event)
253 {
254  if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::FocusIn)
255  {
256  if (ui->tabWidget->currentIndex() == 0)
257  {
258  /* Clear status message on focus change */
259  ui->statusLabel_SM->clear();
260 
261  /* Select generated signature */
262  if (object == ui->signatureOut_SM)
263  {
264  ui->signatureOut_SM->selectAll();
265  return true;
266  }
267  }
268  else if (ui->tabWidget->currentIndex() == 1)
269  {
270  /* Clear status message on focus change */
271  ui->statusLabel_VM->clear();
272  }
273  }
274  return QDialog::eventFilter(object, event);
275 }
bool eventFilter(QObject *object, QEvent *event)
interfaces::Wallet & wallet() const
Definition: walletmodel.h:223
QFont fixedPitchFont()
Definition: guiutil.cpp:78
void setAddress_VM(const QString &address)
void setModel(AddressTableModel *model)
UnlockContext requestUnlock()
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:325
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
std::vector< unsigned char > DecodeBase64(const char *p, bool *pf_invalid)
Open address book to pick address.
AddressTableModel * getAddressTableModel()
Ui::SignVerifyMessageDialog * ui
bool SignCompact(const uint256 &hash, std::vector< unsigned char > &vchSig) const
Create a compact signature (65 bytes), which allows reconstructing the used public key...
Definition: key.cpp:246
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
Definition: guiutil.cpp:101
void setClipboard(const QString &str)
Definition: guiutil.cpp:785
bool RecoverCompact(const uint256 &hash, const std::vector< unsigned char > &vchSig)
Recover a public key from a compact signature.
Definition: pubkey.cpp:186
static secp256k1_context * ctx
Definition: tests.c:46
std::string EncodeBase64(const unsigned char *pch, size_t len)
An encapsulated public key.
Definition: pubkey.h:30
Widget that shows a list of sending or receiving addresses.
SignVerifyMessageDialog(const PlatformStyle *platformStyle, QWidget *parent)
uint256 GetHash()
Definition: hash.h:136
CTxDestination DecodeDestination(const std::string &str)
Definition: key_io.cpp:216
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:125
const std::string strMessageMagic
Definition: validation.cpp:20
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:20
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:117
An encapsulated private key.
Definition: key.h:27
const PlatformStyle * platformStyle
boost::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:139
void setModel(WalletModel *model)
virtual bool getPrivKey(const CKeyID &address, CKey &key)=0
Get private key.
const QString & getReturnValue() const
void setAddress_SM(const QString &address)