Bitcoin Core  0.19.99
P2P Digital Currency
signverifymessagedialog.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2019 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 <vector>
18 
19 #include <QClipboard>
20 
21 SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
22  QDialog(parent),
23  ui(new Ui::SignVerifyMessageDialog),
24  model(nullptr),
25  platformStyle(_platformStyle)
26 {
27  ui->setupUi(this);
28 
29  ui->addressBookButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
30  ui->pasteButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editpaste"));
31  ui->copySignatureButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editcopy"));
32  ui->signMessageButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/edit"));
33  ui->clearButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
34  ui->addressBookButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
35  ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/transaction_0"));
36  ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
37 
38  GUIUtil::setupAddressWidget(ui->addressIn_SM, this);
39  GUIUtil::setupAddressWidget(ui->addressIn_VM, this);
40 
41  ui->addressIn_SM->installEventFilter(this);
42  ui->messageIn_SM->installEventFilter(this);
43  ui->signatureOut_SM->installEventFilter(this);
44  ui->addressIn_VM->installEventFilter(this);
45  ui->messageIn_VM->installEventFilter(this);
46  ui->signatureIn_VM->installEventFilter(this);
47 
48  ui->signatureOut_SM->setFont(GUIUtil::fixedPitchFont());
49  ui->signatureIn_VM->setFont(GUIUtil::fixedPitchFont());
50 }
51 
53 {
54  delete ui;
55 }
56 
58 {
59  this->model = _model;
60 }
61 
62 void SignVerifyMessageDialog::setAddress_SM(const QString &address)
63 {
64  ui->addressIn_SM->setText(address);
65  ui->messageIn_SM->setFocus();
66 }
67 
68 void SignVerifyMessageDialog::setAddress_VM(const QString &address)
69 {
70  ui->addressIn_VM->setText(address);
71  ui->messageIn_VM->setFocus();
72 }
73 
75 {
76  ui->tabWidget->setCurrentIndex(0);
77  if (fShow)
78  this->show();
79 }
80 
82 {
83  ui->tabWidget->setCurrentIndex(1);
84  if (fShow)
85  this->show();
86 }
87 
89 {
91  {
94  if (dlg.exec())
95  {
97  }
98  }
99 }
100 
102 {
103  setAddress_SM(QApplication::clipboard()->text());
104 }
105 
107 {
108  if (!model)
109  return;
110 
111  /* Clear old signature to ensure users don't get confused on error with an old signature displayed */
112  ui->signatureOut_SM->clear();
113 
114  CTxDestination destination = DecodeDestination(ui->addressIn_SM->text().toStdString());
115  if (!IsValidDestination(destination)) {
116  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
117  ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
118  return;
119  }
120  const PKHash* pkhash = boost::get<PKHash>(&destination);
121  if (!pkhash) {
122  ui->addressIn_SM->setValid(false);
123  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
124  ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
125  return;
126  }
127 
129  if (!ctx.isValid())
130  {
131  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
132  ui->statusLabel_SM->setText(tr("Wallet unlock was cancelled."));
133  return;
134  }
135 
136  CKey key;
137  if (!model->wallet().getPrivKey(GetScriptForDestination(destination), CKeyID(*pkhash), key))
138  {
139  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
140  ui->statusLabel_SM->setText(tr("Private key for the entered address is not available."));
141  return;
142  }
143 
144  CHashWriter ss(SER_GETHASH, 0);
145  ss << strMessageMagic;
146  ss << ui->messageIn_SM->document()->toPlainText().toStdString();
147 
148  std::vector<unsigned char> vchSig;
149  if (!key.SignCompact(ss.GetHash(), vchSig))
150  {
151  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
152  ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signing failed.") + QString("</nobr>"));
153  return;
154  }
155 
156  ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
157  ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>"));
158 
159  ui->signatureOut_SM->setText(QString::fromStdString(EncodeBase64(vchSig.data(), vchSig.size())));
160 }
161 
163 {
164  GUIUtil::setClipboard(ui->signatureOut_SM->text());
165 }
166 
168 {
169  ui->addressIn_SM->clear();
170  ui->messageIn_SM->clear();
171  ui->signatureOut_SM->clear();
172  ui->statusLabel_SM->clear();
173 
174  ui->addressIn_SM->setFocus();
175 }
176 
178 {
179  if (model && model->getAddressTableModel())
180  {
183  if (dlg.exec())
184  {
186  }
187  }
188 }
189 
191 {
192  CTxDestination destination = DecodeDestination(ui->addressIn_VM->text().toStdString());
193  if (!IsValidDestination(destination)) {
194  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
195  ui->statusLabel_VM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
196  return;
197  }
198  if (!boost::get<PKHash>(&destination)) {
199  ui->addressIn_VM->setValid(false);
200  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
201  ui->statusLabel_VM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
202  return;
203  }
204 
205  bool fInvalid = false;
206  std::vector<unsigned char> vchSig = DecodeBase64(ui->signatureIn_VM->text().toStdString().c_str(), &fInvalid);
207 
208  if (fInvalid)
209  {
210  ui->signatureIn_VM->setValid(false);
211  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
212  ui->statusLabel_VM->setText(tr("The signature could not be decoded.") + QString(" ") + tr("Please check the signature and try again."));
213  return;
214  }
215 
216  CHashWriter ss(SER_GETHASH, 0);
217  ss << strMessageMagic;
218  ss << ui->messageIn_VM->document()->toPlainText().toStdString();
219 
220  CPubKey pubkey;
221  if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
222  {
223  ui->signatureIn_VM->setValid(false);
224  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
225  ui->statusLabel_VM->setText(tr("The signature did not match the message digest.") + QString(" ") + tr("Please check the signature and try again."));
226  return;
227  }
228 
229  if (!(CTxDestination(PKHash(pubkey)) == destination)) {
230  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
231  ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>"));
232  return;
233  }
234 
235  ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }");
236  ui->statusLabel_VM->setText(QString("<nobr>") + tr("Message verified.") + QString("</nobr>"));
237 }
238 
240 {
241  ui->addressIn_VM->clear();
242  ui->signatureIn_VM->clear();
243  ui->messageIn_VM->clear();
244  ui->statusLabel_VM->clear();
245 
246  ui->addressIn_VM->setFocus();
247 }
248 
249 bool SignVerifyMessageDialog::eventFilter(QObject *object, QEvent *event)
250 {
251  if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::FocusIn)
252  {
253  if (ui->tabWidget->currentIndex() == 0)
254  {
255  /* Clear status message on focus change */
256  ui->statusLabel_SM->clear();
257 
258  /* Select generated signature */
259  if (object == ui->signatureOut_SM)
260  {
261  ui->signatureOut_SM->selectAll();
262  return true;
263  }
264  }
265  else if (ui->tabWidget->currentIndex() == 1)
266  {
267  /* Clear status message on focus change */
268  ui->statusLabel_VM->clear();
269  }
270  }
271  return QDialog::eventFilter(object, event);
272 }
bool eventFilter(QObject *object, QEvent *event)
interfaces::Wallet & wallet() const
Definition: walletmodel.h:147
QFont fixedPitchFont()
Definition: guiutil.cpp:81
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:104
void setClipboard(const QString &str)
Definition: guiutil.cpp:704
bool RecoverCompact(const uint256 &hash, const std::vector< unsigned char > &vchSig)
Recover a public key from a compact signature.
Definition: pubkey.cpp:187
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
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:289
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:215
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:50
const std::string strMessageMagic
Definition: validation.cpp:25
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:20
virtual bool getPrivKey(const CScript &script, const CKeyID &address, CKey &key)=0
Get private key.
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:143
void setModel(WalletModel *model)
const QString & getReturnValue() const
void setAddress_SM(const QString &address)