Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to compress database using zstd algorithm #11498

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ option(WITH_XC_BROWSER "Include browser integration with keepassxc-browser." OFF
option(WITH_XC_BROWSER_PASSKEYS "Passkeys support for browser integration." OFF)
option(WITH_XC_YUBIKEY "Include YubiKey support." OFF)
option(WITH_XC_SSHAGENT "Include SSH agent support." OFF)
option(WITH_XC_ZSTD "Include zstd compression support." OFF)
option(WITH_XC_KEESHARE "Sharing integration with KeeShare" OFF)
option(WITH_XC_UPDATECHECK "Include automatic update checks; disable for controlled distributions" ON)
if(UNIX AND NOT APPLE)
Expand Down Expand Up @@ -102,6 +103,7 @@ if(WITH_XC_ALL)
set(WITH_XC_BROWSER_PASSKEYS ON)
set(WITH_XC_YUBIKEY ON)
set(WITH_XC_SSHAGENT ON)
set(WITH_XC_ZSTD ON)
set(WITH_XC_KEESHARE ON)
if(UNIX AND NOT APPLE)
set(WITH_XC_FDOSECRETS ON)
Expand Down Expand Up @@ -575,6 +577,12 @@ if(WITH_XC_YUBIKEY)
endif()
endif()

if(WITH_XC_ZSTD)
find_library(ZSTD_LIBRARIES zstd REQUIRED)
find_path(ZSTD_INCLUDE_DIR zstd.h REQUIRED)
include_directories(SYSTEM ${ZSTD_INCLUDE_DIR})
endif()

if(UNIX)
check_cxx_source_compiles("#include <sys/prctl.h>
int main() { prctl(PR_SET_DUMPABLE, 0); return 0; }"
Expand Down
48 changes: 44 additions & 4 deletions share/translations/keepassxc_en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2119,10 +2119,6 @@ If you keep this number, your database will not be protected from brute force at
<source>Additional Database Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable compression (recommended)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Delete Recycle Bin</source>
<translation type="unfinished"></translation>
Expand Down Expand Up @@ -2229,6 +2225,22 @@ removed from the database.</source>
<source>Select Database Icon</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable compression:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>None</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>gzip (default)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>zstd</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidgetKeeShare</name>
Expand Down Expand Up @@ -4908,6 +4920,10 @@ If this reoccurs, then your database file may be corrupt.</source>
<extracomment>Translation: variant map = data structure for storing meta data</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported compression algorithm</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Kdbx4Writer</name>
Expand All @@ -4929,6 +4945,10 @@ If this reoccurs, then your database file may be corrupt.</source>
<extracomment>Translation comment: variant map = data structure for storing meta data</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported compression algorithm</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>KdbxReader</name>
Expand Down Expand Up @@ -9096,6 +9116,14 @@ This option is deprecated, use --set-key-file instead.</source>
<source>Internal zlib error when decompressing: </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Internal zstd error when decompressing: </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Internal zstd error when compressing: </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtIOCompressor::open</name>
Expand All @@ -9107,6 +9135,18 @@ This option is deprecated, use --set-key-file instead.</source>
<source>Internal zlib error: </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Internal zstd error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Internal zstd error: </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>this build doesn&apos;t ship zstd support</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RemoteHandler</name>
Expand Down
44 changes: 42 additions & 2 deletions share/translations/keepassxc_en_US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2068,8 +2068,20 @@ If you keep this number, your database will not be protected from brute force at
<translation>Additional Database Settings</translation>
</message>
<message>
<source>Enable compression (recommended)</source>
<translation>Enable compression (recommended)</translation>
<source>Enable compression:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>None</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>gzip (default)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>zstd</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Delete Recycle Bin</source>
Expand Down Expand Up @@ -4461,6 +4473,10 @@ If this reoccurs, then your database file may be corrupt.</translation>
<extracomment>Translation: variant map = data structure for storing meta data</extracomment>
<translation>Invalid variant map field type size</translation>
</message>
<message>
<source>Unsupported compression algorithm</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Kdbx4Writer</name>
Expand All @@ -4482,6 +4498,10 @@ If this reoccurs, then your database file may be corrupt.</translation>
<extracomment>Translation comment: variant map = data structure for storing meta data</extracomment>
<translation>Failed to serialize KDF parameters variant map</translation>
</message>
<message>
<source>Unsupported compression algorithm</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>KdbxReader</name>
Expand Down Expand Up @@ -8252,6 +8272,14 @@ Kernel: %3 %4</translation>
<source>Internal zlib error when decompressing: </source>
<translation>Internal zlib error when decompressing: </translation>
</message>
<message>
<source>Internal zstd error when decompressing: </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Internal zstd error when compressing: </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtIOCompressor::open</name>
Expand All @@ -8263,6 +8291,18 @@ Kernel: %3 %4</translation>
<source>Internal zlib error: </source>
<translation>Internal zlib error: </translation>
</message>
<message>
<source>this build doesn't ship zstd support</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Internal zstd error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Internal zstd error: </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ReportsWidgetBrowserStatistics</name>
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ add_feature_info(Passkeys WITH_XC_BROWSER_PASSKEYS "Passkeys support for browser
add_feature_info(SSHAgent WITH_XC_SSHAGENT "SSH agent integration compatible with KeeAgent")
add_feature_info(KeeShare WITH_XC_KEESHARE "Sharing integration with KeeShare")
add_feature_info(YubiKey WITH_XC_YUBIKEY "YubiKey HMAC-SHA1 challenge-response")
add_feature_info(Zstd WITH_XC_ZSTD "Database compression using zstd")
add_feature_info(UpdateCheck WITH_XC_UPDATECHECK "Automatic update checking")
if(UNIX AND NOT APPLE)
add_feature_info(FdoSecrets WITH_XC_FDOSECRETS "Implement freedesktop.org Secret Storage Spec server side API.")
Expand Down Expand Up @@ -367,6 +368,7 @@ target_link_libraries(keepassxc_core
${PCSC_LIBRARIES}
${ZXCVBN_LIBRARIES}
${ZLIB_LIBRARIES}
${ZSTD_LIBRARIES}
${MINIZIP_LIBRARIES}
${ARGON2_LIBRARIES}
${KEYUTILS_LIBRARIES}
Expand Down
1 change: 1 addition & 0 deletions src/config-keepassx.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#cmakedefine WITH_XC_DOCS
#cmakedefine WITH_XC_X11
#cmakedefine WITH_XC_BOTAN3
#cmakedefine WITH_XC_ZSTD

#cmakedefine KEEPASSXC_BUILD_TYPE "@KEEPASSXC_BUILD_TYPE@"
#cmakedefine KEEPASSXC_BUILD_TYPE_RELEASE
Expand Down
5 changes: 3 additions & 2 deletions src/core/Database.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ class Database : public ModifiableObject
enum CompressionAlgorithm
{
CompressionNone = 0,
CompressionGZip = 1
CompressionGZip = 1,
CompressionZstd = 2,
};
static const quint32 CompressionAlgorithmMax = CompressionGZip;
static const quint32 CompressionAlgorithmMax = CompressionZstd;

enum SaveAction
{
Expand Down
3 changes: 1 addition & 2 deletions src/format/Kdbx3Reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ bool Kdbx3Reader::readDatabaseImpl(QIODevice* device,
if (db->compressionAlgorithm() == Database::CompressionNone) {
xmlDevice = &hashedStream;
} else {
ioCompressor.reset(new QtIOCompressor(&hashedStream));
ioCompressor->setStreamFormat(QtIOCompressor::GzipFormat);
ioCompressor.reset(new QtIOCompressor(&hashedStream, QtIOCompressor::GzipFormatSpec{}));
if (!ioCompressor->open(QIODevice::ReadOnly)) {
raiseError(ioCompressor->errorString());
return false;
Expand Down
3 changes: 1 addition & 2 deletions src/format/Kdbx3Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,7 @@ bool Kdbx3Writer::writeDatabase(QIODevice* device, Database* db)
if (db->compressionAlgorithm() == Database::CompressionNone) {
outputDevice = &hashedStream;
} else {
ioCompressor.reset(new QtIOCompressor(&hashedStream));
ioCompressor->setStreamFormat(QtIOCompressor::GzipFormat);
ioCompressor.reset(new QtIOCompressor(&hashedStream, QtIOCompressor::GzipFormatSpec{}));
if (!ioCompressor->open(QIODevice::WriteOnly)) {
raiseError(ioCompressor->errorString());
return false;
Expand Down
18 changes: 14 additions & 4 deletions src/format/Kdbx4Reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,21 @@ bool Kdbx4Reader::readDatabaseImpl(QIODevice* device,
QIODevice* xmlDevice = nullptr;
QScopedPointer<QtIOCompressor> ioCompressor;

if (db->compressionAlgorithm() == Database::CompressionNone) {
switch (db->compressionAlgorithm()) {
case Database::CompressionNone:
xmlDevice = &cipherStream;
} else {
ioCompressor.reset(new QtIOCompressor(&cipherStream));
ioCompressor->setStreamFormat(QtIOCompressor::GzipFormat);
break;
case Database::CompressionGZip:
ioCompressor.reset(new QtIOCompressor(&cipherStream, QtIOCompressor::GzipFormatSpec{}));
break;
case Database::CompressionZstd:
ioCompressor.reset(new QtIOCompressor(&cipherStream, QtIOCompressor::ZstdFormatSpec{}));
break;
default:
raiseError(tr("Unsupported compression algorithm"));
return false;
}
if (ioCompressor) {
if (!ioCompressor->open(QIODevice::ReadOnly)) {
raiseError(ioCompressor->errorString());
return false;
Expand Down
18 changes: 14 additions & 4 deletions src/format/Kdbx4Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,21 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
QIODevice* outputDevice = nullptr;
QScopedPointer<QtIOCompressor> ioCompressor;

if (db->compressionAlgorithm() == Database::CompressionNone) {
switch (db->compressionAlgorithm()) {
case Database::CompressionNone:
outputDevice = cipherStream.data();
} else {
ioCompressor.reset(new QtIOCompressor(cipherStream.data()));
ioCompressor->setStreamFormat(QtIOCompressor::GzipFormat);
break;
case Database::CompressionGZip:
ioCompressor.reset(new QtIOCompressor(cipherStream.data(), QtIOCompressor::GzipFormatSpec{}));
break;
case Database::CompressionZstd:
ioCompressor.reset(new QtIOCompressor(cipherStream.data(), QtIOCompressor::ZstdFormatSpec{}));
break;
default:
raiseError(tr("Unsupported compression algorithm"));
return false;
}
if (ioCompressor) {
if (!ioCompressor->open(QIODevice::WriteOnly)) {
raiseError(ioCompressor->errorString());
return false;
Expand Down
3 changes: 1 addition & 2 deletions src/format/KdbxXmlReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1157,8 +1157,7 @@ QByteArray KdbxXmlReader::readCompressedBinary()
QBuffer buffer(&rawData);
buffer.open(QIODevice::ReadOnly);

QtIOCompressor compressor(&buffer);
compressor.setStreamFormat(QtIOCompressor::GzipFormat);
QtIOCompressor compressor(&buffer, QtIOCompressor::GzipFormatSpec{});
compressor.open(QIODevice::ReadOnly);

QByteArray result;
Expand Down
3 changes: 1 addition & 2 deletions src/format/KdbxXmlWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,7 @@ void KdbxXmlWriter::writeBinaries()
QBuffer buffer;
buffer.open(QIODevice::ReadWrite);

QtIOCompressor compressor(&buffer);
compressor.setStreamFormat(QtIOCompressor::GzipFormat);
QtIOCompressor compressor(&buffer, QtIOCompressor::GzipFormatSpec{});
compressor.open(QIODevice::WriteOnly);

qint64 bytesWritten = compressor.write(i.value());
Expand Down
4 changes: 4 additions & 0 deletions src/format/KeePass2Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ quint32 KeePass2Writer::kdbxVersionRequired(Database const* db, bool ignoreCurre
}
}

if (db->compressionAlgorithm() == Database::CompressionZstd) {
VERSION_MAX(version, KeePass2::FILE_VERSION_4_1)
}

return version;
}

Expand Down
16 changes: 13 additions & 3 deletions src/gui/dbsettings/DatabaseSettingsWidgetGeneral.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "DatabaseSettingsWidgetGeneral.h"
#include "ui_DatabaseSettingsWidgetGeneral.h"

#include "config-keepassx.h"

#include <QColorDialog>
#include <QDialogButtonBox>
#include <QInputDialog>
Expand Down Expand Up @@ -56,7 +58,15 @@ void DatabaseSettingsWidgetGeneral::initialize()
m_ui->dbDescriptionEdit->setText(meta->description());
m_ui->recycleBinEnabledCheckBox->setChecked(meta->recycleBinEnabled());
m_ui->defaultUsernameEdit->setText(meta->defaultUserName());
m_ui->compressionCheckbox->setChecked(m_db->compressionAlgorithm() != Database::CompressionNone);

m_ui->compressionCombobox->clear();
m_ui->compressionCombobox->addItem(tr("None"), Database::CompressionNone);
m_ui->compressionCombobox->addItem(tr("gzip (default)"), Database::CompressionGZip);
#ifdef WITH_XC_ZSTD
if (m_db->formatVersion() >= KeePass2::FILE_VERSION_4)
m_ui->compressionCombobox->addItem(tr("zstd"), Database::CompressionZstd);
#endif
m_ui->compressionCombobox->setCurrentIndex(m_db->compressionAlgorithm());

m_ui->dbPublicName->setText(m_db->publicName());
setupPublicColorButton(m_db->publicColor());
Expand Down Expand Up @@ -123,8 +133,8 @@ bool DatabaseSettingsWidgetGeneral::saveSettings()
meta->setRecycleBin(nullptr);
}

m_db->setCompressionAlgorithm(m_ui->compressionCheckbox->isChecked() ? Database::CompressionGZip
: Database::CompressionNone);
m_db->setCompressionAlgorithm(
static_cast<Database::CompressionAlgorithm>(m_ui->compressionCombobox->currentData().toInt()));

meta->setName(m_ui->dbNameEdit->text());
meta->setDescription(m_ui->dbDescriptionEdit->text());
Expand Down
Loading