<feature, refactor>(core, ui): Key package generate.
1. refactor GpgKeyImportExporter to meet with key package generation. 2. add ExportKeyPackageDialog. 3. add Qt AES ability. 4. refactor Key List to provide menu ability control. 5. add check all and uncheck all ability to key list menu.
This commit is contained in:
parent
efabb4fa3d
commit
c20c7b9bb8
@ -231,7 +231,7 @@ endif ()
|
||||
# Basic Envirnoment Configure
|
||||
set(BASIC_ENV_CONFIG 1)
|
||||
set(QT_MOC_CONFIG 1)
|
||||
set(ESAY_LOGGING_PP 1)
|
||||
set(EASY_LOGGING_PP 1)
|
||||
|
||||
if (LINUX_INSTALL_SOFTWARE)
|
||||
include(GNUInstallDirs)
|
||||
|
@ -45,6 +45,7 @@
|
||||
<file alias="key_generate.png">resource/icons/key_generate.png</file>
|
||||
<file alias="key_import.png">resource/icons/key_import.png</file>
|
||||
<file alias="kgpg_key2.png">resource/icons/kgpg_key2.png</file>
|
||||
<file alias="key_package.png">resource/icons/key_package.png</file>
|
||||
<file alias="misc_doc.png">resource/icons/misc_doc.png</file>
|
||||
<file alias="quote.png">resource/icons/quote.png</file>
|
||||
<file alias="signature.png">resource/icons/signature.png</file>
|
||||
|
BIN
resource/icons/key_package.png
Normal file
BIN
resource/icons/key_package.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
@ -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)) {
|
||||
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;
|
||||
}
|
||||
auto key =
|
||||
GpgKeyGetter::GetInstance().GetKey(mKeyList->getSelected()->front());
|
||||
if (!key.good()) {
|
||||
QMessageBox::critical(nullptr, _("Error"), _("Key Not Found."));
|
||||
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."));
|
||||
|
@ -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{};
|
||||
|
@ -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);
|
||||
|
||||
|
626
src/ui/aes/qaesencryption.cpp
Normal file
626
src/ui/aes/qaesencryption.cpp
Normal file
@ -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);
|
||||
}
|
155
src/ui/aes/qaesencryption.h
Normal file
155
src/ui/aes/qaesencryption.h
Normal file
@ -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
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
165
src/ui/widgets/ExportKeyPackageDialog.cpp
Normal file
165
src/ui/widgets/ExportKeyPackageDialog.cpp
Normal file
@ -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<eric@bktus.com> 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();
|
||||
}
|
55
src/ui/widgets/ExportKeyPackageDialog.h
Normal file
55
src/ui/widgets/ExportKeyPackageDialog.h
Normal file
@ -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<eric@bktus.com> 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
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
2
third_party/CMakeLists.txt
vendored
2
third_party/CMakeLists.txt
vendored
@ -1,4 +1,4 @@
|
||||
if (ESAY_LOGGING_PP)
|
||||
if (EASY_LOGGING_PP)
|
||||
message(STATUS "Build easyloggingpp")
|
||||
add_subdirectory(easyloggingpp)
|
||||
endif ()
|
||||
|
207
ui/ExportKeyPackageDialog.ui
Normal file
207
ui/ExportKeyPackageDialog.ui
Normal file
@ -0,0 +1,207 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>exportKeyPackageDialog</class>
|
||||
<widget class="QDialog" name="exportKeyPackageDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>527</width>
|
||||
<height>385</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Export As Key Package</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="nameLabel">
|
||||
<property name="text">
|
||||
<string>Key Package Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="gnerateNameButton">
|
||||
<property name="text">
|
||||
<string>Generate Key Package Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="nameValueLabel">
|
||||
<property name="text">
|
||||
<string>KeyPackage_0000</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="selectOutputPathLabel">
|
||||
<property name="text">
|
||||
<string>Output Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="setOutputPathButton">
|
||||
<property name="text">
|
||||
<string>Select Output Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="outputPathLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="passphraseLabel">
|
||||
<property name="text">
|
||||
<string>Passphrase</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="generatePassphraseButton">
|
||||
<property name="text">
|
||||
<string>Generate and Save Passphrase</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="passphraseValueLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="includeSecretKeyCheckBox">
|
||||
<property name="text">
|
||||
<string>Include secret key (Think twice before acting)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="noPublicKeyCheckBox">
|
||||
<property name="text">
|
||||
<string>Exclude keys that do not have a private key</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="tipsLabel">
|
||||
<property name="text">
|
||||
<string>Tips: You can use Key Package to safely and conveniently transfer your public and private keys between devices.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>exportKeyPackageDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>exportKeyPackageDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -46,7 +46,21 @@
|
||||
<item>
|
||||
<widget class="QPushButton" name="syncButton">
|
||||
<property name="text">
|
||||
<string>Sync With Key Server</string>
|
||||
<string>Sync Public Key</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="uncheckButton">
|
||||
<property name="text">
|
||||
<string>Uncheck ALL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="checkALLButton">
|
||||
<property name="text">
|
||||
<string>Check ALL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
Loading…
Reference in New Issue
Block a user