cipher: Fix build option and use a dialog for entering the password

Fix the sqlcipher build option in the qmake project to actually enable
the SQLCipher support.

Add a new dialog called CipherDialog which is used to ask the user for
the password and other encryption details instead of using standard Qt
input dialogs.
This commit is contained in:
Martin Kleusberg
2014-11-02 13:12:31 +01:00
parent 9ba36d02b2
commit 167d8cbd74
8 changed files with 265 additions and 21 deletions

View File

@@ -30,6 +30,7 @@ set(SQLB_HDR
src/gen_version.h
src/sqlitetypes.h
src/csvparser.h
src/sqlite.h
src/grammar/sqlite3TokenTypes.hpp
src/grammar/Sqlite3Lexer.hpp
src/grammar/Sqlite3Parser.hpp
@@ -54,7 +55,7 @@ set(SQLB_MOC_HDR
src/sqltextedit.h
src/DbStructureModel.h
src/Application.h
src/sqlite.h
src/CipherDialog.h
)
set(SQLB_SRC
@@ -81,6 +82,7 @@ set(SQLB_SRC
src/grammar/Sqlite3Parser.cpp
src/main.cpp
src/Application.cpp
src/CipherDialog.cpp
)
set(SQLB_FORMS
@@ -94,6 +96,7 @@ set(SQLB_FORMS
src/PreferencesDialog.ui
src/SqlExecutionArea.ui
src/VacuumDialog.ui
src/CipherDialog.ui
)
set(SQLB_RESOURCES
@@ -182,7 +185,7 @@ endif(APPLE)
# SQLCipher option
if(sqlcipher)
add_definitions(-DSQLCIPHER)
add_definitions(-DENABLE_SQLCIPHER)
set(LIBSQLITE_NAME sqlcipher)
else(sqlcipher)
set(LIBSQLITE_NAME sqlite3)

View File

@@ -12,7 +12,7 @@ AboutDialog::AboutDialog(QWidget *parent) :
ui->label_version->setText(ui->label_version->text() + " " + APP_VERSION);
ui->label_versionqt->setText(ui->label_versionqt->text() + " " + QT_VERSION_STR);
#ifdef SQLCIPHER
#ifdef ENABLE_SQLCIPHER
ui->label_versionsqlite->setText(ui->label_versionsqlite->text().replace("SQLite", "SQLCipher") + " " + SQLITE_VERSION);
#else
ui->label_versionsqlite->setText(ui->label_versionsqlite->text() + " " + SQLITE_VERSION);

47
src/CipherDialog.cpp Normal file
View File

@@ -0,0 +1,47 @@
#include "CipherDialog.h"
#include "ui_CipherDialog.h"
#include <QPushButton>
CipherDialog::CipherDialog(QWidget* parent, bool encrypt) :
QDialog(parent),
ui(new Ui::CipherDialog),
encryptMode(encrypt)
{
ui->setupUi(this);
if(encrypt)
{
ui->labelDialogDescription->setText(tr("Please set a key to encrypt the database.\nNote that if you change any of the other, optional, settings you'll need "
"to re-enter them as well every time you open the database file."));
} else {
ui->labelDialogDescription->setText(tr("Please enter the key used to encrypt the database.\nIf any of the other setting were altered for this database file "
"you need to provide this information as well."));
ui->editPassword2->setVisible(false);
ui->labelPassword2->setVisible(false);
}
}
CipherDialog::~CipherDialog()
{
delete ui;
}
QString CipherDialog::password()
{
return ui->editPassword->text();
}
int CipherDialog::pageSize()
{
return ui->spinPageSize->value();
}
void CipherDialog::checkInputFields()
{
bool valid = true;
if(encryptMode)
valid = ui->editPassword->text() == ui->editPassword2->text();
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid);
}

32
src/CipherDialog.h Normal file
View File

@@ -0,0 +1,32 @@
#ifndef CIPHERDIALOG_H
#define CIPHERDIALOG_H
#include <QDialog>
namespace Ui {
class CipherDialog;
}
class CipherDialog : public QDialog
{
Q_OBJECT
public:
// Set the encrypt parameter to true when the dialog is used to encrypt a database;
// set it to false if the dialog is used to ask the user for the key to decrypt a file.
explicit CipherDialog(QWidget* parent, bool encrypt);
~CipherDialog();
// Allow read access tothe input fields
QString password();
int pageSize();
private:
Ui::CipherDialog* ui;
bool encryptMode;
private slots:
void checkInputFields();
};
#endif

166
src/CipherDialog.ui Normal file
View File

@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CipherDialog</class>
<widget class="QDialog" name="CipherDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>475</width>
<height>147</height>
</rect>
</property>
<property name="windowTitle">
<string>SQLCipher encryption</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="labelDialogDescription"/>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="labelPassword">
<property name="text">
<string>&amp;Password</string>
</property>
<property name="buddy">
<cstring>editPassword</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="editPassword">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelPassword2">
<property name="text">
<string>&amp;Reenter password</string>
</property>
<property name="buddy">
<cstring>editPassword2</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="editPassword2">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Page &amp;size</string>
</property>
<property name="buddy">
<cstring>spinPageSize</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="spinPageSize">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>8092</number>
</property>
<property name="value">
<number>4096</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>CipherDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>227</x>
<y>110</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>126</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>CipherDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>295</x>
<y>116</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>126</y>
</hint>
</hints>
</connection>
<connection>
<sender>editPassword</sender>
<signal>textChanged(QString)</signal>
<receiver>CipherDialog</receiver>
<slot>checkInputFields()</slot>
<hints>
<hint type="sourcelabel">
<x>150</x>
<y>38</y>
</hint>
<hint type="destinationlabel">
<x>155</x>
<y>26</y>
</hint>
</hints>
</connection>
<connection>
<sender>editPassword2</sender>
<signal>textChanged(QString)</signal>
<receiver>CipherDialog</receiver>
<slot>checkInputFields()</slot>
<hints>
<hint type="sourcelabel">
<x>201</x>
<y>57</y>
</hint>
<hint type="destinationlabel">
<x>206</x>
<y>46</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>checkInputFields()</slot>
</slots>
</ui>

View File

@@ -1,7 +1,7 @@
#ifndef SQLITE_H
#define SQLITE_H
#ifdef SQLCIPHER
#ifdef ENABLE_SQLCIPHER
#define SQLITE_TEMP_STORE 2
#define SQLITE_HAS_CODEC
#include <sqlcipher/sqlite3.h>

View File

@@ -1,6 +1,7 @@
#include "sqlitedb.h"
#include "sqlitetablemodel.h"
#include "sqlite.h"
#include "CipherDialog.h"
#include <QFile>
#include <QMessageBox>
@@ -71,24 +72,16 @@ bool DBBrowserDB::open(const QString& db)
err = sqlite3_prepare_v2(_db, utf8Statement, utf8Statement.length(), &vm, &tail);
if(sqlite3_step(vm) != SQLITE_ROW)
{
#ifdef SQLCIPHER
QString pass = QInputDialog::getText(0, qApp->applicationName(),
QObject::tr("Couldn't read from database file. This means it is either not a valid SQLite3 "
"database or it is encrypted.\nIn the latter case you can provide a passphrase to open the file. Note"
"that only databases encrypted using SQLCipher are supported."));
if(pass.isEmpty())
#ifdef ENABLE_SQLCIPHER
CipherDialog cipher(0, false);
if(cipher.exec())
{
sqlite3_key(_db, cipher.password().toUtf8(), cipher.password().toUtf8().length());
sqlite3_exec(_db, QString("PRAGMA cipher_page_size = %1;").arg(cipher.pageSize()).toUtf8(), NULL, NULL, NULL);
} else {
sqlite3_close(_db);
_db = 0;
return false;
} else {
int pagesize = QInputDialog::getInt(0, qApp->applicationName(),
QObject::tr("If the database has been encrypted using a different page size than normally (i.e. 1024 bytes) this "
"value is required, too."),
1024, 0);
if(pagesize == 0) pagesize = 1024;
sqlite3_key(_db, pass.toUtf8(), pass.toUtf8().length());
sqlite3_exec(_db, QString("PRAGMA cipher_page_size = %1;").arg(pagesize).toUtf8(), NULL, NULL, NULL);
}
#else
sqlite3_close(_db);

View File

@@ -43,7 +43,8 @@ HEADERS += \
VacuumDialog.h \
DbStructureModel.h \
Application.h \
sqlite.h
sqlite.h \
CipherDialog.h
SOURCES += \
sqlitedb.cpp \
@@ -67,7 +68,8 @@ SOURCES += \
SqlExecutionArea.cpp \
VacuumDialog.cpp \
DbStructureModel.cpp \
Application.cpp
Application.cpp \
CipherDialog.cpp
RESOURCES += icons/icons.qrc
@@ -81,7 +83,8 @@ FORMS += \
ExportCsvDialog.ui \
ImportCsvDialog.ui \
SqlExecutionArea.ui \
VacuumDialog.ui
VacuumDialog.ui \
CipherDialog.ui
TRANSLATIONS += \
translations/sqlb_cn.ts \