From ff5399ba3100587ca55b392f85e6b52d89c44969 Mon Sep 17 00:00:00 2001 From: Aslan2142 Date: Wed, 26 Feb 2020 21:15:11 +0100 Subject: [PATCH] Version 1.0.0 --- PKGBUILD_amd64 | 20 ++ PKGBUILD_arm64 | 20 ++ README.md | 25 ++ control_amd64 | 9 + control_arm64 | 9 + main.cpp | 103 ++++++++ mainwindow.cpp | 257 ++++++++++++++++++++ mainwindow.h | 48 ++++ mainwindow.ui | 312 +++++++++++++++++++++++++ makearchpkg.sh | 10 + makedebpkg.sh | 24 ++ parameterparser.cpp | 57 +++++ parameterparser.h | 19 ++ passman-1.0.0.tar.xz.txt | 1 + passman.cpp | 175 ++++++++++++++ passman.desktop | 19 ++ passman.h | 53 +++++ passman.pro | 50 ++++ passman_icon.svg | 83 +++++++ qaesencryption.cpp | 492 +++++++++++++++++++++++++++++++++++++++ qaesencryption.h | 154 ++++++++++++ resources.qrc | 5 + 22 files changed, 1945 insertions(+) create mode 100644 PKGBUILD_amd64 create mode 100644 PKGBUILD_arm64 create mode 100644 README.md create mode 100644 control_amd64 create mode 100644 control_arm64 create mode 100644 main.cpp create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h create mode 100644 mainwindow.ui create mode 100644 makearchpkg.sh create mode 100644 makedebpkg.sh create mode 100644 parameterparser.cpp create mode 100644 parameterparser.h create mode 100644 passman-1.0.0.tar.xz.txt create mode 100644 passman.cpp create mode 100755 passman.desktop create mode 100644 passman.h create mode 100644 passman.pro create mode 100644 passman_icon.svg create mode 100644 qaesencryption.cpp create mode 100644 qaesencryption.h create mode 100644 resources.qrc diff --git a/PKGBUILD_amd64 b/PKGBUILD_amd64 new file mode 100644 index 0000000..50228e7 --- /dev/null +++ b/PKGBUILD_amd64 @@ -0,0 +1,20 @@ +pkgname=passman +pkgver=1.0.0 +pkgrel=1 +pkgdesc="A Simple Password Manager with AES-256 Encryption" +arch=('x86_64') +license=('GPLv3') + +build() { + qmake .. + make +} + +package() { + mkdir -p $pkgdir/usr/bin + mkdir -p $pkgdir/usr/share/applications + mkdir -p $pkgdir/opt/aslan/icons + cp passman $pkgdir/usr/bin/passman + cp ../passman.desktop $pkgdir/usr/share/applications/passman.desktop + cp ../passman_icon.svg $pkgdir/opt/aslan/icons/passman_icon.svg +} diff --git a/PKGBUILD_arm64 b/PKGBUILD_arm64 new file mode 100644 index 0000000..298c832 --- /dev/null +++ b/PKGBUILD_arm64 @@ -0,0 +1,20 @@ +pkgname=passman +pkgver=1.0.0 +pkgrel=1 +pkgdesc="A Simple Password Manager with AES-256 Encryption" +arch=('aarch64') +license=('GPLv3') + +build() { + qmake .. + make +} + +package() { + mkdir -p $pkgdir/usr/bin + mkdir -p $pkgdir/usr/share/applications + mkdir -p $pkgdir/opt/aslan/icons + cp passman $pkgdir/usr/bin/passman + cp ../passman.desktop $pkgdir/usr/share/applications/passman.desktop + cp ../passman_icon.svg $pkgdir/opt/aslan/icons/passman_icon.svg +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..bbcf262 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# AsloEngine +A Simple Password Manager with AES-256 Encryption + +Version 1.0.0 + + +## How To Compile + +### Debian Linux: +Run **makedebpkg.sh** script with parameter (arm64/amd64) +This will make .deb package + +Example: **makedebpkg.sh amd64** + +### Arch Linux: +Run **makearchpkg.sh** script with parameter (arm64/amd64) +This will make .tar.xz package + +Example: **makearchpkg.sh amd64** + +### Windows: +Use QT Creator + +### Mac OS: +Use QT Creator diff --git a/control_amd64 b/control_amd64 new file mode 100644 index 0000000..0cb2d47 --- /dev/null +++ b/control_amd64 @@ -0,0 +1,9 @@ +Package: passman +Version: 1.0.0 +Section: utils +Priority: optional +Architecture: amd64 +Essential: no +Installed-Size: 132 +Maintainer: Aslan2142 +Description: A Simple Password Manager with AES-256 Encryption diff --git a/control_arm64 b/control_arm64 new file mode 100644 index 0000000..9dd9221 --- /dev/null +++ b/control_arm64 @@ -0,0 +1,9 @@ +Package: passman +Version: 1.0.0 +Section: utils +Priority: optional +Architecture: arm64 +Essential: no +Installed-Size: 132 +Maintainer: Aslan2142 +Description: A Simple Password Manager with AES-256 Encryption diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..66b54ac --- /dev/null +++ b/main.cpp @@ -0,0 +1,103 @@ +#include +#include +#include "mainwindow.h" +#include "passman.h" +#include "parameterparser.h" + +int main(int argc, char *argv[]) +{ + QString version = "1.0.0"; + + if (argc == 1) + { + QApplication a(argc, argv); + MainWindow w(version); + w.show(); + w.check_database(); + + return a.exec(); + } + + + + //Logic for CLI + + parameterparser parameter_parser(argc, argv); + passman password_manager; + + std::string password = parameter_parser.get_value("pass", 'p'); + if (password.compare("-") == 0) + { + std::cin >> password; + } + password_manager.key = QString::fromStdString(password); + + if (parameter_parser.has_parameter("create-database", 'd')) + { + if (password_manager.database_exists()) + { + std::cerr << "Error Creating Database (database already exists)" << std::endl; + return 4; + } + + if (password.length() > 0) + { + password_manager.encrypt(); + password_manager.save(); + } else { + std::cerr << "Error Creating Database (blank password)" << std::endl; + return 3; + } + } + + if (!password_manager.load()) + { + std::cerr << "Error Loading Database" << std::endl; + return 1; + } + if (!password_manager.decrypt()) + { + std::cerr << "Error Decrypting Database" << std::endl; + return 2; + } + + std::string new_entry = parameter_parser.get_value("new", 'n'); + if (new_entry.compare("-") != 0) + { + QStringList entry = QString::fromStdString(new_entry).split(","); + + password_manager.add_entry(entry[0], entry[1], entry[2], entry[3]); + password_manager.encrypt(); + password_manager.save(); + } + + if (parameter_parser.has_parameter("backup", 'b')) + { + password_manager.backup(); + } + + if (parameter_parser.has_parameter("show-all", 'a')) + { + const std::vector> database = password_manager.get_database_copy(); + for (const std::array& entry : database) + { + std::cout << "|| " << entry[0].toStdString() << " | " << entry[1].toStdString() << " | " << entry[2].toStdString() << " | " << entry[3].toStdString() << " ||" << std::endl; + } + } + + std::string show_website = parameter_parser.get_value("show", 's'); + if (show_website.compare("-") != 0) + { + const std::vector> database = password_manager.get_database_copy(); + for (const std::array& entry : database) + { + if (entry[0].toStdString().compare(show_website) != 0) + { + continue; + } + std::cout << "|| " << entry[0].toStdString() << " | " << entry[1].toStdString() << " | " << entry[2].toStdString() << " | " << entry[3].toStdString() << " ||" << std::endl; + } + } + + return 0; +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..68f95cd --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,257 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QString version, QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + setWindowTitle("PassMan v" + version); + + connect(ui->pushButtonUnlock, SIGNAL(clicked()), this, SLOT(decrypt_database())); + connect(ui->pushButtonBackup, SIGNAL(clicked()), this, SLOT(backup_database())); + connect(ui->pushButtonSave, SIGNAL(clicked()), this, SLOT(save_database())); + connect(ui->pushButtonAddEntry, SIGNAL(clicked()), this, SLOT(add_entry())); + connect(ui->pushButtonRemoveEntry, SIGNAL(clicked()), this, SLOT(remove_entry())); + connect(ui->pushButtonGeneratePassword, SIGNAL(clicked()), this, SLOT(generate_password())); + connect(ui->lineEditSearch, SIGNAL(textChanged(QString)), this, SLOT(search(QString))); + + ui->lineEditEncryptionKey->setFocus(); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::decrypt_database() +{ + //Load and Decrypt Database + password_manager.key = ui->lineEditEncryptionKey->text(); + + if (!password_manager.load()) + { + ui->labelDatabaseInfo->setText("Database could not be Loaded"); + ui->labelEncryptionInfo->setText(""); + return; + } + if (!password_manager.decrypt()) + { + ui->labelDatabaseInfo->setText("Database Loaded"); + ui->labelEncryptionInfo->setText("Database could not be Decrypted"); + return; + } + + ui->labelDatabaseInfo->setText("Database Loaded"); + ui->labelEncryptionInfo->setText("Database Decrypted"); + + //Fill up the Table + std::vector> database = password_manager.get_database_copy(); + + ui->tableWidgetCredentials->clear(); + ui->tableWidgetCredentials->setRowCount(static_cast(database.size())); + ui->tableWidgetCredentials->setColumnCount(4); + + for (ulong i = 0; i < database.size(); i++) + { + for (ulong j = 0; j < database[i].size(); j++) + { + ui->tableWidgetCredentials->setItem(static_cast(i), static_cast(j), new QTableWidgetItem(database[i][j])); + } + } + + saved = true; + + //Enable/Disable UI Elements + ui->pushButtonUnlock->setEnabled(false); + ui->lineEditEncryptionKey->setEnabled(false); + + ui->pushButtonBackup->setEnabled(true); + ui->pushButtonSave->setEnabled(true); + ui->pushButtonAddEntry->setEnabled(true); + ui->pushButtonRemoveEntry->setEnabled(true); + ui->pushButtonGeneratePassword->setEnabled(true); + ui->spinBoxPasswordLength->setEnabled(true); + ui->lineEditSearch->setEnabled(true); + ui->tableWidgetCredentials->setEnabled(true); + + ui->tableWidgetCredentials->setHorizontalHeaderLabels({"Website", "Username", "Password", "Note"}); + ui->tableWidgetCredentials->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); +} + +void MainWindow::backup_database() +{ + if (password_manager.backup()) + { + ui->labelDatabaseInfo->setText("Database Backup Complete"); + } else { + ui->labelDatabaseInfo->setText("Database could not be Backed Up"); + } +} + +void MainWindow::save_database() +{ + password_manager.clear_database(); + + std::array tmp_row; + for (int i = 0; i < ui->tableWidgetCredentials->rowCount(); i++) + { + for (int j = 0; j < 4; j++) + { + tmp_row[static_cast(j)] = ui->tableWidgetCredentials->item(i, j)->text(); + } + password_manager.add_entry(tmp_row[0], tmp_row[1], tmp_row[2], tmp_row[3]); + } + + password_manager.encrypt(); + password_manager.save(); + + saved = true; +} + +void MainWindow::add_entry() +{ + int row_count = ui->tableWidgetCredentials->rowCount(); + + ui->tableWidgetCredentials->insertRow(row_count); + ui->tableWidgetCredentials->scrollToItem(ui->tableWidgetCredentials->takeItem(row_count, 0)); + + ui->tableWidgetCredentials->setItem(row_count, 0, new QTableWidgetItem("")); + ui->tableWidgetCredentials->setItem(row_count, 1, new QTableWidgetItem("")); + ui->tableWidgetCredentials->setItem(row_count, 2, new QTableWidgetItem(password_manager.generate_password(password_length))); + ui->tableWidgetCredentials->setItem(row_count, 3, new QTableWidgetItem("")); + + saved = false; +} + +void MainWindow::remove_entry() +{ + QList selected = ui->tableWidgetCredentials->selectedItems(); + + saved = selected.size() <= 0; + + for (QTableWidgetItem* item : selected) + { + ui->tableWidgetCredentials->removeRow(item->row()); + } +} + +void MainWindow::generate_password() +{ + QList selected = ui->tableWidgetCredentials->selectedItems(); + + saved = selected.size() <= 0; + + for (QTableWidgetItem* item : selected) + { + std::array entry = password_manager.get_entry_copy(item->row()); + ui->tableWidgetCredentials->setItem(item->row(), 2, new QTableWidgetItem(password_manager.generate_password(password_length))); + } +} + +void MainWindow::search(const QString &input) +{ + //Show all rows + for (int i = 0; i < ui->tableWidgetCredentials->rowCount(); i++) + { + ui->tableWidgetCredentials->showRow(i); + } + + //End if not searching + if (input.size() == 0) + { + return; + } + + //Hide rows that don't contain searched text + for (int i = 0; i < ui->tableWidgetCredentials->rowCount(); i++) + { + if (!ui->tableWidgetCredentials->item(i, 0)->text().contains(input)) + { + ui->tableWidgetCredentials->hideRow(i); + } + } +} + +void MainWindow::closeEvent(QCloseEvent *event) +{ + if (saved) + { + event->accept(); + return; + } + + QMessageBox exit_message_box; + exit_message_box.setIcon(QMessageBox::Warning); + exit_message_box.setText("You didn't save!"); + exit_message_box.setInformativeText("Do you want to save before exiting?"); + exit_message_box.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + exit_message_box.setDefaultButton(QMessageBox::Yes); + + switch (exit_message_box.exec()) { + case QMessageBox::Save: + save_database(); + event->accept(); + break; + case QMessageBox::Discard: + event->accept(); + break; + case QMessageBox::Cancel: + event->ignore(); + break; + default: + event->ignore(); + break; + } +} + +void MainWindow::check_database() +{ + + if (password_manager.database_exists()) + { + return; + } + + QInputDialog input_dialog; + input_dialog.resize(400, 200); + input_dialog.setWindowTitle("Database not Found"); + input_dialog.setLabelText("Enter Password for your new Database:"); + + if (input_dialog.exec() == 0) + { + close(); + return; + } + + QString password = input_dialog.textValue(); + + if (password.length() > 0) + { + password_manager.key = password; + password_manager.encrypt(); + password_manager.save(); + } + + check_database(); +} + +void MainWindow::on_spinBoxPasswordLength_valueChanged(int arg1) +{ + password_length = arg1; +} + +void MainWindow::on_tableWidgetCredentials_itemChanged() +{ + saved = false; +} + +void MainWindow::on_tableWidgetCredentials_itemSelectionChanged() +{ + if (ui->tableWidgetCredentials->selectedItems().size() > 1) + { + ui->pushButtonRemoveEntry->setText("Remove Selected Entries"); + } else { + ui->pushButtonRemoveEntry->setText("Remove Selected Entry"); + } +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..70fe17d --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,48 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include +#include +#include "passman.h" + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QString version, QWidget *parent = nullptr); + ~MainWindow() override; + void check_database(); + +protected: + passman password_manager; + bool saved = true; + int password_length = 20; + void closeEvent(QCloseEvent *event) override; + +protected slots: + void decrypt_database(); + void backup_database(); + void save_database(); + void add_entry(); + void remove_entry(); + void generate_password(); + void search(const QString &input); + +private slots: + void on_spinBoxPasswordLength_valueChanged(int arg1); + void on_tableWidgetCredentials_itemChanged(); + void on_tableWidgetCredentials_itemSelectionChanged(); + +private: + Ui::MainWindow *ui; +}; + +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..991eabb --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,312 @@ + + + MainWindow + + + + 0 + 0 + 870 + 484 + + + + + 620 + 420 + + + + PassMan + + + + :/icons/passman_icon.svg:/icons/passman_icon.svg + + + QTabWidget::Rounded + + + + + + + + + + + + + false + + + Qt::AlignCenter + + + Enter Website Name to Search + + + + + + + + + false + + + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + Qt::NoPen + + + false + + + 0 + + + 100 + + + 41 + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 40 + 20 + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + false + + + Backup Database + + + + + + + false + + + Save Database + + + + + + + false + + + Add New Entry + + + + + + + false + + + Remove Selected Entry + + + + + + + false + + + Generate New Password + + + + + + + + + false + + + + + + Password Length: + + + 1000 + + + 20 + + + 10 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Database Encrypted + + + Qt::AlignCenter + + + true + + + + + + + QFrame::NoFrame + + + Enter Encryption Key + + + Qt::AutoText + + + Qt::AlignCenter + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + + + + QLineEdit::Password + + + Qt::AlignCenter + + + Encryption Key + + + + + + + + 230 + 0 + + + + Decrypt Database + + + + + + + + + + + + + + + + + + lineEditEncryptionKey + returnPressed() + pushButtonUnlock + click() + + + 734 + 418 + + + 734 + 450 + + + + + diff --git a/makearchpkg.sh b/makearchpkg.sh new file mode 100644 index 0000000..dbe8862 --- /dev/null +++ b/makearchpkg.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# Copy PKGBUILD for given Architecture +cp PKGBUILD_$1 PKGBUILD + +# Make Package +makepkg -f + +# Remove PKGBUILD for given Architecture +rm PKGBUILD diff --git a/makedebpkg.sh b/makedebpkg.sh new file mode 100644 index 0000000..d5900c6 --- /dev/null +++ b/makedebpkg.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# Compile +mkdir build +cd build +qmake .. +make +cd .. + +# Make Folders +mkdir -p build/passman_debian/DEBIAN +mkdir -p build/passman_debian/usr/bin +mkdir -p build/passman_debian/usr/share/applications +mkdir -p build/passman_debian/opt/aslan/icons + +# Copy files +cp control_$1 build/passman_debian/DEBIAN/control +cp build/passman build/passman_debian/usr/bin/passman +cp passman.desktop build/passman_debian/usr/share/applications/passman.desktop +cp passman_icon.svg build/passman_debian/opt/aslan/icons/passman_icon.svg + +# Make Package +dpkg-deb --build build/passman_debian +mv build/passman_debian.deb passman_debian_$1.deb diff --git a/parameterparser.cpp b/parameterparser.cpp new file mode 100644 index 0000000..93ff994 --- /dev/null +++ b/parameterparser.cpp @@ -0,0 +1,57 @@ +#include "parameterparser.h" +#include +parameterparser::parameterparser(int argc, char *argv[]) +{ + parse(argc, argv); +} + +void parameterparser::parse(int argc, char *argv[]) +{ + arg_names.emplace_back("program"); + arg_values.emplace_back(""); + + for (int i = 1; i < argc; i++) + { + if (argv[i][0] == '-' && argv[i][1] == '-') + { + //Parameter ex.(--parameter) + arg_names.emplace_back(argv[i]); + arg_values.emplace_back(""); + } else if (argv[i][0] == '-') { + //Parameter ex.(-p) + for (int j = 1; argv[i][j] != '\0'; j++) + { + arg_names.emplace_back(std::string(1, argv[i][j])); + arg_values.emplace_back(""); + } + } else { + //Parameter Value + arg_values[arg_values.size() - 1] = argv[i]; + } + } +} + + +bool parameterparser::has_parameter(std::string parameter_name, char parameter_abbr) +{ + return get_value(parameter_name, parameter_abbr) == "-" ? false : true; +} + +std::string parameterparser::get_value(std::string parameter_name, char parameter_abbr) +{ + parameter_name = "--" + parameter_name; + + for (unsigned long i = 0; i < arg_names.size(); i++) + { + if (arg_names[i].compare(parameter_name) == 0) + { + return arg_values[i]; + } + if (arg_names[i].compare(std::string(1, parameter_abbr)) == 0) + { + return arg_values[i]; + } + } + + return "-"; +} diff --git a/parameterparser.h b/parameterparser.h new file mode 100644 index 0000000..e7008f1 --- /dev/null +++ b/parameterparser.h @@ -0,0 +1,19 @@ +#ifndef PARAMETERPARSER_H +#define PARAMETERPARSER_H + +#include +#include + +class parameterparser +{ +public: + parameterparser(int argc, char *argv[]); + bool has_parameter(std::string parameter_name, char parameter_abbr); + std::string get_value(std::string parameter_name, char parameter_abbr); +protected: + std::vector arg_names; + std::vector arg_values; + void parse(int argc, char *argv[]); +}; + +#endif // PARAMETERPARSER_H diff --git a/passman-1.0.0.tar.xz.txt b/passman-1.0.0.tar.xz.txt new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/passman-1.0.0.tar.xz.txt @@ -0,0 +1 @@ + diff --git a/passman.cpp b/passman.cpp new file mode 100644 index 0000000..05067df --- /dev/null +++ b/passman.cpp @@ -0,0 +1,175 @@ +#include "passman.h" + +passman::passman() : encryption(new QAESEncryption(QAESEncryption::AES_256, QAESEncryption::CBC)) { } + +//Save Database to Disk +void passman::save() const +{ + QFile output_file(database_path); + output_file.open(QIODevice::WriteOnly); + output_file.write(encrypted_data); + output_file.close(); +} + +//Load Database from Disk +bool passman::load() +{ + if (!database_exists()) + { + return false; + } + + QFile input_file(database_path); + input_file.open(QIODevice::ReadOnly); + encrypted_data = input_file.readAll(); + input_file.close(); + + return true; +} + +//Encrypt Database +void passman::encrypt() +{ + QByteArray data = QString("passwords\n").toLocal8Bit(); + + //Convert Database into Byte Array + for (std::array& entry_row : decrypted_entries) + { + for (QString& entry_column : entry_row) + { + data.append((entry_column + '\t').toLocal8Bit()); + } + data.append(QString('\n').toLocal8Bit()); + } + + //Encrypt data for every iv + for (int i = 0; i < ivs.size(); i++) + { + data = encryption->encode(data, QCryptographicHash::hash(key.toLocal8Bit(), QCryptographicHash::Sha256), QCryptographicHash::hash((ivs[i] + key).toLocal8Bit(), QCryptographicHash::Md5)); + } + encrypted_data = data; +} + +//Decrypt Database +bool passman::decrypt() +{ + QByteArray data = encrypted_data; + + //Decrypt data for every iv + for (int i = ivs.size() - 1; i >= 0; i--) + { + data = encryption->decode(data, QCryptographicHash::hash(key.toLocal8Bit(), QCryptographicHash::Sha256), QCryptographicHash::hash((ivs[i] + key).toLocal8Bit(), QCryptographicHash::Md5)); + } + + decrypted_entries.clear(); + + //Convert Byte Array into Database + QString stringData = QString::fromLocal8Bit(data); + QString line = ""; + for (QChar& ch : stringData) + { + if (ch == '\n') + { + if (line == "password") + { + line = ""; + continue; + } + + QStringList columns = line.split('\t'); + std::array row; + if (columns.length() == 5) + { + for (int i = 0; i < 4; i++) + { + row[static_cast(i)] = columns[i]; + } + decrypted_entries.emplace_back(row); + } + + line = ""; + continue; + } + line += ch; + } + + return stringData.startsWith("password"); +} + +//Make Database Backup +bool passman::backup() const +{ + if (!database_exists()) + { + return false; + } + + QFile input_file(database_path); + input_file.open(QIODevice::ReadOnly); + QByteArray data = input_file.readAll(); + input_file.close(); + + QFile output_file(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/credentials_backup.database"); + output_file.open(QIODevice::WriteOnly); + output_file.write(data); + output_file.close(); + + return true; +} + +void passman::add_entry(QString website_name, QString username, QString password, QString note) +{ + std::array row; + row[0] = website_name; + row[1] = username; + row[2] = password; + row[3] = note; + decrypted_entries.emplace_back(row); +} + +void passman::remove_entry(int index) +{ + decrypted_entries.erase(decrypted_entries.begin() + index); +} + +void passman::alter_entry(int index, QString new_website_name, QString new_username, QString new_password, QString new_note) +{ + std::array& row = decrypted_entries[static_cast(index)]; + row[0] = new_website_name; + row[1] = new_username; + row[2] = new_password; + row[3] = new_note; +} + +void passman::clear_database() +{ + decrypted_entries.clear(); +} + +std::array passman::get_entry_copy(int index) const +{ + return decrypted_entries[static_cast(index)]; +} + +std::vector> passman::get_database_copy() const +{ + return decrypted_entries; +} + +QString passman::generate_password(int length) const +{ + QRandomGenerator rand = QRandomGenerator::securelySeeded(); + + QString output = ""; + for (int i = 0; i < length; i++) + { + output += characters[rand.bounded(0, characters.length())]; + } + + return output; +} + +bool passman::database_exists() const +{ + return QFile::exists(database_path); +} diff --git a/passman.desktop b/passman.desktop new file mode 100755 index 0000000..1d20759 --- /dev/null +++ b/passman.desktop @@ -0,0 +1,19 @@ +[Desktop Entry] +Comment[en_US]= +Comment= +Exec=/usr/bin/passman +GenericName[en_US]=Password Manager +GenericName=Password Manager +Icon=/opt/aslan/icons/passman_icon +MimeType= +Name[en_US]=Passman +Name=Passman +Path= +StartupNotify=true +Terminal=false +TerminalOptions= +Type=Application +X-DBUS-ServiceName= +X-DBUS-StartupType= +X-KDE-SubstituteUID=false +X-KDE-Username= diff --git a/passman.h b/passman.h new file mode 100644 index 0000000..14a6765 --- /dev/null +++ b/passman.h @@ -0,0 +1,53 @@ +#ifndef PASSMAN_H +#define PASSMAN_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "qaesencryption.h" + +class passman +{ +public: + passman(); + QString database_path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/credentials.database"; + QString key = ""; + void save() const; + bool load(); + void encrypt(); + bool decrypt(); + bool backup() const; + void add_entry(QString website_name, QString username, QString password, QString note); + void remove_entry(int index); + void alter_entry(int index, QString new_website_name, QString new_username, QString new_password, QString new_note); + void clear_database(); + std::array get_entry_copy(int index) const; + std::vector> get_database_copy() const; + QString generate_password(int length) const; + bool database_exists() const; + +protected: + QAESEncryption *encryption; + QByteArray encrypted_data; //Encrypted Database + std::vector> decrypted_entries; //Database Entries + QString characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:;.,/=-+*<>{}()[]_%#$@!?^&"; + QStringList ivs = { + "jW2jT]%0k2#-2R1.d(7'6V0Z|4=-HX2G9@F;561.07@21,NHq42)*896M(18R+9w080*Hs^,45G?;]5R7}'*0Z67?Y7|%SFI**0g", + ")OR2*711+M)*a,5D/qB}/#]|fN*30oA<#;>]B80>,4J9@<<;J5;#wL*]p$G9D0i1860;Y}b;|h)]6h6.O(n(*R)j87WrfZJ%>DM635u68i/s7@<*=/[V562&46E}P)/+8pZ$0c/3)690A/t.8eJ+4gJxf1&q?99%AP{)c71", + "6J00^0cZ-X16a=Z+K<_{8J34#1@9*Tb@3B4_^5'k0+YY[^--IZ71y0^62T&w>9}o738zAj7p1.%NA)+3^246X|F61I3<+I.8Z3tE4,HE_56o{[*7;*rf^", + "@F7L-7$;'h*|?0io3Zo}063)193|3'o/6-E+877Tr[vW87sNc8q<6,69-IS72cz6|2I/p{I8D6W520/$&6*Y3&%v,*0/85(ikK!J", + "72|/3;10O@!(|t)]8}02Gf126N)+6*w6e2P57/dWd*JW5+aR?h31e/=4o58!$l9!4?6_,7L%4}z3Lu8;sb^q}9%lVy6I57L]8<,-ho?310Dd_h|y1#iz%3]rN'zr5T1Bc2uQ5cb!K39386)50c0+%.w.X'", + "2-n$rL3v4T/*/22F%2tN}.yDX78#50z3Z9-B10X5*4]97+R-OK'2^F%7$>95c8jLu531C==1|V7Cd=o;5L6/B17jF2C9<1]R4'DY", + }; +}; + +#endif // PASSMAN_H diff --git a/passman.pro b/passman.pro new file mode 100644 index 0000000..892dd0e --- /dev/null +++ b/passman.pro @@ -0,0 +1,50 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2019-12-11T18:51:02 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = passman +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +CONFIG += c++11 + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + qaesencryption.cpp \ + passman.cpp \ + parameterparser.cpp + +HEADERS += \ + mainwindow.h \ + parameterparser.h \ + qaesencryption.h \ + passman.h \ + parameterparser.h + +FORMS += \ + mainwindow.ui + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +RESOURCES += \ + resources.qrc diff --git a/passman_icon.svg b/passman_icon.svg new file mode 100644 index 0000000..f8e0bfd --- /dev/null +++ b/passman_icon.svg @@ -0,0 +1,83 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/qaesencryption.cpp b/qaesencryption.cpp new file mode 100644 index 0000000..8aaaed8 --- /dev/null +++ b/qaesencryption.cpp @@ -0,0 +1,492 @@ +#include "qaesencryption.h" + +/* + * Static Functions + * */ +QByteArray QAESEncryption::Crypt(QAESEncryption::AES level, QAESEncryption::MODE mode, const QByteArray &rawText, + const QByteArray &key, const QByteArray &iv, QAESEncryption::PADDING padding) +{ + return QAESEncryption(level, mode, padding).encode(rawText, key, iv); +} + +QByteArray QAESEncryption::Decrypt(QAESEncryption::AES level, QAESEncryption::MODE mode, const QByteArray &rawText, + const QByteArray &key, const QByteArray &iv, QAESEncryption::PADDING padding) +{ + return QAESEncryption(level, mode, padding).decode(rawText, key, iv); +} + +QByteArray QAESEncryption::ExpandKey(QAESEncryption::AES level, QAESEncryption::MODE mode, const QByteArray &key) +{ + return QAESEncryption(level, mode).expandKey(key); +} + +QByteArray QAESEncryption::RemovePadding(const QByteArray &rawText, QAESEncryption::PADDING padding) +{ + QByteArray ret(rawText); + switch (padding) + { + case PADDING::ZERO: + //Works only if the last byte of the decoded array is not zero + while (ret.at(ret.length()-1) == 0x00) + ret.remove(ret.length()-1, 1); + break; + case PADDING::PKCS7: + ret.remove(ret.length() - ret.at(ret.length()-1), ret.at(ret.length()-1)); + break; + case PADDING::ISO: + ret.truncate(ret.lastIndexOf(0x80)); + break; + default: + //do nothing + break; + } + return ret; +} +/* + * End Static function declarations + * */ + +/* + * Inline Functions + * */ + +inline quint8 xTime(quint8 x){ + return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); +} + +inline quint8 multiply(quint8 x, quint8 y){ + return (((y & 1) * x) ^ ((y>>1 & 1) * xTime(x)) ^ ((y>>2 & 1) * xTime(xTime(x))) ^ ((y>>3 & 1) + * xTime(xTime(xTime(x)))) ^ ((y>>4 & 1) * xTime(xTime(xTime(xTime(x)))))); +} + +/* + * End Inline functions + * */ + + +QAESEncryption::QAESEncryption(QAESEncryption::AES level, QAESEncryption::MODE mode, PADDING padding) + : m_nb(4), m_blocklen(16), m_level(level), m_mode(mode), m_padding(padding) +{ + m_state = NULL; + + switch (level) + { + case AES_128: { + AES128 aes; + m_nk = aes.nk; + m_keyLen = aes.keylen; + m_nr = aes.nr; + m_expandedKey = aes.expandedKey; + } + break; + case AES_192: { + AES192 aes; + m_nk = aes.nk; + m_keyLen = aes.keylen; + m_nr = aes.nr; + m_expandedKey = aes.expandedKey; + } + break; + case AES_256: { + AES256 aes; + m_nk = aes.nk; + m_keyLen = aes.keylen; + m_nr = aes.nr; + m_expandedKey = aes.expandedKey; + } + break; + default: { + AES128 aes; + m_nk = aes.nk; + m_keyLen = aes.keylen; + m_nr = aes.nr; + m_expandedKey = aes.expandedKey; + } + break; + } + +} +QByteArray QAESEncryption::getPadding(int currSize, int alignment) +{ + QByteArray ret(0); + int size = (alignment - currSize % alignment) % alignment; + if (size == 0) return ret; + switch(m_padding) + { + case PADDING::ZERO: + ret.insert(0, size, 0x00); + break; + case PADDING::PKCS7: + ret.insert(0, size, size); + break; + case PADDING::ISO: + ret.insert(0, 0x80); + ret.insert(1, size, 0x00); + break; + default: + ret.insert(0, size, 0x00); + break; + } + return ret; +} + +QByteArray QAESEncryption::expandKey(const QByteArray &key) +{ + int i, k; + quint8 tempa[4]; // Used for the column/row operations + QByteArray roundKey(key); + + // The first round key is the key itself. + // ... + + // All other round keys are found from the previous round keys. + //i == Nk + for(i = m_nk; i < m_nb * (m_nr + 1); i++) + { + tempa[0] = (quint8) roundKey.at((i-1) * 4 + 0); + tempa[1] = (quint8) roundKey.at((i-1) * 4 + 1); + tempa[2] = (quint8) roundKey.at((i-1) * 4 + 2); + tempa[3] = (quint8) roundKey.at((i-1) * 4 + 3); + + if (i % m_nk == 0) + { + // This function shifts the 4 bytes in a word to the left once. + // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] + + // Function RotWord() + k = tempa[0]; + tempa[0] = tempa[1]; + tempa[1] = tempa[2]; + tempa[2] = tempa[3]; + tempa[3] = k; + + // Function Subword() + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + + tempa[0] = tempa[0] ^ Rcon[i/m_nk]; + } + if (m_level == AES_256 && i % m_nk == 4) + { + // Function Subword() + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + } + roundKey.insert(i * 4 + 0, (quint8) roundKey.at((i - m_nk) * 4 + 0) ^ tempa[0]); + roundKey.insert(i * 4 + 1, (quint8) roundKey.at((i - m_nk) * 4 + 1) ^ tempa[1]); + roundKey.insert(i * 4 + 2, (quint8) roundKey.at((i - m_nk) * 4 + 2) ^ tempa[2]); + roundKey.insert(i * 4 + 3, (quint8) roundKey.at((i - m_nk) * 4 + 3) ^ tempa[3]); + } + return roundKey; +} + +// This function adds the round key to state. +// The round key is added to the state by an XOR function. +void QAESEncryption::addRoundKey(const quint8 round, const QByteArray expKey) +{ + QByteArray::iterator it = m_state->begin(); + for(int i=0; i < 16; ++i) + it[i] = (quint8) it[i] ^ (quint8) expKey.at(round * m_nb * 4 + (i/4) * m_nb + (i%4)); +} + +// The SubBytes Function Substitutes the values in the +// state matrix with values in an S-box. +void QAESEncryption::subBytes() +{ + QByteArray::iterator it = m_state->begin(); + for(int i = 0; i < 16; i++) + it[i] = getSBoxValue((quint8) it[i]); +} + +// The ShiftRows() function shifts the rows in the state to the left. +// Each row is shifted with different offset. +// Offset = Row number. So the first row is not shifted. +void QAESEncryption::shiftRows() +{ + QByteArray::iterator it = m_state->begin(); + quint8 temp; + //Keep in mind that QByteArray is column-driven!! + + //Shift 1 to left + temp = (quint8)it[1]; + it[1] = (quint8)it[5]; + it[5] = (quint8)it[9]; + it[9] = (quint8)it[13]; + it[13] = (quint8)temp; + + //Shift 2 to left + temp = (quint8)it[2]; + it[2] = (quint8)it[10]; + it[10] = (quint8)temp; + temp = (quint8)it[6]; + it[6] = (quint8)it[14]; + it[14] = (quint8)temp; + + //Shift 3 to left + temp = (quint8)it[3]; + it[3] = (quint8)it[15]; + it[15] = (quint8)it[11]; + it[11] = (quint8)it[7]; + it[7] = (quint8)temp; +} + +// MixColumns function mixes the columns of the state matrix +//optimized!! +void QAESEncryption::mixColumns() +{ + QByteArray::iterator it = m_state->begin(); + quint8 tmp, tm, t; + + for(int i = 0; i < 16; i += 4){ + t = (quint8)it[i]; + tmp = (quint8)it[i] ^ (quint8)it[i+1] ^ (quint8)it[i+2] ^ (quint8)it[i+3] ; + + tm = xTime( (quint8)it[i] ^ (quint8)it[i+1] ); + it[i] = (quint8)it[i] ^ (quint8)tm ^ (quint8)tmp; + + tm = xTime( (quint8)it[i+1] ^ (quint8)it[i+2]); + it[i+1] = (quint8)it[i+1] ^ (quint8)tm ^ (quint8)tmp; + + tm = xTime( (quint8)it[i+2] ^ (quint8)it[i+3]); + it[i+2] =(quint8)it[i+2] ^ (quint8)tm ^ (quint8)tmp; + + tm = xTime((quint8)it[i+3] ^ (quint8)t); + it[i+3] =(quint8)it[i+3] ^ (quint8)tm ^ (quint8)tmp; + } +} + +// MixColumns function mixes the columns of the state matrix. +// The method used to multiply may be difficult to understand for the inexperienced. +// Please use the references to gain more information. +void QAESEncryption::invMixColumns() +{ + QByteArray::iterator it = m_state->begin(); + quint8 a,b,c,d; + for(int i = 0; i < 16; i+=4){ + a = (quint8) it[i]; + b = (quint8) it[i+1]; + c = (quint8) it[i+2]; + d = (quint8) it[i+3]; + + it[i] = (quint8) (multiply(a, 0x0e) ^ multiply(b, 0x0b) ^ multiply(c, 0x0d) ^ multiply(d, 0x09)); + it[i+1] = (quint8) (multiply(a, 0x09) ^ multiply(b, 0x0e) ^ multiply(c, 0x0b) ^ multiply(d, 0x0d)); + it[i+2] = (quint8) (multiply(a, 0x0d) ^ multiply(b, 0x09) ^ multiply(c, 0x0e) ^ multiply(d, 0x0b)); + it[i+3] = (quint8) (multiply(a, 0x0b) ^ multiply(b, 0x0d) ^ multiply(c, 0x09) ^ multiply(d, 0x0e)); + } +} + +// The SubBytes Function Substitutes the values in the +// state matrix with values in an S-box. +void QAESEncryption::invSubBytes() +{ + QByteArray::iterator it = m_state->begin(); + for(int i = 0; i < 16; ++i) + it[i] = getSBoxInvert((quint8) it[i]); +} + +void QAESEncryption::invShiftRows() +{ + QByteArray::iterator it = m_state->begin(); + uint8_t temp; + + //Keep in mind that QByteArray is column-driven!! + + //Shift 1 to right + temp = (quint8)it[13]; + it[13] = (quint8)it[9]; + it[9] = (quint8)it[5]; + it[5] = (quint8)it[1]; + it[1] = (quint8)temp; + + //Shift 2 + temp = (quint8)it[10]; + it[10] = (quint8)it[2]; + it[2] = (quint8)temp; + temp = (quint8)it[14]; + it[14] = (quint8)it[6]; + it[6] = (quint8)temp; + + //Shift 3 + temp = (quint8)it[15]; + it[15] = (quint8)it[3]; + it[3] = (quint8)it[7]; + it[7] = (quint8)it[11]; + it[11] = (quint8)temp; +} + +QByteArray QAESEncryption::byteXor(const QByteArray &a, const QByteArray &b) +{ + QByteArray::const_iterator it_a = a.begin(); + QByteArray::const_iterator it_b = b.begin(); + QByteArray ret; + + for(int i = 0; i < m_blocklen; i++) + ret.insert(i,it_a[i] ^ it_b[i]); + + return ret; +} + +// Cipher is the main function that encrypts the PlainText. +QByteArray QAESEncryption::cipher(const QByteArray &expKey, const QByteArray &in) +{ + + //m_state is the input buffer... + QByteArray output(in); + m_state = &output; + + // Add the First round key to the state before starting the rounds. + addRoundKey(0, expKey); + + // There will be Nr rounds. + // The first Nr-1 rounds are identical. + // These Nr-1 rounds are executed in the loop below. + for(quint8 round = 1; round < m_nr; ++round){ + subBytes(); + shiftRows(); + mixColumns(); + addRoundKey(round, expKey); + } + + // The last round is given below. + // The MixColumns function is not here in the last round. + subBytes(); + shiftRows(); + addRoundKey(m_nr, expKey); + + return output; +} + +QByteArray QAESEncryption::invCipher(const QByteArray &expKey, const QByteArray &in) +{ + //m_state is the input buffer.... handle it! + QByteArray output(in); + m_state = &output; + + // Add the First round key to the state before starting the rounds. + addRoundKey(m_nr, expKey); + + // There will be Nr rounds. + // The first Nr-1 rounds are identical. + // These Nr-1 rounds are executed in the loop below. + for(quint8 round=m_nr-1; round>0 ; round--){ + invShiftRows(); + invSubBytes(); + addRoundKey(round, expKey); + invMixColumns(); + } + + // The last round is given below. + // The MixColumns function is not here in the last round. + invShiftRows(); + invSubBytes(); + addRoundKey(0, expKey); + + return output; +} + +QByteArray QAESEncryption::encode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv) +{ + if (m_mode >= CBC && (iv.isNull() || iv.size() != m_blocklen)) + return QByteArray(); + + QByteArray ret; + QByteArray expandedKey = expandKey(key); + QByteArray alignedText(rawText); + QByteArray ivTemp(iv); + + //Fill array with padding + alignedText.append(getPadding(rawText.size(), m_blocklen)); + + //Preparation for CFB + if (m_mode == CFB) + ret.append(byteXor(alignedText.mid(0, m_blocklen), cipher(expandedKey, iv))); + + //Looping thru all blocks + for(int i=0; i < alignedText.size(); i+= m_blocklen){ + switch(m_mode) + { + case ECB: + ret.append(cipher(expandedKey, alignedText.mid(i, m_blocklen))); + break; + case CBC: + alignedText.replace(i, m_blocklen, byteXor(alignedText.mid(i, m_blocklen),ivTemp)); + ret.append(cipher(expandedKey, alignedText.mid(i, m_blocklen))); + ivTemp = ret.mid(i, m_blocklen); + break; + case CFB: + if (i+m_blocklen < alignedText.size()) + ret.append(byteXor(alignedText.mid(i+m_blocklen, m_blocklen), + cipher(expandedKey, ret.mid(i, m_blocklen)))); + break; + default: + //do nothing + break; + } + } + return ret; +} + +QByteArray QAESEncryption::decode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv) +{ + if (m_mode >= CBC && (iv.isNull() || iv.size() != m_blocklen)) + return QByteArray(); + + QByteArray ret; + QByteArray expandedKey = expandKey(key); + QByteArray ivTemp(iv); + + //Preparation for CFB + if (m_mode == CFB) + ret.append(byteXor(rawText.mid(0, m_blocklen), cipher(expandedKey, iv))); + + for(int i=0; i < rawText.size(); i+= m_blocklen){ + switch(m_mode) + { + case ECB: + ret.append(invCipher(expandedKey, rawText.mid(i, m_blocklen))); + break; + case CBC: + ret.append(invCipher(expandedKey, rawText.mid(i, m_blocklen))); + ret.replace(i, m_blocklen, byteXor(ret.mid(i, m_blocklen),ivTemp)); + ivTemp = rawText.mid(i, m_blocklen); + break; + case CFB: + if (i+m_blocklen < rawText.size()){ + ret.append(byteXor(rawText.mid(i+m_blocklen, m_blocklen), + cipher(expandedKey, rawText.mid(i, m_blocklen)))); + } + break; + default: + //do nothing + break; + } + } + return ret; +} + +QByteArray QAESEncryption::removePadding(const QByteArray &rawText) +{ + QByteArray ret(rawText); + switch (m_padding) + { + case PADDING::ZERO: + //Works only if the last byte of the decoded array is not zero + while (ret.at(ret.length()-1) == 0x00) + ret.remove(ret.length()-1, 1); + break; + case PADDING::PKCS7: + ret.remove(ret.length() - ret.at(ret.length()-1), ret.at(ret.length()-1)); + break; + case PADDING::ISO: + ret.truncate(ret.lastIndexOf(0x80)); + break; + default: + //do nothing + break; + } + return ret; +} diff --git a/qaesencryption.h b/qaesencryption.h new file mode 100644 index 0000000..0065cf1 --- /dev/null +++ b/qaesencryption.h @@ -0,0 +1,154 @@ +#ifndef QAESENCRYPTION_H +#define QAESENCRYPTION_H + +#include +#include + +class QAESEncryption : public QObject +{ + Q_OBJECT +public: + enum AES { + AES_128, + AES_192, + AES_256 + }; + + enum MODE { + ECB, + CBC, + CFB + }; + + enum PADDING { + ZERO, + PKCS7, + ISO + }; + + static QByteArray Crypt(QAESEncryption::AES level, QAESEncryption::MODE mode, const QByteArray &rawText, const QByteArray &key, + const QByteArray &iv = NULL, QAESEncryption::PADDING padding = QAESEncryption::ISO); + static QByteArray Decrypt(QAESEncryption::AES level, QAESEncryption::MODE mode, const QByteArray &rawText, const QByteArray &key, + const QByteArray &iv = NULL, QAESEncryption::PADDING padding = QAESEncryption::ISO); + static QByteArray ExpandKey(QAESEncryption::AES level, QAESEncryption::MODE mode, const QByteArray &key); + static QByteArray RemovePadding(const QByteArray &rawText, QAESEncryption::PADDING padding); + + QAESEncryption(QAESEncryption::AES level, QAESEncryption::MODE mode, QAESEncryption::PADDING padding = QAESEncryption::ISO); + + QByteArray encode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv = NULL); + QByteArray decode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv = NULL); + QByteArray removePadding(const QByteArray &rawText); + QByteArray expandKey(const QByteArray &key); + +signals: + +public slots: + +private: + int m_nb; + int m_blocklen; + int m_level; + int m_mode; + int m_nk; + int m_keyLen; + int m_nr; + int m_expandedKey; + int m_padding; + QByteArray* m_state; + + struct AES256{ + int nk = 8; + int keylen = 32; + int nr = 14; + int expandedKey = 240; + }; + + struct AES192{ + int nk = 6; + int keylen = 24; + int nr = 12; + int expandedKey = 209; + }; + + struct AES128{ + int nk = 4; + int keylen = 16; + int nr = 10; + int expandedKey = 176; + }; + + quint8 getSBoxValue(quint8 num){return sbox[num];} + quint8 getSBoxInvert(quint8 num){return rsbox[num];} + + void addRoundKey(const quint8 round, const QByteArray expKey); + void subBytes(); + void shiftRows(); + void mixColumns(); + void invMixColumns(); + void invSubBytes(); + void invShiftRows(); + QByteArray getPadding(int currSize, int alignment); + QByteArray cipher(const QByteArray &expKey, const QByteArray &plainText); + QByteArray invCipher(const QByteArray &expKey, const QByteArray &plainText); + QByteArray byteXor(const QByteArray &in, const QByteArray &iv); + + const quint8 sbox[256] = { + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; + + const quint8 rsbox[256] = + { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; + + // The round constant word array, Rcon[i], contains the values given by + // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) + //Only the first 14 elements are needed + const quint8 Rcon[256] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, /*0x4d, 0x9a, + 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, + 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, + 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, + 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, + 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, + 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, + 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, + 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, + 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d */}; +}; + +#endif // QAESENCRYPTION_H diff --git a/resources.qrc b/resources.qrc new file mode 100644 index 0000000..0b7f0e6 --- /dev/null +++ b/resources.qrc @@ -0,0 +1,5 @@ + + + passman_icon.svg + +