Paper wallet for Hush, which you can use with no internet access while wearing a tinfoil hat inside of a Faraday cage. https://hush.is
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

211 lines
6.5 KiB

// Copyright (c) 2016-2020 The Hush developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
#include <cstring>
#include "precompiled.h"
#include "mainwindow.h"
#include "version.h"
#include "ui_mainwindow.h"
#include "ui_wallet.h"
#include "ui_about.h"
#include "hushpaperrust.h"
void SaveRestore(QDialog* d) {
d->restoreGeometry(QSettings().value(d->objectName() % "geometry").toByteArray());
QObject::connect(d, &QDialog::finished, [=](auto) {
QSettings().setValue(d->objectName() % "geometry", d->saveGeometry());
});
}
QString SplitIntoLines(QString s, int maxlen) {
if (s.length() <= maxlen)
return s;
QStringList ans;
int start = 0;
for (int i=0; i < (s.length() / maxlen) + 1; i++) {
ans << s.mid(start, maxlen);
start += maxlen;
}
return ans.join("\n");
}
// Add a wallet (address + pk) section to the given vertical layout
void AddWallet(QString address, QString pk, QWidget* scroll) {
Ui_WalletWidget w;
auto g1 = new QGroupBox(scroll);
w.setupUi(g1);
scroll->layout()->addWidget(g1);
// Setup fixed with fonts
//const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
w.qrAddress->setQrcodeString(address);
w.lblAddress->setText(SplitIntoLines(address, 39));
//w.lblAddress->setFont(fixedFont);
w.qrPrivateKey->setQrcodeString(pk);
w.lblPrivateKey->setText(SplitIntoLines(pk, 59));
//w.lblPrivateKey->setFont(fixedFont);
}
/**
* Generate wallets and return a JSON.
*/
QString Generate(int zaddrs, int taddrs, QString entropy) {
// Call into rust to get the addresses
char* wallet = rust_generate_wallet(false, zaddrs, taddrs, entropy.toStdString().c_str());
QString walletJson(wallet);
// We'll overwrite the privatekeys for safety before sending it back to rust
std::memset(wallet, 0xFF, strlen(wallet));
rust_free_string(wallet);
return walletJson;
}
void MainWindow::populateWallets() {
// First, get the numbers
int zaddrs = ui->txtzaddrs->text().toInt();
int taddrs = ui->txttaddrs->text().toInt();
QString entropy = ui->txtEntropy->text();
currentWallets = Generate(zaddrs, taddrs, entropy);
// Then, clear the Scroll area
auto children = ui->scroll->findChildren<QGroupBox *>();
for (int i=0; i < children.length(); i++) {
delete children[i];
}
// Then add the new wallets
auto json = QJsonDocument::fromJson(currentWallets.toUtf8());
for (int i=0; i < json.array().size(); i++) {
auto addr = json.array()[i].toObject()["address"].toString();
auto pk = json.array()[i].toObject()["private_key"].toString();
AddWallet(addr, pk, ui->scroll);
}
}
void MainWindow::SaveAsPDFButton() {
// If there's nothing to save, just exit
if (currentWallets.isEmpty())
return;
// Get a save file name
auto filename = QFileDialog::getSaveFileName(this, tr("Save as PDF"), "", tr("PDF Files (*.pdf)"));
if (!filename.isEmpty()) {
if (!filename.endsWith(".pdf"))
filename = filename + ".pdf";
bool success = rust_save_as_pdf(false, this->currentWallets.toStdString().c_str(), filename.toStdString().c_str());
if (success) {
QMessageBox::information(this, tr("Saved!"), tr("The wallets were saved to ") + filename);
} else {
QMessageBox::warning(this, tr("Failed to save file"),
tr("Couldn't save the file for some unknown reason"));
}
}
}
void MainWindow::SaveAsJSONButton() {
// If there's nothing to save, just exit
if (currentWallets.isEmpty())
return;
auto filename = QFileDialog::getSaveFileName(this, tr("Save as text"), "", tr("Text Files (*.txt)"));
if (!filename.isEmpty()) {
if (!filename.endsWith(".txt"))
filename = filename + ".txt";
QFile file(filename);
if (file.open(QIODevice::WriteOnly))
{
QTextStream stream(&file);
stream << this->currentWallets << endl;
QMessageBox::information(this, tr("Saved!"), tr("The wallets were saved to ") + filename);
} else {
QMessageBox::warning(this, tr("Failed to save file"),
tr("Couldn't save the file for some unknown reason"));
}
}
}
void MainWindow::closeEvent(QCloseEvent*) {
QSettings().setValue("geometry", saveGeometry());
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Save the geometry
restoreGeometry(QSettings().value("geometry").toByteArray());
// First, set up the validators for the number fields
intValidator = new QIntValidator(0, 25);
ui->txttaddrs->setValidator(intValidator);
ui->txtzaddrs->setValidator(intValidator);
QString entropyTooltip = tr("Please type in random characters to use as entropy, which will be mixed in with the system's entropy to generate random numbers.");
ui->txtEntropy->setToolTip(entropyTooltip);
ui->lblEntropy->setToolTip(entropyTooltip);
// Wire up the generate button
QObject::connect(ui->btnGenerate, &QPushButton::clicked, [=]() {
this->populateWallets();
});
// Close button
QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close);
// Help site
QObject::connect(ui->actionHelp_site, &QAction::triggered, [=]() {
QDesktopServices::openUrl(QUrl("https://faq.hush.is/sdp"));
});
// About button
QObject::connect(ui->actionAbout, &QAction::triggered, [=]() {
QDialog ad(this);
Ui_AboutDialog d;
d.setupUi(&ad);
d.lblVersion->setText(QString("SilentDragonPaper ") + APP_VERSION + "(" + APP_BUILD_DATE + ")");
SaveRestore(&ad);
ad.exec();
});
// Save as PDF
// Button
QObject::connect(ui->btnSavePDF, &QPushButton::clicked, [=]() {
SaveAsPDFButton();
});
// Menu item
QObject::connect(ui->actionSave_as_PDF, &QAction::triggered, this, &MainWindow::SaveAsPDFButton);
// Save as JSON
QObject::connect(ui->btnSaveJSON, &QPushButton::clicked, [=]() {
SaveAsJSONButton();
});
// Menu item
QObject::connect(ui->actionSave_as_JSON, &QAction::triggered, this, &MainWindow::SaveAsJSONButton);
// Generate the default wallets
populateWallets();
}
MainWindow::~MainWindow()
{
delete ui;
delete intValidator;
}