Version 1.0.0

This commit is contained in:
Aslan2142 2020-02-26 21:15:11 +01:00
parent ab27c5c51d
commit ff5399ba31
22 changed files with 1945 additions and 0 deletions

20
PKGBUILD_amd64 Normal file
View file

@ -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
}

20
PKGBUILD_arm64 Normal file
View file

@ -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
}

25
README.md Normal file
View file

@ -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

9
control_amd64 Normal file
View file

@ -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

9
control_arm64 Normal file
View file

@ -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

103
main.cpp Normal file
View file

@ -0,0 +1,103 @@
#include <iostream>
#include <QApplication>
#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<std::array<QString, 4>> database = password_manager.get_database_copy();
for (const std::array<QString, 4>& 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<std::array<QString, 4>> database = password_manager.get_database_copy();
for (const std::array<QString, 4>& 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;
}

257
mainwindow.cpp Normal file
View file

@ -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<std::array<QString, 4>> database = password_manager.get_database_copy();
ui->tableWidgetCredentials->clear();
ui->tableWidgetCredentials->setRowCount(static_cast<int>(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<int>(i), static_cast<int>(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<QString, 4> tmp_row;
for (int i = 0; i < ui->tableWidgetCredentials->rowCount(); i++)
{
for (int j = 0; j < 4; j++)
{
tmp_row[static_cast<ulong>(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<QTableWidgetItem*> selected = ui->tableWidgetCredentials->selectedItems();
saved = selected.size() <= 0;
for (QTableWidgetItem* item : selected)
{
ui->tableWidgetCredentials->removeRow(item->row());
}
}
void MainWindow::generate_password()
{
QList<QTableWidgetItem*> selected = ui->tableWidgetCredentials->selectedItems();
saved = selected.size() <= 0;
for (QTableWidgetItem* item : selected)
{
std::array<QString, 4> 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");
}
}

48
mainwindow.h Normal file
View file

@ -0,0 +1,48 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMessageBox>
#include <QInputDialog>
#include <QCloseEvent>
#include <QTableWidgetItem>
#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

312
mainwindow.ui Normal file
View file

@ -0,0 +1,312 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>870</width>
<height>484</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>620</width>
<height>420</height>
</size>
</property>
<property name="windowTitle">
<string>PassMan</string>
</property>
<property name="windowIcon">
<iconset resource="resources.qrc">
<normaloff>:/icons/passman_icon.svg</normaloff>:/icons/passman_icon.svg</iconset>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="lineEditSearch">
<property name="enabled">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="placeholderText">
<string>Enter Website Name to Search</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTableWidget" name="tableWidgetCredentials">
<property name="enabled">
<bool>false</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
</property>
<property name="gridStyle">
<enum>Qt::NoPen</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="columnCount">
<number>0</number>
</property>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>100</number>
</attribute>
<attribute name="horizontalHeaderMinimumSectionSize">
<number>41</number>
</attribute>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QFrame" name="frameControl">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="pushButtonBackup">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Backup Database</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonSave">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Save Database</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonAddEntry">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Add New Entry</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonRemoveEntry">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Remove Selected Entry</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonGeneratePassword">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Generate New Password</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QSpinBox" name="spinBoxPasswordLength">
<property name="enabled">
<bool>false</bool>
</property>
<property name="suffix">
<string/>
</property>
<property name="prefix">
<string>Password Length: </string>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>20</number>
</property>
<property name="displayIntegerBase">
<number>10</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelDatabaseInfo">
<property name="text">
<string>Database Encrypted</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelEncryptionInfo">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="text">
<string>Enter Encryption Key</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLineEdit" name="lineEditEncryptionKey">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="inputMask">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="placeholderText">
<string>Encryption Key</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonUnlock">
<property name="minimumSize">
<size>
<width>230</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Decrypt Database</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
<include location="resources.qrc"/>
</resources>
<connections>
<connection>
<sender>lineEditEncryptionKey</sender>
<signal>returnPressed()</signal>
<receiver>pushButtonUnlock</receiver>
<slot>click()</slot>
<hints>
<hint type="sourcelabel">
<x>734</x>
<y>418</y>
</hint>
<hint type="destinationlabel">
<x>734</x>
<y>450</y>
</hint>
</hints>
</connection>
</connections>
</ui>

10
makearchpkg.sh Normal file
View file

@ -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

24
makedebpkg.sh Normal file
View file

@ -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

57
parameterparser.cpp Normal file
View file

@ -0,0 +1,57 @@
#include "parameterparser.h"
#include <iostream>
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 "-";
}

19
parameterparser.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef PARAMETERPARSER_H
#define PARAMETERPARSER_H
#include <string>
#include <vector>
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<std::string> arg_names;
std::vector<std::string> arg_values;
void parse(int argc, char *argv[]);
};
#endif // PARAMETERPARSER_H

1
passman-1.0.0.tar.xz.txt Normal file
View file

@ -0,0 +1 @@

175
passman.cpp Normal file
View file

@ -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<QString, 4>& 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<QString, 4> row;
if (columns.length() == 5)
{
for (int i = 0; i < 4; i++)
{
row[static_cast<ulong>(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<QString, 4> 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<QString, 4>& row = decrypted_entries[static_cast<ulong>(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<QString, 4> passman::get_entry_copy(int index) const
{
return decrypted_entries[static_cast<ulong>(index)];
}
std::vector<std::array<QString, 4>> 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);
}

19
passman.desktop Executable file
View file

@ -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=

53
passman.h Normal file
View file

@ -0,0 +1,53 @@
#ifndef PASSMAN_H
#define PASSMAN_H
#include <iostream>
#include <vector>
#include <QString>
#include <QCryptographicHash>
#include <QRandomGenerator>
#include <QFile>
#include <QStandardPaths>
#include <QRandomGenerator>
#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<QString, 4> get_entry_copy(int index) const;
std::vector<std::array<QString, 4>> get_database_copy() const;
QString generate_password(int length) const;
bool database_exists() const;
protected:
QAESEncryption *encryption;
QByteArray encrypted_data; //Encrypted Database
std::vector<std::array<QString, 4>> 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<I*.)0diN/yi*08;^hJ596]2NY9&+#l",
"J>}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<Y[I08'z02H06;DK88p(I0z",
",<4t/*8[$;6clb/yo1f3*$iq]1{6L5@861(&s*7(Y44<85r8<9R._&4})0k|=41)dh*Xf)aL-/&8T&72704<!=v[h5i21^]Jj1i6",
"z@9;[k-lkl^bQ6?*30R5kU]O9.](]M}'9N'6|;;2Mmq!OV18|BS]f06c_F=>)+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/=4o5<H@Uzu2<;71Qd63B{k9-PQ_41[5yA'e^?2A27$[8-7",
"H(6>8!$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

50
passman.pro Normal file
View file

@ -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

83
passman_icon.svg Normal file
View file

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="256mm"
height="256mm"
viewBox="0 0 256 256"
version="1.1"
id="svg8"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="passman_icon.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.1767767"
inkscape:cx="267.1635"
inkscape:cy="441.34339"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1014"
inkscape:window-x="0"
inkscape:window-y="36"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-41)">
<rect
style="fill:#000000;fill-opacity:1;stroke:#8bc34a;stroke-width:38.4001236;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect43"
width="13.104113"
height="32.832691"
x="93.836334"
y="83.68634" />
<rect
style="fill:#689f38;fill-opacity:1;stroke:#689f38;stroke-width:68.59830475;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
id="rect39"
width="0.04028409"
height="120.28278"
x="133.98329"
y="78.945221" />
<circle
style="fill:#8bc34a;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
id="path41"
cx="134.09354"
cy="218.69034"
r="73.357323" />
<circle
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
id="path5342"
cx="133.99538"
cy="220.09711"
r="38.244026" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

492
qaesencryption.cpp Normal file
View file

@ -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;
}

154
qaesencryption.h Normal file
View file

@ -0,0 +1,154 @@
#ifndef QAESENCRYPTION_H
#define QAESENCRYPTION_H
#include <QObject>
#include <QByteArray>
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

5
resources.qrc Normal file
View file

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/icons">
<file>passman_icon.svg</file>
</qresource>
</RCC>