aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpg/CMakeLists.txt18
-rw-r--r--src/gpg/function/GpgKeyImportExporter.cpp25
-rw-r--r--src/gpg/function/GpgKeyImportExporter.h6
-rw-r--r--src/ui/CMakeLists.txt15
-rwxr-xr-xsrc/ui/KeyMgmt.cpp75
-rwxr-xr-xsrc/ui/KeyMgmt.h4
-rw-r--r--src/ui/MainWindow.cpp3
-rw-r--r--src/ui/aes/qaesencryption.cpp626
-rw-r--r--src/ui/aes/qaesencryption.h155
-rw-r--r--src/ui/keypair_details/KeyUIDSignDialog.cpp2
-rw-r--r--src/ui/smtp/RecipientsPicker.cpp2
-rw-r--r--src/ui/smtp/SenderPicker.cpp2
-rw-r--r--src/ui/widgets/ExportKeyPackageDialog.cpp165
-rw-r--r--src/ui/widgets/ExportKeyPackageDialog.h55
-rw-r--r--src/ui/widgets/KeyList.cpp62
-rw-r--r--src/ui/widgets/KeyList.h22
16 files changed, 1157 insertions, 80 deletions
diff --git a/src/gpg/CMakeLists.txt b/src/gpg/CMakeLists.txt
index ac01aa26..0ccc8171 100644
--- a/src/gpg/CMakeLists.txt
+++ b/src/gpg/CMakeLists.txt
@@ -9,8 +9,8 @@ set(UTILS_DIR ${CMAKE_SOURCE_DIR}/utils)
set(GPGME_LIB_DIR ${UTILS_DIR}/gpgme/lib)
-if (ESAY_LOGGING_PP)
- message(STATUS "Link ESAY_LOGGING_PP")
+if (EASY_LOGGING_PP)
+ message(STATUS "Link EASY_LOGGING_PP")
set(THIRD_PARTY_LIBS easy_logging_pp config++)
endif ()
@@ -33,13 +33,13 @@ elseif (APPLE)
${BOOST_LIBS}
${libgpgme} ${libgpg-error} ${libassuan}
dl)
- if(XCODE_BUILD)
- set_target_properties(gpg_core
- PROPERTIES
- ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}
- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}
- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE})
- endif()
+ if (XCODE_BUILD)
+ set_target_properties(gpg_core
+ PROPERTIES
+ ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}
+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}
+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE})
+ endif ()
else ()
find_library(libgpgme NAMES libgpgme.a)
find_library(libgpg-error NAMES libgpg-error.a)
diff --git a/src/gpg/function/GpgKeyImportExporter.cpp b/src/gpg/function/GpgKeyImportExporter.cpp
index ca9b86d1..33f865a7 100644
--- a/src/gpg/function/GpgKeyImportExporter.cpp
+++ b/src/gpg/function/GpgKeyImportExporter.cpp
@@ -60,24 +60,34 @@ GpgFrontend::GpgImportInformation GpgFrontend::GpgKeyImportExporter::ImportKey(
* @param out_buffer output byte array
* @return if success
*/
-bool GpgFrontend::GpgKeyImportExporter::ExportKeys(
- KeyIdArgsListPtr& uid_list, ByteArrayPtr& out_buffer) const {
+bool GpgFrontend::GpgKeyImportExporter::ExportKeys(KeyIdArgsListPtr& uid_list,
+ ByteArrayPtr& out_buffer,
+ bool secret) const {
if (uid_list->empty()) return false;
+ std::stringstream ss;
+
+ int _mode = 0;
+
+ if (secret) _mode |= GPGME_EXPORT_MODE_SECRET;
+
// Alleviate another crash problem caused by an unknown array out-of-bounds
// access
auto all_success = true;
for (size_t i = 0; i < uid_list->size(); i++) {
GpgData data_out;
- auto err = gpgme_op_export(ctx, (*uid_list)[i].c_str(), 0, data_out);
+ auto err = gpgme_op_export(ctx, (*uid_list)[i].c_str(), _mode, data_out);
if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) all_success = false;
DLOG(INFO) << "exportKeys read_bytes"
<< gpgme_data_seek(data_out, 0, SEEK_END);
auto temp_out_buffer = data_out.Read2Buffer();
- std::swap(out_buffer, temp_out_buffer);
+
+ ss << *temp_out_buffer << std::endl;
}
+ out_buffer = std::make_unique<ByteArray>(ss.str());
+
return all_success;
}
@@ -87,11 +97,12 @@ bool GpgFrontend::GpgKeyImportExporter::ExportKeys(
* @param outBuffer output byte array
* @return if success
*/
-bool GpgFrontend::GpgKeyImportExporter::ExportKeys(
- const KeyArgsList& keys, ByteArrayPtr& out_buffer) const {
+bool GpgFrontend::GpgKeyImportExporter::ExportKeys(const KeyArgsList& keys,
+ ByteArrayPtr& out_buffer,
+ bool secret) const {
KeyIdArgsListPtr key_ids = std::make_unique<std::vector<std::string>>();
for (const auto& key : keys) key_ids->push_back(key.id());
- return ExportKeys(key_ids, out_buffer);
+ return ExportKeys(key_ids, out_buffer, secret);
}
/**
diff --git a/src/gpg/function/GpgKeyImportExporter.h b/src/gpg/function/GpgKeyImportExporter.h
index b6c91303..64b3b8a9 100644
--- a/src/gpg/function/GpgKeyImportExporter.h
+++ b/src/gpg/function/GpgKeyImportExporter.h
@@ -88,9 +88,11 @@ class GpgKeyImportExporter
GpgImportInformation ImportKey(StdBypeArrayPtr inBuffer);
- bool ExportKeys(KeyIdArgsListPtr& uid_list, ByteArrayPtr& out_buffer) const;
+ bool ExportKeys(KeyIdArgsListPtr& uid_list, ByteArrayPtr& out_buffer,
+ bool secret = false) const;
- bool ExportKeys(const KeyArgsList& keys, ByteArrayPtr& outBuffer) const;
+ bool ExportKeys(const KeyArgsList& keys, ByteArrayPtr& outBuffer,
+ bool secret = false) const;
bool ExportKey(const GpgKey& key, ByteArrayPtr& out_buffer) const;
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index dd4973be..d61519d9 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -1,4 +1,5 @@
aux_source_directory(. UI_SOURCE)
+aux_source_directory(./aes UI_SOURCE)
aux_source_directory(./keypair_details UI_SOURCE)
aux_source_directory(./widgets UI_SOURCE)
aux_source_directory(./keygen UI_SOURCE)
@@ -19,11 +20,11 @@ target_link_libraries(${GPGFRONTEND_UI_LIB_NAME}
target_include_directories(gpgfrontend-ui PUBLIC
${CMAKE_CURRENT_BINARY_DIR}/${GPGFRONTEND_UI_LIB_NAME}_autogen/include)
-if(XCODE_BUILD)
-set_target_properties(gpgfrontend-ui
- PROPERTIES
- ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}
- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}
- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE})
-endif()
+if (XCODE_BUILD)
+ set_target_properties(gpgfrontend-ui
+ PROPERTIES
+ ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}
+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}
+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE})
+endif ()
target_compile_features(gpgfrontend-ui PUBLIC cxx_std_17) \ No newline at end of file
diff --git a/src/ui/KeyMgmt.cpp b/src/ui/KeyMgmt.cpp
index 99647571..bd5c91a9 100755
--- a/src/ui/KeyMgmt.cpp
+++ b/src/ui/KeyMgmt.cpp
@@ -33,15 +33,16 @@
#include "ui/UserInterfaceUtils.h"
#include "ui/keygen/SubkeyGenerateDialog.h"
#include "ui/settings/GlobalSettingStation.h"
+#include "ui/widgets/ExportKeyPackageDialog.h"
namespace GpgFrontend::UI {
KeyMgmt::KeyMgmt(QWidget* parent) : QMainWindow(parent) {
/* the list of Keys available*/
- mKeyList = new KeyList(true, this);
+ key_list_ = new KeyList(KeyMenuAbility::ALL, this);
- mKeyList->addListGroupTab(_("All"), KeyListRow::SECRET_OR_PUBLIC_KEY);
+ key_list_->addListGroupTab(_("All"), KeyListRow::SECRET_OR_PUBLIC_KEY);
- mKeyList->addListGroupTab(
+ key_list_->addListGroupTab(
_("Only Public Key"), KeyListRow::SECRET_OR_PUBLIC_KEY,
KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress |
KeyListColumn::Usage | KeyListColumn::Validity,
@@ -50,7 +51,7 @@ KeyMgmt::KeyMgmt(QWidget* parent) : QMainWindow(parent) {
!(key.revoked() || key.disabled() || key.expired());
});
- mKeyList->addListGroupTab(
+ key_list_->addListGroupTab(
_("Has Private Key"), KeyListRow::SECRET_OR_PUBLIC_KEY,
KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress |
KeyListColumn::Usage | KeyListColumn::Validity,
@@ -59,8 +60,8 @@ KeyMgmt::KeyMgmt(QWidget* parent) : QMainWindow(parent) {
!(key.revoked() || key.disabled() || key.expired());
});
- mKeyList->addListGroupTab(
- _("No Master Key"), KeyListRow::SECRET_OR_PUBLIC_KEY,
+ key_list_->addListGroupTab(
+ _("No Primary Key"), KeyListRow::SECRET_OR_PUBLIC_KEY,
KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress |
KeyListColumn::Usage | KeyListColumn::Validity,
[](const GpgKey& key) -> bool {
@@ -68,24 +69,24 @@ KeyMgmt::KeyMgmt(QWidget* parent) : QMainWindow(parent) {
!(key.revoked() || key.disabled() || key.expired());
});
- mKeyList->addListGroupTab(
+ key_list_->addListGroupTab(
_("Revoked"), KeyListRow::SECRET_OR_PUBLIC_KEY,
KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress |
KeyListColumn::Usage | KeyListColumn::Validity,
[](const GpgKey& key) -> bool { return key.revoked(); });
- mKeyList->addListGroupTab(
+ key_list_->addListGroupTab(
_("Expired"), KeyListRow::SECRET_OR_PUBLIC_KEY,
KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress |
KeyListColumn::Usage | KeyListColumn::Validity,
[](const GpgKey& key) -> bool { return key.expired(); });
- setCentralWidget(mKeyList);
- mKeyList->setDoubleClickedAction([this](const GpgKey& key, QWidget* parent) {
+ setCentralWidget(key_list_);
+ key_list_->setDoubleClickedAction([this](const GpgKey& key, QWidget* parent) {
new KeyDetailsDialog(key, parent);
});
- mKeyList->slotRefresh();
+ key_list_->slotRefresh();
createActions();
createMenus();
@@ -146,8 +147,8 @@ KeyMgmt::KeyMgmt(QWidget* parent) : QMainWindow(parent) {
this->statusBar()->show();
setWindowTitle(_("KeyPair Management"));
- mKeyList->addMenuAction(deleteSelectedKeysAct);
- mKeyList->addMenuAction(showKeyDetailsAct);
+ key_list_->addMenuAction(deleteSelectedKeysAct);
+ key_list_->addMenuAction(showKeyDetailsAct);
connect(this, SIGNAL(signalKeyStatusUpdated()), SignalStation::GetInstance(),
SIGNAL(KeyDatabaseRefresh()));
@@ -210,11 +211,11 @@ void KeyMgmt::createActions() {
connect(exportKeyToClipboardAct, SIGNAL(triggered()), this,
SLOT(slotExportKeyToClipboard()));
- exportKeyToFileAct = new QAction(_("Export To File"), this);
- exportKeyToFileAct->setIcon(QIcon(":export_key_to_file.png"));
- exportKeyToFileAct->setToolTip(_("Export Selected Key(s) To File"));
+ exportKeyToFileAct = new QAction(_("Export To Key Package"), this);
+ exportKeyToFileAct->setIcon(QIcon(":key_package.png"));
+ exportKeyToFileAct->setToolTip(_("Export Checked Key(s) To a Key Package"));
connect(exportKeyToFileAct, SIGNAL(triggered()), this,
- SLOT(slotExportKeyToFile()));
+ SLOT(slotExportKeyToKeyPackage()));
exportKeyAsOpenSSHFormat = new QAction(_("Export As OpenSSH"), this);
exportKeyAsOpenSSHFormat->setIcon(QIcon(":ssh-key.png"));
@@ -295,11 +296,11 @@ void KeyMgmt::createToolBars() {
}
void KeyMgmt::slotDeleteSelectedKeys() {
- deleteKeysWithWarning(mKeyList->getSelected());
+ deleteKeysWithWarning(key_list_->getSelected());
}
void KeyMgmt::slotDeleteCheckedKeys() {
- deleteKeysWithWarning(mKeyList->getChecked());
+ deleteKeysWithWarning(key_list_->getChecked());
}
void KeyMgmt::deleteKeysWithWarning(KeyIdArgsListPtr key_ids) {
@@ -337,7 +338,7 @@ void KeyMgmt::deleteKeysWithWarning(KeyIdArgsListPtr key_ids) {
}
void KeyMgmt::slotShowKeyDetails() {
- auto keys_selected = mKeyList->getSelected();
+ auto keys_selected = key_list_->getSelected();
if (keys_selected->empty()) return;
auto key = GpgKeyGetter::GetInstance().GetKey(keys_selected->front());
@@ -350,34 +351,22 @@ void KeyMgmt::slotShowKeyDetails() {
new KeyDetailsDialog(key);
}
-void KeyMgmt::slotExportKeyToFile() {
- ByteArrayPtr key_export_data = nullptr;
- auto keys_checked = mKeyList->getChecked();
- if (!GpgKeyImportExporter::GetInstance().ExportKeys(keys_checked,
- key_export_data)) {
- return;
- }
- auto key =
- GpgKeyGetter::GetInstance().GetKey(mKeyList->getSelected()->front());
- if (!key.good()) {
- QMessageBox::critical(nullptr, _("Error"), _("Key Not Found."));
+void KeyMgmt::slotExportKeyToKeyPackage() {
+ auto keys_checked = key_list_->getChecked();
+ if (keys_checked->empty()) {
+ QMessageBox::critical(
+ this, _("Error"),
+ _("Please check some keys before doing this operation."));
return;
}
- QString fileString = QString::fromStdString(key.name() + " " + key.email() +
- "(" + key.id() + ")_pub.asc");
-
- QString file_name = QFileDialog::getSaveFileName(
- this, _("Export Key To File"), fileString,
- QString(_("Key Files")) + " (*.asc *.txt);;All Files (*)");
-
- write_buffer_to_file(file_name.toStdString(), *key_export_data);
-
+ auto dialog = new ExportKeyPackageDialog(std::move(keys_checked), this);
+ dialog->exec();
emit signalStatusBarChanged(QString(_("key(s) exported")));
}
void KeyMgmt::slotExportKeyToClipboard() {
ByteArrayPtr key_export_data = nullptr;
- auto keys_checked = mKeyList->getChecked();
+ auto keys_checked = key_list_->getChecked();
if (!GpgKeyImportExporter::GetInstance().ExportKeys(keys_checked,
key_export_data)) {
return;
@@ -396,7 +385,7 @@ void KeyMgmt::closeEvent(QCloseEvent* event) {
}
void KeyMgmt::slotGenerateSubKey() {
- auto keys_selected = mKeyList->getSelected();
+ auto keys_selected = key_list_->getSelected();
if (keys_selected->empty()) {
QMessageBox::information(
nullptr, _("Invalid Operation"),
@@ -467,7 +456,7 @@ void KeyMgmt::slotSaveWindowState() {
void KeyMgmt::slotExportAsOpenSSHFormat() {
ByteArrayPtr key_export_data = nullptr;
- auto keys_checked = mKeyList->getChecked();
+ auto keys_checked = key_list_->getChecked();
if (keys_checked->empty()) {
QMessageBox::critical(nullptr, _("Error"), _("No Key Checked."));
diff --git a/src/ui/KeyMgmt.h b/src/ui/KeyMgmt.h
index 7edb1b5c..ae220481 100755
--- a/src/ui/KeyMgmt.h
+++ b/src/ui/KeyMgmt.h
@@ -44,7 +44,7 @@ class KeyMgmt : public QMainWindow {
void slotGenerateSubKey();
- void slotExportKeyToFile();
+ void slotExportKeyToKeyPackage();
void slotExportKeyToClipboard();
@@ -75,7 +75,7 @@ class KeyMgmt : public QMainWindow {
void deleteKeysWithWarning(GpgFrontend::KeyIdArgsListPtr uidList);
- KeyList* mKeyList;
+ KeyList* key_list_;
QMenu* fileMenu{};
QMenu* keyMenu{};
QMenu* generateKeyMenu{};
diff --git a/src/ui/MainWindow.cpp b/src/ui/MainWindow.cpp
index 422db814..fd3e6820 100644
--- a/src/ui/MainWindow.cpp
+++ b/src/ui/MainWindow.cpp
@@ -50,7 +50,8 @@ void MainWindow::init() noexcept {
setCentralWidget(edit);
/* the list of Keys available*/
- mKeyList = new KeyList(true, this);
+ mKeyList = new KeyList(
+ KeyMenuAbility::REFRESH | KeyMenuAbility::UNCHECK_ALL, this);
infoBoard = new InfoBoardWidget(this);
diff --git a/src/ui/aes/qaesencryption.cpp b/src/ui/aes/qaesencryption.cpp
new file mode 100644
index 00000000..9103fb8e
--- /dev/null
+++ b/src/ui/aes/qaesencryption.cpp
@@ -0,0 +1,626 @@
+#include "qaesencryption.h"
+#include <QDebug>
+#include <QVector>
+
+#ifdef USE_INTEL_AES_IF_AVAILABLE
+#include "aesni/aesni-key-exp.h"
+#include "aesni/aesni-enc-ecb.h"
+#include "aesni/aesni-enc-cbc.h"
+#endif
+
+/*
+ * 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)
+{
+ if (rawText.isEmpty())
+ return rawText;
+
+ 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:
+#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
+ ret.remove(ret.length() - ret.back(), ret.back());
+#else
+ ret.remove(ret.length() - ret.at(ret.length() - 1), ret.at(ret.length() - 1));
+#endif
+ break;
+ case Padding::ISO:
+ {
+ // Find the last byte which is not zero
+ int marker_index = ret.length() - 1;
+ for (; marker_index >= 0; --marker_index)
+ {
+ if (ret.at(marker_index) != 0x00)
+ {
+ break;
+ }
+ }
+
+ // And check if it's the byte for marking padding
+ if (ret.at(marker_index) == '\x80')
+ {
+ ret.truncate(marker_index);
+ }
+ break;
+ }
+ default:
+ //do nothing
+ break;
+ }
+ return ret;
+}
+/*
+ * End Static function declarations
+ * */
+
+/*
+ * Local Functions
+ * */
+
+namespace {
+
+quint8 xTime(quint8 x)
+{
+ return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
+}
+
+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 Local functions
+ * */
+
+QAESEncryption::QAESEncryption(Aes level, Mode mode,
+ Padding padding)
+ : m_nb(4), m_blocklen(16), m_level(level), m_mode(mode), m_padding(padding)
+ , m_aesNIAvailable(false), m_state(nullptr)
+{
+#ifdef USE_INTEL_AES_IF_AVAILABLE
+ m_aesNIAvailable = check_aesni_support();
+#endif
+
+ 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)
+{
+ int size = (alignment - currSize % alignment) % alignment;
+ switch(m_padding)
+ {
+ case Padding::ZERO:
+ return QByteArray(size, 0x00);
+ break;
+ case Padding::PKCS7:
+ if (size == 0)
+ size = alignment;
+ return QByteArray(size, size);
+ break;
+ case Padding::ISO:
+ if (size > 0)
+ return QByteArray (size - 1, 0x00).prepend('\x80');
+ break;
+ default:
+ return QByteArray(size, 0x00);
+ break;
+ }
+ return QByteArray();
+}
+
+QByteArray QAESEncryption::expandKey(const QByteArray &key)
+{
+
+#ifdef USE_INTEL_AES_IF_AVAILABLE
+ if (true){
+ switch(m_level) {
+ case AES_128: {
+ AES128 aes128;
+ quint8 ret[aes128.expandedKey];
+ memset(ret, 0x00, sizeof(ret));
+ quint8 uchar_key[key.size()];
+ memcpy(uchar_key, key.data(), key.size());
+ AES_128_Key_Expansion(uchar_key, ret);
+ return QByteArray((char*) ret, aes128.expandedKey);
+ }
+ break;
+ case AES_192: {
+ AES192 aes192;
+ quint8 ret[aes192.expandedKey];
+ memset(ret, 0x00, sizeof(ret));
+ quint8 uchar_key[key.size()];
+ memcpy(uchar_key, key.data(), key.size());
+
+ AES_192_Key_Expansion(uchar_key, ret);
+ return QByteArray((char*) ret, aes192.expandedKey);
+ }
+ break;
+ case AES_256: {
+ AES256 aes256;
+ quint8 ret[aes256.expandedKey];
+ memset(ret, 0x00, sizeof(ret));
+ quint8 uchar_key[key.size()];
+ memcpy(uchar_key, key.data(), key.size());
+
+ AES_256_Key_Expansion(uchar_key, ret);
+ return QByteArray((char*) ret, aes256.expandedKey);
+ }
+ break;
+ default:
+ return QByteArray();
+ break;
+ }
+ } else
+#endif
+ {
+
+ 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[7];
+ it[7] = (quint8)it[11];
+ it[11] = (quint8)it[15];
+ it[15] = (quint8)it[3];
+ it[3] = (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++)
+ for(int i = 0; i < std::min(a.size(), b.size()); 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::printArray(uchar* arr, int size)
+{
+ QByteArray print("");
+ for(int i=0; i<size; i++)
+ print.append(arr[i]);
+
+ return print.toHex();
+}
+
+QByteArray QAESEncryption::encode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv)
+{
+ if (m_mode >= CBC && (iv.isEmpty() || iv.size() != m_blocklen))
+ return QByteArray();
+
+ QByteArray expandedKey = expandKey(key);
+ QByteArray alignedText(rawText);
+
+ //Fill array with padding
+ alignedText.append(getPadding(rawText.size(), m_blocklen));
+
+ switch(m_mode)
+ {
+ case ECB: {
+#ifdef USE_INTEL_AES_IF_AVAILABLE
+ if (m_aesNIAvailable){
+ unsigned char in[alignedText.size()];
+ memcpy(in, alignedText.data(), alignedText.size());
+ unsigned char out[alignedText.size()];
+ memcpy(out, alignedText.data(), alignedText.size());
+ char expKey[expandedKey.size()];
+ memcpy(expKey, expandedKey.data(), expandedKey.size());
+ AES_ECB_encrypt(in, out, alignedText.size(),
+ expKey, m_nr);
+ return QByteArray((char*)out, alignedText.size());
+ }
+#endif
+ QByteArray ret;
+ for(int i=0; i < alignedText.size(); i+= m_blocklen)
+ ret.append(cipher(expandedKey, alignedText.mid(i, m_blocklen)));
+ return ret;
+ }
+ break;
+ case CBC: {
+#ifdef USE_INTEL_AES_IF_AVAILABLE
+ if (m_aesNIAvailable){
+ quint8 in[alignedText.size()];
+ memcpy(in, alignedText.constData(), alignedText.size());
+ quint8 ivec[iv.size()];
+ memcpy(ivec, iv.data(), iv.size());
+ char out[alignedText.size()];
+ memset(out, 0x00, alignedText.size());
+ char expKey[expandedKey.size()];
+ memcpy(expKey, expandedKey.data(), expandedKey.size());
+ AES_CBC_encrypt(in,
+ (unsigned char*) out,
+ ivec,
+ alignedText.size(),
+ expKey,
+ m_nr);
+ return QByteArray(out, alignedText.size());
+ }
+#endif
+ QByteArray ret;
+ QByteArray ivTemp(iv);
+ for(int i=0; i < alignedText.size(); i+= m_blocklen) {
+ 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);
+ }
+ return ret;
+ }
+ break;
+ case CFB: {
+ QByteArray ret;
+ ret.append(byteXor(alignedText.left(m_blocklen), cipher(expandedKey, iv)));
+ for(int i=0; i < alignedText.size(); i+= m_blocklen) {
+ if (i+m_blocklen < alignedText.size())
+ ret.append(byteXor(alignedText.mid(i+m_blocklen, m_blocklen),
+ cipher(expandedKey, ret.mid(i, m_blocklen))));
+ }
+ return ret;
+ }
+ break;
+ case OFB: {
+ QByteArray ret;
+ QByteArray ofbTemp;
+ ofbTemp.append(cipher(expandedKey, iv));
+ for (int i=m_blocklen; i < alignedText.size(); i += m_blocklen){
+ ofbTemp.append(cipher(expandedKey, ofbTemp.right(m_blocklen)));
+ }
+ ret.append(byteXor(alignedText, ofbTemp));
+ return ret;
+ }
+ break;
+ default: break;
+ }
+ return QByteArray();
+}
+
+QByteArray QAESEncryption::decode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv)
+{
+ if (m_mode >= CBC && (iv.isEmpty() || iv.size() != m_blocklen))
+ return QByteArray();
+
+ QByteArray ret;
+ QByteArray expandedKey = expandKey(key);
+
+ switch(m_mode)
+ {
+ case ECB:
+ for(int i=0; i < rawText.size(); i+= m_blocklen)
+ ret.append(invCipher(expandedKey, rawText.mid(i, m_blocklen)));
+ break;
+ case CBC: {
+ QByteArray ivTemp(iv);
+ for(int i=0; i < rawText.size(); i+= m_blocklen){
+ 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: {
+ ret.append(byteXor(rawText.mid(0, m_blocklen), cipher(expandedKey, iv)));
+ for(int i=0; i < rawText.size(); i+= m_blocklen){
+ if (i+m_blocklen < rawText.size()) {
+ ret.append(byteXor(rawText.mid(i+m_blocklen, m_blocklen),
+ cipher(expandedKey, rawText.mid(i, m_blocklen))));
+ }
+ }
+ }
+ break;
+ case OFB: {
+ QByteArray ofbTemp;
+ ofbTemp.append(cipher(expandedKey, iv));
+ for (int i=m_blocklen; i < rawText.size(); i += m_blocklen){
+ ofbTemp.append(cipher(expandedKey, ofbTemp.right(m_blocklen)));
+ }
+ ret.append(byteXor(rawText, ofbTemp));
+ }
+ break;
+ default:
+ //do nothing
+ break;
+ }
+ return ret;
+}
+
+QByteArray QAESEncryption::removePadding(const QByteArray &rawText)
+{
+ return RemovePadding(rawText, (Padding) m_padding);
+}
diff --git a/src/ui/aes/qaesencryption.h b/src/ui/aes/qaesencryption.h
new file mode 100644
index 00000000..cee70606
--- /dev/null
+++ b/src/ui/aes/qaesencryption.h
@@ -0,0 +1,155 @@
+#ifndef QAESENCRYPTION_H
+#define QAESENCRYPTION_H
+
+#ifdef QtAES_EXPORTS
+#include "qtaes_export.h"
+#else
+#define QTAESSHARED_EXPORT
+#endif
+
+#include <QObject>
+#include <QByteArray>
+
+#ifdef __linux__
+#ifndef __LP64__
+#define do_rdtsc _do_rdtsc
+#endif
+#endif
+
+class QTAESSHARED_EXPORT QAESEncryption : public QObject
+{
+ Q_OBJECT
+public:
+ enum Aes {
+ AES_128,
+ AES_192,
+ AES_256
+ };
+
+ enum Mode {
+ ECB,
+ CBC,
+ CFB,
+ OFB
+ };
+
+ enum Padding {
+ ZERO,
+ PKCS7,
+ ISO
+ };
+
+ static QByteArray Crypt(QAESEncryption::Aes level, QAESEncryption::Mode mode, const QByteArray &rawText, const QByteArray &key,
+ const QByteArray &iv = QByteArray(), QAESEncryption::Padding padding = QAESEncryption::ISO);
+ static QByteArray Decrypt(QAESEncryption::Aes level, QAESEncryption::Mode mode, const QByteArray &rawText, const QByteArray &key,
+ const QByteArray &iv = QByteArray(), 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::ISO);
+
+ QAESEncryption(QAESEncryption::Aes level, QAESEncryption::Mode mode,
+ QAESEncryption::Padding padding = QAESEncryption::ISO);
+
+ QByteArray encode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv = QByteArray());
+ QByteArray decode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv = QByteArray());
+ QByteArray removePadding(const QByteArray &rawText);
+ QByteArray expandKey(const QByteArray &key);
+
+ QByteArray printArray(uchar *arr, int size);
+Q_SIGNALS:
+
+public Q_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;
+ bool m_aesNIAvailable;
+ 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 &in);
+ QByteArray invCipher(const QByteArray &expKey, const QByteArray &in);
+ QByteArray byteXor(const QByteArray &a, const QByteArray &b);
+
+ 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[14] = {
+ 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab};
+};
+
+#endif // QAESENCRYPTION_H
diff --git a/src/ui/keypair_details/KeyUIDSignDialog.cpp b/src/ui/keypair_details/KeyUIDSignDialog.cpp
index eb459701..b43a119e 100644
--- a/src/ui/keypair_details/KeyUIDSignDialog.cpp
+++ b/src/ui/keypair_details/KeyUIDSignDialog.cpp
@@ -34,7 +34,7 @@ KeyUIDSignDialog::KeyUIDSignDialog(const GpgKey& key, UIDArgsListPtr uid,
QWidget* parent)
: QDialog(parent), mUids(std::move(uid)), mKey(key) {
const auto key_id = mKey.id();
- mKeyList = new KeyList(false, this);
+ mKeyList = new KeyList(KeyMenuAbility::NONE, this);
mKeyList->addListGroupTab(_("Signers"), KeyListRow::ONLY_SECRET_KEY,
KeyListColumn::NAME | KeyListColumn::EmailAddress,
[key_id](const GpgKey& key) -> bool {
diff --git a/src/ui/smtp/RecipientsPicker.cpp b/src/ui/smtp/RecipientsPicker.cpp
index ee6ac673..eaaa683a 100644
--- a/src/ui/smtp/RecipientsPicker.cpp
+++ b/src/ui/smtp/RecipientsPicker.cpp
@@ -33,7 +33,7 @@ GpgFrontend::UI::RecipientsPicker::RecipientsPicker(
connect(confirm_button, SIGNAL(clicked(bool)), this, SLOT(accept()));
// Setup KeyList
- key_list_ = new KeyList(false, this);
+ key_list_ = new KeyList(KeyMenuAbility::NONE, this);
key_list_->addListGroupTab(
_("Recipient(s)"), KeyListRow::SECRET_OR_PUBLIC_KEY,
KeyListColumn::NAME | KeyListColumn::EmailAddress,
diff --git a/src/ui/smtp/SenderPicker.cpp b/src/ui/smtp/SenderPicker.cpp
index 1cbd409f..fcd3ba61 100644
--- a/src/ui/smtp/SenderPicker.cpp
+++ b/src/ui/smtp/SenderPicker.cpp
@@ -33,7 +33,7 @@ GpgFrontend::UI::SenderPicker::SenderPicker(const KeyId& current_key_id,
connect(confirm_button, SIGNAL(clicked(bool)), this, SLOT(accept()));
// Setup KeyList
- key_list_ = new KeyList(false, this);
+ key_list_ = new KeyList(KeyMenuAbility::NONE, this);
key_list_->addListGroupTab(
_("Sender"), KeyListRow::ONLY_SECRET_KEY,
KeyListColumn::NAME | KeyListColumn::EmailAddress,
diff --git a/src/ui/widgets/ExportKeyPackageDialog.cpp b/src/ui/widgets/ExportKeyPackageDialog.cpp
new file mode 100644
index 00000000..b5eea82d
--- /dev/null
+++ b/src/ui/widgets/ExportKeyPackageDialog.cpp
@@ -0,0 +1,165 @@
+/**
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Foobar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from gpg4usb-team.
+ * Their source code version also complies with GNU General Public License.
+ *
+ * The source code version of this software was modified and released
+ * by Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ */
+
+#include "ExportKeyPackageDialog.h"
+
+#include <boost/format.hpp>
+
+#include "gpg/function/GpgKeyGetter.h"
+#include "gpg/function/GpgKeyImportExporter.h"
+#include "ui/aes/qaesencryption.h"
+#include "ui_ExportKeyPackageDialog.h"
+
+GpgFrontend::UI::ExportKeyPackageDialog::ExportKeyPackageDialog(
+ KeyIdArgsListPtr key_ids, QWidget* parent)
+ : QDialog(parent),
+ ui(std::make_shared<Ui_exportKeyPackageDialog>()),
+ key_ids_(std::move(key_ids)),
+ mt(rd()) {
+ ui->setupUi(this);
+
+ generate_key_package_name();
+
+ connect(ui->gnerateNameButton, &QPushButton::clicked, this,
+ [=]() { generate_key_package_name(); });
+
+ connect(ui->setOutputPathButton, &QPushButton::clicked, this, [=]() {
+ auto file_name = QFileDialog::getSaveFileName(
+ this, _("Export Key Package"), ui->nameValueLabel->text() + ".gfepack",
+ QString(_("Key Package")) + " (*.gfepack);;All Files (*)");
+ ui->outputPathLabel->setText(file_name);
+ });
+
+ connect(ui->generatePassphraseButton, &QPushButton::clicked, this, [=]() {
+ passphrase_ = generate_passphrase(32);
+ auto file_name = QFileDialog::getSaveFileName(
+ this, _("Export Key Package Passphrase"),
+ ui->nameValueLabel->text() + ".key",
+ QString(_("Key File")) + " (*.key);;All Files (*)");
+ ui->passphraseValueLabel->setText(file_name);
+ write_buffer_to_file(file_name.toStdString(), passphrase_);
+ });
+
+ connect(ui->buttonBox, &QDialogButtonBox::accepted, this, [=]() {
+ if (ui->outputPathLabel->text().isEmpty()) {
+ QMessageBox::critical(
+ nullptr, _("Forbidden"),
+ _("Please select an output path before exporting."));
+ return;
+ }
+
+ if (ui->passphraseValueLabel->text().isEmpty()) {
+ QMessageBox::critical(
+ nullptr, _("Forbidden"),
+ _("Please generate a password to protect your key before exporting, "
+ "it is very important. Don't forget to back up your password in a "
+ "safe place."));
+ return;
+ }
+ auto key_id_exported = std::make_unique<KeyIdArgsList>();
+ auto keys = GpgKeyGetter::GetInstance().GetKeys(key_ids_);
+ for (const auto& key : *keys) {
+ if (ui->noPublicKeyCheckBox->isChecked() && !key.is_private_key()) {
+ continue;
+ }
+ key_id_exported->push_back(key.id());
+ }
+
+ ByteArrayPtr key_export_data = nullptr;
+ if (!GpgKeyImportExporter::GetInstance().ExportKeys(
+ key_ids_, key_export_data,
+ ui->includeSecretKeyCheckBox->isChecked())) {
+ QMessageBox::critical(nullptr, _("Error"), _("Export Key(s) Failed."));
+ this->close();
+ return;
+ }
+
+ auto key = passphrase_;
+
+ QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::ECB);
+ auto encoded = encryption.encode(key_export_data->data(), key.data());
+
+ write_buffer_to_file(ui->outputPathLabel->text().toStdString(),
+ encoded.toStdString());
+
+ QMessageBox::information(
+ this, _("Success"),
+ QString(_(
+ "The Key Package has been successfully generated and has been "
+ "protected by encryption algorithms. You can safely transfer your "
+ "Key Package.")) +
+ "<b>" +
+ _("But the key file cannot be leaked under any "
+ "circumstances. Please delete the Key Package and key file as "
+ "soon "
+ "as possible after completing the transfer operation") +
+ "</b>");
+ });
+
+ connect(ui->buttonBox, &QDialogButtonBox::rejected, this,
+ [=]() { this->close(); });
+
+ ui->nameLabel->setText(_("Key Package Name"));
+ ui->selectOutputPathLabel->setText(_("Output Path"));
+ ui->passphraseLabel->setText(_("Passphrase"));
+ ui->tipsLabel->setText(
+ _("Tips: You can use Key Package to safely and conveniently transfer "
+ "your public and private keys between devices."));
+ ui->generatePassphraseButton->setText(_("Generate and Save Passphrase"));
+ ui->gnerateNameButton->setText(_("Generate Key Package Name"));
+ ui->setOutputPathButton->setText(_("Select Output Path"));
+
+ ui->includeSecretKeyCheckBox->setText(
+ _("Include secret key (Think twice before acting)"));
+ ui->noPublicKeyCheckBox->setText(
+ _("Exclude keys that do not have a private key"));
+
+ setAttribute(Qt::WA_DeleteOnClose);
+ setWindowTitle(_("exportKeyPackageDialog"));
+}
+
+std::string GpgFrontend::UI::ExportKeyPackageDialog::generate_passphrase(
+ const int len) {
+ std::uniform_int_distribution<int> dist(999, 99999);
+ static const char alphanum[] =
+ "0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz";
+ std::string tmp_str;
+ tmp_str.reserve(len);
+
+ for (int i = 0; i < len; ++i) {
+ tmp_str += alphanum[dist(mt) % (sizeof(alphanum) - 1)];
+ }
+
+ return tmp_str;
+}
+
+void GpgFrontend::UI::ExportKeyPackageDialog::generate_key_package_name() {
+ std::uniform_int_distribution<int> dist(999, 99999);
+ auto file_string = boost::format("KeyPackage_%1%") % dist(mt);
+ ui->nameValueLabel->setText(file_string.str().c_str());
+ ui->outputPathLabel->clear();
+ ui->passphraseValueLabel->clear();
+}
diff --git a/src/ui/widgets/ExportKeyPackageDialog.h b/src/ui/widgets/ExportKeyPackageDialog.h
new file mode 100644
index 00000000..a254b453
--- /dev/null
+++ b/src/ui/widgets/ExportKeyPackageDialog.h
@@ -0,0 +1,55 @@
+/**
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Foobar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from gpg4usb-team.
+ * Their source code version also complies with GNU General Public License.
+ *
+ * The source code version of this software was modified and released
+ * by Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ */
+
+#ifndef GPGFRONTEND_EXPORTKEYPACKAGEDIALOG_H
+#define GPGFRONTEND_EXPORTKEYPACKAGEDIALOG_H
+
+#include "GpgFrontendUI.h"
+
+class Ui_exportKeyPackageDialog;
+
+namespace GpgFrontend::UI {
+
+class ExportKeyPackageDialog : public QDialog {
+ Q_OBJECT
+
+ public:
+ explicit ExportKeyPackageDialog(KeyIdArgsListPtr key_ids, QWidget* parent);
+
+ std::string generate_passphrase(const int len);
+
+ private:
+ std::shared_ptr<Ui_exportKeyPackageDialog> ui;
+ KeyIdArgsListPtr key_ids_;
+
+ std::random_device rd;
+ std::mt19937 mt;
+
+ std::string passphrase_;
+
+ void generate_key_package_name();
+};
+} // namespace GpgFrontend::UI
+
+#endif // GPGFRONTEND_EXPORTKEYPACKAGEDIALOG_H
diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp
index 6dec19e7..02a8dd92 100644
--- a/src/ui/widgets/KeyList.cpp
+++ b/src/ui/widgets/KeyList.cpp
@@ -38,11 +38,11 @@ namespace GpgFrontend::UI {
int KeyList::key_list_id = 2048;
-KeyList::KeyList(bool menu, QWidget* parent)
+KeyList::KeyList(KeyMenuAbility::AbilityType menu_ability, QWidget* parent)
: QWidget(parent),
_m_key_list_id(key_list_id++),
ui(std::make_shared<Ui_KeyList>()),
- menu_status(menu) {
+ menu_ability_(menu_ability) {
init();
}
@@ -62,7 +62,11 @@ void KeyList::init() {
ui->setupUi(this);
- ui->menuWidget->setHidden(!menu_status);
+ ui->menuWidget->setHidden(!menu_ability_);
+ ui->refreshKeyListButton->setHidden(~menu_ability_ & KeyMenuAbility::REFRESH);
+ ui->syncButton->setHidden(~menu_ability_ & KeyMenuAbility::SYNC_PUBLIC_KEY);
+ ui->uncheckButton->setHidden(~menu_ability_ & KeyMenuAbility::UNCHECK_ALL);
+
ui->keyGroupTab->clear();
popupMenu = new QMenu(this);
@@ -73,6 +77,10 @@ void KeyList::init() {
SLOT(slotRefresh()));
connect(ui->refreshKeyListButton, &QPushButton::clicked, this,
&KeyList::slotRefresh);
+ connect(ui->uncheckButton, &QPushButton::clicked, this,
+ &KeyList::slotUncheckALL);
+ connect(ui->checkALLButton, &QPushButton::clicked, this,
+ &KeyList::slotCheckALL);
connect(ui->syncButton, &QPushButton::clicked, this,
&KeyList::slotSyncWithKeyServer);
connect(this, &KeyList::signalRefreshStatusBar, SignalStation::GetInstance(),
@@ -81,8 +89,16 @@ void KeyList::init() {
setAcceptDrops(true);
ui->refreshKeyListButton->setText(_("Refresh"));
+ ui->refreshKeyListButton->setToolTip(
+ _("Refresh the key list to synchronize changes."));
ui->syncButton->setText(_("Sync Public Key"));
- ui->syncButton->setToolTip(_("Sync public key with your default keyserver"));
+ ui->syncButton->setToolTip(_("Sync public key with your default keyserver."));
+ ui->uncheckButton->setText(_("Uncheck ALL"));
+ ui->uncheckButton->setToolTip(
+ _("Cancel all checked items in the current tab at once."));
+ ui->checkALLButton->setText(_("Check ALL"));
+ ui->checkALLButton->setToolTip(
+ _("Check all items in the current tab at once"));
}
void KeyList::addListGroupTab(
@@ -457,6 +473,32 @@ void KeyList::slotSyncWithKeyServer() {
});
}
+void KeyList::slotUncheckALL() {
+ auto key_list = qobject_cast<QTableWidget*>(ui->keyGroupTab->currentWidget());
+ if (key_list == nullptr) return;
+ if (!mKeyTables.empty()) {
+ for (auto& key_table : mKeyTables) {
+ if (key_table.key_list == key_list) {
+ key_table.UncheckALL();
+ break;
+ }
+ }
+ }
+}
+
+void KeyList::slotCheckALL() {
+ auto key_list = qobject_cast<QTableWidget*>(ui->keyGroupTab->currentWidget());
+ if (key_list == nullptr) return;
+ if (!mKeyTables.empty()) {
+ for (auto& key_table : mKeyTables) {
+ if (key_table.key_list == key_list) {
+ key_table.CheckALL();
+ break;
+ }
+ }
+ }
+}
+
KeyIdArgsListPtr& KeyTable::GetChecked() {
LOG(INFO) << "called";
if (checked_key_ids_ == nullptr)
@@ -597,4 +639,16 @@ void KeyTable::Refresh(KeyLinkListPtr m_keys) {
LOG(INFO) << "End";
}
+
+void KeyTable::UncheckALL() const {
+ for (int i = 0; i < key_list->rowCount(); i++) {
+ key_list->item(i, 0)->setCheckState(Qt::Unchecked);
+ }
+}
+
+void KeyTable::CheckALL() const {
+ for (int i = 0; i < key_list->rowCount(); i++) {
+ key_list->item(i, 0)->setCheckState(Qt::Checked);
+ }
+}
} // namespace GpgFrontend::UI
diff --git a/src/ui/widgets/KeyList.h b/src/ui/widgets/KeyList.h
index 8d6fb600..4b41decd 100644
--- a/src/ui/widgets/KeyList.h
+++ b/src/ui/widgets/KeyList.h
@@ -53,6 +53,17 @@ struct KeyListColumn {
static constexpr InfoType FingerPrint = 1 << 5;
};
+struct KeyMenuAbility {
+ using AbilityType = unsigned int;
+
+ static constexpr AbilityType ALL = ~0;
+ static constexpr AbilityType NONE = 0;
+ static constexpr AbilityType REFRESH = 1 << 0;
+ static constexpr AbilityType SYNC_PUBLIC_KEY = 1 << 1;
+ static constexpr AbilityType UNCHECK_ALL = 1 << 3;
+ static constexpr AbilityType CHECK_ALL = 1 << 5;
+};
+
struct KeyTable {
QTableWidget* key_list;
KeyListRow::KeyType select_type;
@@ -76,6 +87,10 @@ struct KeyTable {
KeyIdArgsListPtr& GetChecked();
+ void UncheckALL() const;
+
+ void CheckALL() const;
+
void SetChecked(KeyIdArgsListPtr key_ids);
};
@@ -83,7 +98,8 @@ class KeyList : public QWidget {
Q_OBJECT
public:
- explicit KeyList(bool menu, QWidget* parent = nullptr);
+ explicit KeyList(KeyMenuAbility::AbilityType menu_ability,
+ QWidget* parent = nullptr);
void addListGroupTab(
const QString& name,
@@ -124,6 +140,8 @@ class KeyList : public QWidget {
private:
void init();
void importKeys(const QByteArray& inBuffer);
+ void slotUncheckALL();
+ void slotCheckALL();
static int key_list_id;
int _m_key_list_id;
@@ -135,7 +153,7 @@ class KeyList : public QWidget {
QMenu* popupMenu{};
GpgFrontend::KeyLinkListPtr _buffered_keys_list;
std::function<void(const GpgKey&, QWidget*)> mAction = nullptr;
- bool menu_status = false;
+ KeyMenuAbility::AbilityType menu_ability_ = KeyMenuAbility::ALL;
private slots: