mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-07-29 09:38:48 -04:00
Formatting the code.
This commit is contained in:
parent
74efc57369
commit
8324d03f0a
294 changed files with 3796 additions and 3740 deletions
|
@ -18,19 +18,21 @@
|
|||
|
||||
#include "Kdbx3Reader.h"
|
||||
|
||||
#include "core/Group.h"
|
||||
#include "core/Endian.h"
|
||||
#include "core/Group.h"
|
||||
#include "crypto/CryptoHash.h"
|
||||
#include "format/KeePass2RandomStream.h"
|
||||
#include "format/KdbxXmlReader.h"
|
||||
#include "format/KeePass2RandomStream.h"
|
||||
#include "streams/HashedBlockStream.h"
|
||||
#include "streams/QtIOCompressor"
|
||||
#include "streams/SymmetricCipherStream.h"
|
||||
|
||||
#include <QBuffer>
|
||||
|
||||
Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device, const QByteArray& headerData,
|
||||
const CompositeKey& key, bool keepDatabase)
|
||||
Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device,
|
||||
const QByteArray& headerData,
|
||||
const CompositeKey& key,
|
||||
bool keepDatabase)
|
||||
{
|
||||
Q_ASSERT(m_kdbxVersion <= KeePass2::FILE_VERSION_3_1);
|
||||
|
||||
|
@ -39,8 +41,8 @@ Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea
|
|||
}
|
||||
|
||||
// check if all required headers were present
|
||||
if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty()
|
||||
|| m_streamStartBytes.isEmpty() || m_protectedStreamKey.isEmpty()
|
||||
if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty() || m_streamStartBytes.isEmpty()
|
||||
|| m_protectedStreamKey.isEmpty()
|
||||
|| m_db->cipher().isNull()) {
|
||||
raiseError(tr("missing database headers"));
|
||||
return nullptr;
|
||||
|
@ -63,8 +65,8 @@ Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea
|
|||
QByteArray finalKey = hash.result();
|
||||
|
||||
SymmetricCipher::Algorithm cipher = SymmetricCipher::cipherToAlgorithm(m_db->cipher());
|
||||
SymmetricCipherStream cipherStream(device, cipher,
|
||||
SymmetricCipher::algorithmMode(cipher), SymmetricCipher::Decrypt);
|
||||
SymmetricCipherStream cipherStream(
|
||||
device, cipher, SymmetricCipher::algorithmMode(cipher), SymmetricCipher::Decrypt);
|
||||
if (!cipherStream.init(finalKey, m_encryptionIV)) {
|
||||
raiseError(cipherStream.errorString());
|
||||
return nullptr;
|
||||
|
|
|
@ -24,13 +24,15 @@
|
|||
/**
|
||||
* KDBX 2/3 reader implementation.
|
||||
*/
|
||||
class Kdbx3Reader: public KdbxReader
|
||||
class Kdbx3Reader : public KdbxReader
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx3Reader)
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx3Reader)
|
||||
|
||||
public:
|
||||
Database* readDatabaseImpl(QIODevice* device, const QByteArray& headerData,
|
||||
const CompositeKey& key, bool keepDatabase) override;
|
||||
Database* readDatabaseImpl(QIODevice* device,
|
||||
const QByteArray& headerData,
|
||||
const CompositeKey& key,
|
||||
bool keepDatabase) override;
|
||||
|
||||
protected:
|
||||
bool readHeaderField(StoreDataStream& headerStream) override;
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
#include "core/Database.h"
|
||||
#include "crypto/CryptoHash.h"
|
||||
#include "crypto/Random.h"
|
||||
#include "format/KdbxXmlWriter.h"
|
||||
#include "format/KeePass2.h"
|
||||
#include "format/KeePass2RandomStream.h"
|
||||
#include "format/KdbxXmlWriter.h"
|
||||
#include "streams/HashedBlockStream.h"
|
||||
#include "streams/QtIOCompressor"
|
||||
#include "streams/SymmetricCipherStream.h"
|
||||
|
@ -65,23 +65,27 @@ bool Kdbx3Writer::writeDatabase(QIODevice* device, Database* db)
|
|||
|
||||
writeMagicNumbers(&header, KeePass2::SIGNATURE_1, KeePass2::SIGNATURE_2, KeePass2::FILE_VERSION_3_1);
|
||||
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray()));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::CompressionFlags,
|
||||
Endian::sizedIntToBytes<qint32>(db->compressionAlgo(),
|
||||
KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(
|
||||
writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray()));
|
||||
CHECK_RETURN_FALSE(
|
||||
writeHeaderField<quint16>(&header,
|
||||
KeePass2::HeaderFieldID::CompressionFlags,
|
||||
Endian::sizedIntToBytes<qint32>(db->compressionAlgo(), KeePass2::BYTEORDER)));
|
||||
auto kdf = db->kdf();
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::MasterSeed, masterSeed));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::TransformSeed, kdf->seed()));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::TransformRounds,
|
||||
Endian::sizedIntToBytes<qint64>(kdf->rounds(),
|
||||
KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header,
|
||||
KeePass2::HeaderFieldID::TransformRounds,
|
||||
Endian::sizedIntToBytes<qint64>(kdf->rounds(), KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::EncryptionIV, encryptionIV));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::ProtectedStreamKey, protectedStreamKey));
|
||||
CHECK_RETURN_FALSE(
|
||||
writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::ProtectedStreamKey, protectedStreamKey));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::StreamStartBytes, startBytes));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::InnerRandomStreamID,
|
||||
Endian::sizedIntToBytes<qint32>(static_cast<qint32>(
|
||||
KeePass2::ProtectedStreamAlgo::Salsa20),
|
||||
KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint16>(
|
||||
&header,
|
||||
KeePass2::HeaderFieldID::InnerRandomStreamID,
|
||||
Endian::sizedIntToBytes<qint32>(static_cast<qint32>(KeePass2::ProtectedStreamAlgo::Salsa20),
|
||||
KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::EndOfHeader, endOfHeader));
|
||||
header.close();
|
||||
|
||||
|
@ -93,8 +97,7 @@ bool Kdbx3Writer::writeDatabase(QIODevice* device, Database* db)
|
|||
|
||||
// write cipher stream
|
||||
SymmetricCipher::Algorithm algo = SymmetricCipher::cipherToAlgorithm(db->cipher());
|
||||
SymmetricCipherStream cipherStream(device, algo,
|
||||
SymmetricCipher::algorithmMode(algo), SymmetricCipher::Encrypt);
|
||||
SymmetricCipherStream cipherStream(device, algo, SymmetricCipher::algorithmMode(algo), SymmetricCipher::Encrypt);
|
||||
cipherStream.init(finalKey, encryptionIV);
|
||||
if (!cipherStream.open(QIODevice::WriteOnly)) {
|
||||
raiseError(cipherStream.errorString());
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
/**
|
||||
* KDBX2/3 writer implementation.
|
||||
*/
|
||||
class Kdbx3Writer: public KdbxWriter
|
||||
class Kdbx3Writer : public KdbxWriter
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx3Writer)
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx3Writer)
|
||||
|
||||
public:
|
||||
bool writeDatabase(QIODevice* device, Database* db) override;
|
||||
|
|
|
@ -19,17 +19,19 @@
|
|||
|
||||
#include <QBuffer>
|
||||
|
||||
#include "core/Group.h"
|
||||
#include "core/Endian.h"
|
||||
#include "core/Group.h"
|
||||
#include "crypto/CryptoHash.h"
|
||||
#include "format/KeePass2RandomStream.h"
|
||||
#include "format/KdbxXmlReader.h"
|
||||
#include "format/KeePass2RandomStream.h"
|
||||
#include "streams/HmacBlockStream.h"
|
||||
#include "streams/QtIOCompressor"
|
||||
#include "streams/SymmetricCipherStream.h"
|
||||
|
||||
Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, const QByteArray& headerData,
|
||||
const CompositeKey& key, bool keepDatabase)
|
||||
Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device,
|
||||
const QByteArray& headerData,
|
||||
const CompositeKey& key,
|
||||
bool keepDatabase)
|
||||
{
|
||||
Q_ASSERT(m_kdbxVersion == KeePass2::FILE_VERSION_4);
|
||||
|
||||
|
@ -40,9 +42,7 @@ Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea
|
|||
}
|
||||
|
||||
// check if all required headers were present
|
||||
if (m_masterSeed.isEmpty()
|
||||
|| m_encryptionIV.isEmpty()
|
||||
|| m_db->cipher().isNull()) {
|
||||
if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty() || m_db->cipher().isNull()) {
|
||||
raiseError(tr("missing database headers"));
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -69,8 +69,8 @@ Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea
|
|||
}
|
||||
|
||||
QByteArray hmacKey = KeePass2::hmacKey(m_masterSeed, m_db->transformedMasterKey());
|
||||
if (headerHmac != CryptoHash::hmac(headerData,
|
||||
HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey), CryptoHash::Sha256)) {
|
||||
if (headerHmac
|
||||
!= CryptoHash::hmac(headerData, HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey), CryptoHash::Sha256)) {
|
||||
raiseError(tr("Wrong key or database file is corrupt. (HMAC mismatch)"));
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -85,8 +85,8 @@ Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea
|
|||
raiseError(tr("Unknown cipher"));
|
||||
return nullptr;
|
||||
}
|
||||
SymmetricCipherStream cipherStream(&hmacStream, cipher,
|
||||
SymmetricCipher::algorithmMode(cipher), SymmetricCipher::Decrypt);
|
||||
SymmetricCipherStream cipherStream(
|
||||
&hmacStream, cipher, SymmetricCipher::algorithmMode(cipher), SymmetricCipher::Decrypt);
|
||||
if (!cipherStream.init(finalKey, m_encryptionIV)) {
|
||||
raiseError(cipherStream.errorString());
|
||||
return nullptr;
|
||||
|
@ -304,8 +304,8 @@ bool Kdbx4Reader::readInnerHeaderField(QIODevice* device)
|
|||
QVariantMap Kdbx4Reader::readVariantMap(QIODevice* device)
|
||||
{
|
||||
bool ok;
|
||||
quint16 version = Endian::readSizedInt<quint16>(device, KeePass2::BYTEORDER, &ok)
|
||||
& KeePass2::VARIANTMAP_CRITICAL_MASK;
|
||||
quint16 version =
|
||||
Endian::readSizedInt<quint16>(device, KeePass2::BYTEORDER, &ok) & KeePass2::VARIANTMAP_CRITICAL_MASK;
|
||||
quint16 maxVersion = KeePass2::VARIANTMAP_VERSION & KeePass2::VARIANTMAP_CRITICAL_MASK;
|
||||
if (!ok || (version > maxVersion)) {
|
||||
//: Translation: variant map = data structure for storing meta data
|
||||
|
|
|
@ -27,11 +27,13 @@
|
|||
*/
|
||||
class Kdbx4Reader : public KdbxReader
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx4Reader)
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx4Reader)
|
||||
|
||||
public:
|
||||
Database* readDatabaseImpl(QIODevice* device, const QByteArray& headerData,
|
||||
const CompositeKey& key, bool keepDatabase) override;
|
||||
Database* readDatabaseImpl(QIODevice* device,
|
||||
const QByteArray& headerData,
|
||||
const CompositeKey& key,
|
||||
bool keepDatabase) override;
|
||||
QHash<QByteArray, QString> binaryPoolInverse() const;
|
||||
QHash<QString, QByteArray> binaryPool() const;
|
||||
|
||||
|
|
|
@ -20,14 +20,14 @@
|
|||
#include <QBuffer>
|
||||
#include <QFile>
|
||||
|
||||
#include "streams/HmacBlockStream.h"
|
||||
#include "core/CustomData.h"
|
||||
#include "core/Database.h"
|
||||
#include "core/Metadata.h"
|
||||
#include "core/CustomData.h"
|
||||
#include "crypto/CryptoHash.h"
|
||||
#include "crypto/Random.h"
|
||||
#include "format/KeePass2RandomStream.h"
|
||||
#include "format/KdbxXmlWriter.h"
|
||||
#include "format/KeePass2RandomStream.h"
|
||||
#include "streams/HmacBlockStream.h"
|
||||
#include "streams/QtIOCompressor"
|
||||
#include "streams/SymmetricCipherStream.h"
|
||||
|
||||
|
@ -73,10 +73,12 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
|
|||
|
||||
writeMagicNumbers(&header, KeePass2::SIGNATURE_1, KeePass2::SIGNATURE_2, KeePass2::FILE_VERSION_4);
|
||||
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray()));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::CompressionFlags,
|
||||
Endian::sizedIntToBytes(static_cast<int>(db->compressionAlgo()),
|
||||
KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(
|
||||
writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray()));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint32>(
|
||||
&header,
|
||||
KeePass2::HeaderFieldID::CompressionFlags,
|
||||
Endian::sizedIntToBytes(static_cast<int>(db->compressionAlgo()), KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::MasterSeed, masterSeed));
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::EncryptionIV, encryptionIV));
|
||||
|
||||
|
@ -94,8 +96,8 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
|
|||
if (!publicCustomData.isEmpty()) {
|
||||
QByteArray serialized;
|
||||
serializeVariantMap(publicCustomData, serialized);
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint32>(
|
||||
&header, KeePass2::HeaderFieldID::PublicCustomData, serialized));
|
||||
CHECK_RETURN_FALSE(
|
||||
writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::PublicCustomData, serialized));
|
||||
}
|
||||
|
||||
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::EndOfHeader, endOfHeader));
|
||||
|
@ -109,8 +111,8 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
|
|||
|
||||
// write HMAC-authenticated cipher stream
|
||||
QByteArray hmacKey = KeePass2::hmacKey(masterSeed, db->transformedMasterKey());
|
||||
QByteArray headerHmac = CryptoHash::hmac(headerData, HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey),
|
||||
CryptoHash::Sha256);
|
||||
QByteArray headerHmac =
|
||||
CryptoHash::hmac(headerData, HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey), CryptoHash::Sha256);
|
||||
CHECK_RETURN_FALSE(writeData(device, headerHash));
|
||||
CHECK_RETURN_FALSE(writeData(device, headerHmac));
|
||||
|
||||
|
@ -123,9 +125,8 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
|
|||
return false;
|
||||
}
|
||||
|
||||
cipherStream.reset(new SymmetricCipherStream(hmacBlockStream.data(), algo,
|
||||
SymmetricCipher::algorithmMode(algo),
|
||||
SymmetricCipher::Encrypt));
|
||||
cipherStream.reset(new SymmetricCipherStream(
|
||||
hmacBlockStream.data(), algo, SymmetricCipher::algorithmMode(algo), SymmetricCipher::Encrypt));
|
||||
|
||||
if (!cipherStream->init(finalKey, encryptionIV)) {
|
||||
raiseError(cipherStream->errorString());
|
||||
|
@ -153,11 +154,12 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
|
|||
|
||||
Q_ASSERT(outputDevice);
|
||||
|
||||
CHECK_RETURN_FALSE(writeInnerHeaderField(outputDevice, KeePass2::InnerHeaderFieldID::InnerRandomStreamID,
|
||||
Endian::sizedIntToBytes(static_cast<int>(KeePass2::ProtectedStreamAlgo::ChaCha20),
|
||||
KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(writeInnerHeaderField(outputDevice, KeePass2::InnerHeaderFieldID::InnerRandomStreamKey,
|
||||
protectedStreamKey));
|
||||
CHECK_RETURN_FALSE(writeInnerHeaderField(
|
||||
outputDevice,
|
||||
KeePass2::InnerHeaderFieldID::InnerRandomStreamID,
|
||||
Endian::sizedIntToBytes(static_cast<int>(KeePass2::ProtectedStreamAlgo::ChaCha20), KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(
|
||||
writeInnerHeaderField(outputDevice, KeePass2::InnerHeaderFieldID::InnerRandomStreamKey, protectedStreamKey));
|
||||
|
||||
// Write attachments to the inner header
|
||||
writeAttachments(outputDevice, db);
|
||||
|
@ -208,7 +210,8 @@ bool Kdbx4Writer::writeInnerHeaderField(QIODevice* device, KeePass2::InnerHeader
|
|||
QByteArray fieldIdArr;
|
||||
fieldIdArr[0] = static_cast<char>(fieldId);
|
||||
CHECK_RETURN_FALSE(writeData(device, fieldIdArr));
|
||||
CHECK_RETURN_FALSE(writeData(device, Endian::sizedIntToBytes(static_cast<quint32>(data.size()), KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(
|
||||
writeData(device, Endian::sizedIntToBytes(static_cast<quint32>(data.size()), KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(writeData(device, data));
|
||||
|
||||
return true;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
*/
|
||||
class Kdbx4Writer : public KdbxWriter
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx4Writer)
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx4Writer)
|
||||
|
||||
public:
|
||||
bool writeDatabase(QIODevice* device, Database* db) override;
|
||||
|
|
|
@ -249,8 +249,8 @@ void KdbxReader::setInnerRandomStreamID(const QByteArray& data)
|
|||
}
|
||||
auto id = Endian::bytesToSizedInt<quint32>(data, KeePass2::BYTEORDER);
|
||||
KeePass2::ProtectedStreamAlgo irsAlgo = KeePass2::idToProtectedStreamAlgo(id);
|
||||
if (irsAlgo == KeePass2::ProtectedStreamAlgo::InvalidProtectedStreamAlgo ||
|
||||
irsAlgo == KeePass2::ProtectedStreamAlgo::ArcFourVariant) {
|
||||
if (irsAlgo == KeePass2::ProtectedStreamAlgo::InvalidProtectedStreamAlgo
|
||||
|| irsAlgo == KeePass2::ProtectedStreamAlgo::ArcFourVariant) {
|
||||
raiseError(tr("Invalid inner random stream cipher"));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class QIODevice;
|
|||
*/
|
||||
class KdbxReader
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(KdbxReader)
|
||||
Q_DECLARE_TR_FUNCTIONS(KdbxReader)
|
||||
|
||||
public:
|
||||
KdbxReader() = default;
|
||||
|
@ -61,8 +61,8 @@ protected:
|
|||
* @param keepDatabase keep database in case of read failure
|
||||
* @return pointer to the read database, nullptr on failure
|
||||
*/
|
||||
virtual Database* readDatabaseImpl(QIODevice* device, const QByteArray& headerData,
|
||||
const CompositeKey& key, bool keepDatabase) = 0;
|
||||
virtual Database*
|
||||
readDatabaseImpl(QIODevice* device, const QByteArray& headerData, const CompositeKey& key, bool keepDatabase) = 0;
|
||||
|
||||
/**
|
||||
* Read next header field from stream.
|
||||
|
@ -103,5 +103,4 @@ private:
|
|||
QString m_errorStr = "";
|
||||
};
|
||||
|
||||
|
||||
#endif //KEEPASSXC_KDBXREADER_H
|
||||
#endif // KEEPASSXC_KDBXREADER_H
|
||||
|
|
|
@ -35,7 +35,7 @@ class Database;
|
|||
*/
|
||||
class KdbxWriter
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(KdbxWriter)
|
||||
Q_DECLARE_TR_FUNCTIONS(KdbxWriter)
|
||||
|
||||
public:
|
||||
KdbxWriter() = default;
|
||||
|
@ -56,7 +56,6 @@ public:
|
|||
QString errorString() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Helper method for writing a KDBX header field to a device.
|
||||
*
|
||||
|
@ -74,8 +73,8 @@ protected:
|
|||
QByteArray fieldIdArr;
|
||||
fieldIdArr[0] = static_cast<char>(fieldId);
|
||||
CHECK_RETURN_FALSE(writeData(device, fieldIdArr));
|
||||
CHECK_RETURN_FALSE(writeData(device, Endian::sizedIntToBytes<SizedQInt>(static_cast<SizedQInt>(data.size()),
|
||||
KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(writeData(
|
||||
device, Endian::sizedIntToBytes<SizedQInt>(static_cast<SizedQInt>(data.size()), KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(writeData(device, data));
|
||||
|
||||
return true;
|
||||
|
@ -88,5 +87,4 @@ protected:
|
|||
QString m_errorStr = "";
|
||||
};
|
||||
|
||||
|
||||
#endif //KEEPASSXC_KDBXWRITER_H
|
||||
#endif // KEEPASSXC_KDBXWRITER_H
|
||||
|
|
|
@ -17,16 +17,16 @@
|
|||
|
||||
#include "KdbxXmlReader.h"
|
||||
#include "KeePass2RandomStream.h"
|
||||
#include "core/Global.h"
|
||||
#include "core/Tools.h"
|
||||
#include "core/Entry.h"
|
||||
#include "core/Group.h"
|
||||
#include "core/DatabaseIcons.h"
|
||||
#include "core/Endian.h"
|
||||
#include "core/Entry.h"
|
||||
#include "core/Global.h"
|
||||
#include "core/Group.h"
|
||||
#include "core/Tools.h"
|
||||
#include "streams/QtIOCompressor"
|
||||
|
||||
#include <QFile>
|
||||
#include <QBuffer>
|
||||
#include <QFile>
|
||||
|
||||
/**
|
||||
* @param version KDBX version
|
||||
|
@ -114,13 +114,11 @@ void KdbxXmlReader::readDatabase(QIODevice* device, Database* db, KeePass2Random
|
|||
}
|
||||
|
||||
if (!m_tmpParent->children().isEmpty()) {
|
||||
qWarning("KdbxXmlReader::readDatabase: found %d invalid group reference(s)",
|
||||
m_tmpParent->children().size());
|
||||
qWarning("KdbxXmlReader::readDatabase: found %d invalid group reference(s)", m_tmpParent->children().size());
|
||||
}
|
||||
|
||||
if (!m_tmpParent->entries().isEmpty()) {
|
||||
qWarning("KdbxXmlReader::readDatabase: found %d invalid entry reference(s)",
|
||||
m_tmpParent->children().size());
|
||||
qWarning("KdbxXmlReader::readDatabase: found %d invalid entry reference(s)", m_tmpParent->children().size());
|
||||
}
|
||||
|
||||
const QSet<QString> poolKeys = m_binaryPool.keys().toSet();
|
||||
|
@ -136,7 +134,7 @@ void KdbxXmlReader::readDatabase(QIODevice* device, Database* db, KeePass2Random
|
|||
qWarning("KdbxXmlReader::readDatabase: found unused key \"%s\"", qPrintable(key));
|
||||
}
|
||||
|
||||
QHash<QString, QPair<Entry*, QString> >::const_iterator i;
|
||||
QHash<QString, QPair<Entry*, QString>>::const_iterator i;
|
||||
for (i = m_binaryMap.constBegin(); i != m_binaryMap.constEnd(); ++i) {
|
||||
const QPair<Entry*, QString>& target = i.value();
|
||||
target.first->attachments()->set(target.second, m_binaryPool[i.key()]);
|
||||
|
@ -191,8 +189,7 @@ QString KdbxXmlReader::errorString() const
|
|||
|
||||
bool KdbxXmlReader::isTrueValue(const QStringRef& value)
|
||||
{
|
||||
return value.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0
|
||||
|| value == "1";
|
||||
return value.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0 || value == "1";
|
||||
}
|
||||
|
||||
void KdbxXmlReader::raiseError(const QString& errorMessage)
|
||||
|
@ -386,12 +383,10 @@ void KdbxXmlReader::parseBinaries()
|
|||
|
||||
QXmlStreamAttributes attr = m_xml.attributes();
|
||||
QString id = attr.value("ID").toString();
|
||||
QByteArray data = isTrueValue(attr.value("Compressed"))
|
||||
? readCompressedBinary() : readBinary();
|
||||
QByteArray data = isTrueValue(attr.value("Compressed")) ? readCompressedBinary() : readBinary();
|
||||
|
||||
if (m_binaryPool.contains(id)) {
|
||||
qWarning("KdbxXmlReader::parseBinaries: overwriting binary item \"%s\"",
|
||||
qPrintable(id));
|
||||
qWarning("KdbxXmlReader::parseBinaries: overwriting binary item \"%s\"", qPrintable(id));
|
||||
}
|
||||
|
||||
m_binaryPool.insert(id, data);
|
||||
|
@ -1192,4 +1187,3 @@ void KdbxXmlReader::skipCurrentElement()
|
|||
qWarning("KdbxXmlReader::skipCurrentElement: skip element \"%s\"", qPrintable(m_xml.name().toString()));
|
||||
m_xml.skipCurrentElement();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,14 +18,14 @@
|
|||
#ifndef KEEPASSXC_KDBXXMLREADER_H
|
||||
#define KEEPASSXC_KDBXXMLREADER_H
|
||||
|
||||
#include "core/Database.h"
|
||||
#include "core/Metadata.h"
|
||||
#include "core/TimeInfo.h"
|
||||
#include "core/Uuid.h"
|
||||
#include "core/Database.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QString>
|
||||
#include <QPair>
|
||||
#include <QString>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
class QIODevice;
|
||||
|
@ -38,7 +38,7 @@ class KeePass2RandomStream;
|
|||
*/
|
||||
class KdbxXmlReader
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(KdbxXmlReader)
|
||||
Q_DECLARE_TR_FUNCTIONS(KdbxXmlReader)
|
||||
|
||||
public:
|
||||
explicit KdbxXmlReader(quint32 version);
|
||||
|
@ -112,11 +112,11 @@ protected:
|
|||
QHash<Uuid, Entry*> m_entries;
|
||||
|
||||
QHash<QString, QByteArray> m_binaryPool;
|
||||
QHash<QString, QPair<Entry*, QString> > m_binaryMap;
|
||||
QHash<QString, QPair<Entry*, QString>> m_binaryMap;
|
||||
QByteArray m_headerHash;
|
||||
|
||||
bool m_error = false;
|
||||
QString m_errorStr = "";
|
||||
};
|
||||
|
||||
#endif //KEEPASSXC_KDBXXMLREADER_H
|
||||
#endif // KEEPASSXC_KDBXXMLREADER_H
|
||||
|
|
|
@ -33,7 +33,10 @@ KdbxXmlWriter::KdbxXmlWriter(quint32 version)
|
|||
{
|
||||
}
|
||||
|
||||
void KdbxXmlWriter::writeDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream, const QByteArray& headerHash)
|
||||
void KdbxXmlWriter::writeDatabase(QIODevice* device,
|
||||
Database* db,
|
||||
KeePass2RandomStream* randomStream,
|
||||
const QByteArray& headerHash)
|
||||
{
|
||||
m_db = db;
|
||||
m_meta = db->metadata();
|
||||
|
@ -64,7 +67,7 @@ void KdbxXmlWriter::writeDatabase(QIODevice* device, Database* db, KeePass2Rando
|
|||
void KdbxXmlWriter::writeDatabase(const QString& filename, Database* db)
|
||||
{
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::WriteOnly|QIODevice::Truncate);
|
||||
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||
writeDatabase(&file, db);
|
||||
}
|
||||
|
||||
|
@ -204,8 +207,7 @@ void KdbxXmlWriter::writeBinaries()
|
|||
|
||||
buffer.seek(0);
|
||||
data = buffer.readAll();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
data = i.key();
|
||||
}
|
||||
|
||||
|
@ -354,12 +356,12 @@ void KdbxXmlWriter::writeEntry(const Entry* entry)
|
|||
for (const QString& key : attributesKeyList) {
|
||||
m_xml.writeStartElement("String");
|
||||
|
||||
bool protect = ( ((key == "Title") && m_meta->protectTitle()) ||
|
||||
((key == "UserName") && m_meta->protectUsername()) ||
|
||||
((key == "Password") && m_meta->protectPassword()) ||
|
||||
((key == "URL") && m_meta->protectUrl()) ||
|
||||
((key == "Notes") && m_meta->protectNotes()) ||
|
||||
entry->attributes()->isProtected(key) );
|
||||
bool protect =
|
||||
(((key == "Title") && m_meta->protectTitle()) || ((key == "UserName") && m_meta->protectUsername())
|
||||
|| ((key == "Password") && m_meta->protectPassword())
|
||||
|| ((key == "URL") && m_meta->protectUrl())
|
||||
|| ((key == "Notes") && m_meta->protectNotes())
|
||||
|| entry->attributes()->isProtected(key));
|
||||
|
||||
writeString("Key", key);
|
||||
|
||||
|
@ -375,13 +377,11 @@ void KdbxXmlWriter::writeEntry(const Entry* entry)
|
|||
raiseError(m_randomStream->errorString());
|
||||
}
|
||||
value = QString::fromLatin1(rawData.toBase64());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
m_xml.writeAttribute("ProtectInMemory", "True");
|
||||
value = entry->attributes()->value(key);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
value = entry->attributes()->value(key);
|
||||
}
|
||||
|
||||
|
@ -462,8 +462,7 @@ void KdbxXmlWriter::writeString(const QString& qualifiedName, const QString& str
|
|||
{
|
||||
if (string.isEmpty()) {
|
||||
m_xml.writeEmptyElement(qualifiedName);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
m_xml.writeTextElement(qualifiedName, stripInvalidXml10Chars(string));
|
||||
}
|
||||
}
|
||||
|
@ -477,8 +476,7 @@ void KdbxXmlWriter::writeBool(const QString& qualifiedName, bool b)
|
|||
{
|
||||
if (b) {
|
||||
writeString(qualifiedName, "True");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
writeString(qualifiedName, "False");
|
||||
}
|
||||
}
|
||||
|
@ -513,8 +511,7 @@ void KdbxXmlWriter::writeUuid(const QString& qualifiedName, const Group* group)
|
|||
{
|
||||
if (group) {
|
||||
writeUuid(qualifiedName, group->uuid());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
writeUuid(qualifiedName, Uuid());
|
||||
}
|
||||
}
|
||||
|
@ -523,8 +520,7 @@ void KdbxXmlWriter::writeUuid(const QString& qualifiedName, const Entry* entry)
|
|||
{
|
||||
if (entry) {
|
||||
writeUuid(qualifiedName, entry->uuid());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
writeUuid(qualifiedName, Uuid());
|
||||
}
|
||||
}
|
||||
|
@ -539,9 +535,8 @@ void KdbxXmlWriter::writeColor(const QString& qualifiedName, const QColor& color
|
|||
QString colorStr;
|
||||
|
||||
if (color.isValid()) {
|
||||
colorStr = QString("#%1%2%3").arg(colorPartToString(color.red()),
|
||||
colorPartToString(color.green()),
|
||||
colorPartToString(color.blue()));
|
||||
colorStr = QString("#%1%2%3").arg(
|
||||
colorPartToString(color.red()), colorPartToString(color.green()), colorPartToString(color.blue()));
|
||||
}
|
||||
|
||||
writeString(qualifiedName, colorStr);
|
||||
|
@ -553,11 +548,9 @@ void KdbxXmlWriter::writeTriState(const QString& qualifiedName, Group::TriState
|
|||
|
||||
if (triState == Group::Inherit) {
|
||||
value = "null";
|
||||
}
|
||||
else if (triState == Group::Enable) {
|
||||
} else if (triState == Group::Enable) {
|
||||
value = "true";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
value = "false";
|
||||
}
|
||||
|
||||
|
@ -583,13 +576,12 @@ QString KdbxXmlWriter::stripInvalidXml10Chars(QString str)
|
|||
if (ch.isLowSurrogate() && i != 0 && str.at(i - 1).isHighSurrogate()) {
|
||||
// keep valid surrogate pair
|
||||
i--;
|
||||
}
|
||||
else if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D) // control characters
|
||||
|| (uc >= 0x7F && uc <= 0x84) // control characters, valid but discouraged by XML
|
||||
|| (uc >= 0x86 && uc <= 0x9F) // control characters, valid but discouraged by XML
|
||||
|| (uc > 0xFFFD) // noncharacter
|
||||
|| ch.isLowSurrogate() // single low surrogate
|
||||
|| ch.isHighSurrogate()) // single high surrogate
|
||||
} else if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D) // control characters
|
||||
|| (uc >= 0x7F && uc <= 0x84) // control characters, valid but discouraged by XML
|
||||
|| (uc >= 0x86 && uc <= 0x9F) // control characters, valid but discouraged by XML
|
||||
|| (uc > 0xFFFD) // noncharacter
|
||||
|| ch.isLowSurrogate() // single low surrogate
|
||||
|| ch.isHighSurrogate()) // single high surrogate
|
||||
{
|
||||
qWarning("Stripping invalid XML 1.0 codepoint %x", uc);
|
||||
str.remove(i, 1);
|
||||
|
|
|
@ -37,7 +37,9 @@ class KdbxXmlWriter
|
|||
public:
|
||||
explicit KdbxXmlWriter(quint32 version);
|
||||
|
||||
void writeDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream = nullptr,
|
||||
void writeDatabase(QIODevice* device,
|
||||
Database* db,
|
||||
KeePass2RandomStream* randomStream = nullptr,
|
||||
const QByteArray& headerHash = QByteArray());
|
||||
void writeDatabase(const QString& filename, Database* db);
|
||||
bool hasError();
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <QImage>
|
||||
#include <QTextCodec>
|
||||
|
||||
#include "crypto/kdf/AesKdf.h"
|
||||
#include "core/Database.h"
|
||||
#include "core/Endian.h"
|
||||
#include "core/Entry.h"
|
||||
|
@ -29,6 +28,7 @@
|
|||
#include "core/Metadata.h"
|
||||
#include "core/Tools.h"
|
||||
#include "crypto/CryptoHash.h"
|
||||
#include "crypto/kdf/AesKdf.h"
|
||||
#include "format/KeePass1.h"
|
||||
#include "keys/FileKey.h"
|
||||
#include "keys/PasswordKey.h"
|
||||
|
@ -47,7 +47,6 @@ private:
|
|||
QByteArray m_keyfileData;
|
||||
};
|
||||
|
||||
|
||||
KeePass1Reader::KeePass1Reader()
|
||||
: m_db(nullptr)
|
||||
, m_tmpParent(nullptr)
|
||||
|
@ -58,8 +57,7 @@ KeePass1Reader::KeePass1Reader()
|
|||
{
|
||||
}
|
||||
|
||||
Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password,
|
||||
QIODevice* keyfileDevice)
|
||||
Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password, QIODevice* keyfileDevice)
|
||||
{
|
||||
m_error = false;
|
||||
m_errorStr.clear();
|
||||
|
@ -112,8 +110,9 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
|
|||
}
|
||||
|
||||
auto version = Endian::readSizedInt<quint32>(m_device, KeePass1::BYTEORDER, &ok);
|
||||
if (!ok || (version & KeePass1::FILE_VERSION_CRITICAL_MASK)
|
||||
!= (KeePass1::FILE_VERSION & KeePass1::FILE_VERSION_CRITICAL_MASK)) {
|
||||
if (!ok
|
||||
|| (version & KeePass1::FILE_VERSION_CRITICAL_MASK)
|
||||
!= (KeePass1::FILE_VERSION & KeePass1::FILE_VERSION_CRITICAL_MASK)) {
|
||||
raiseError(tr("Unsupported KeePass database version."));
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -200,8 +199,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
|
|||
parseMetaStream(entry);
|
||||
|
||||
delete entry;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
quint32 groupId = m_entryGroupIds.value(entry);
|
||||
if (!m_groupIds.contains(groupId)) {
|
||||
qWarning("Orphaned entry found, assigning to root group.");
|
||||
|
@ -251,8 +249,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
|
|||
return db.take();
|
||||
}
|
||||
|
||||
Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password,
|
||||
const QString& keyfileName)
|
||||
Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password, const QString& keyfileName)
|
||||
{
|
||||
QScopedPointer<QFile> keyFile;
|
||||
if (!keyfileName.isEmpty()) {
|
||||
|
@ -268,8 +265,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
|
|||
return db.take();
|
||||
}
|
||||
|
||||
Database* KeePass1Reader::readDatabase(const QString& filename, const QString& password,
|
||||
const QString& keyfileName)
|
||||
Database* KeePass1Reader::readDatabase(const QString& filename, const QString& password, const QString& keyfileName)
|
||||
{
|
||||
QFile dbFile(filename);
|
||||
if (!dbFile.open(QFile::ReadOnly)) {
|
||||
|
@ -297,10 +293,10 @@ QString KeePass1Reader::errorString()
|
|||
return m_errorStr;
|
||||
}
|
||||
|
||||
SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const QByteArray& keyfileData,
|
||||
qint64 contentPos)
|
||||
SymmetricCipherStream*
|
||||
KeePass1Reader::testKeys(const QString& password, const QByteArray& keyfileData, qint64 contentPos)
|
||||
{
|
||||
const QList<PasswordEncoding> encodings = { Windows1252, Latin1, UTF8 };
|
||||
const QList<PasswordEncoding> encodings = {Windows1252, Latin1, UTF8};
|
||||
|
||||
QScopedPointer<SymmetricCipherStream> cipherStream;
|
||||
QByteArray passwordData;
|
||||
|
@ -310,28 +306,24 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q
|
|||
for (PasswordEncoding encoding : encodings) {
|
||||
if (encoding == Windows1252) {
|
||||
passwordData = passwordDataCorrect;
|
||||
}
|
||||
else if (encoding == Latin1) {
|
||||
} else if (encoding == Latin1) {
|
||||
// KeePassX used Latin-1 encoding for passwords until version 0.3.1
|
||||
// but KeePass/Win32 uses Windows Codepage 1252.
|
||||
passwordData = password.toLatin1();
|
||||
|
||||
if (passwordData == passwordDataCorrect) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
qWarning("Testing password encoded as Latin-1.");
|
||||
}
|
||||
}
|
||||
else if (encoding == UTF8) {
|
||||
} else if (encoding == UTF8) {
|
||||
// KeePassX used UTF-8 encoding for passwords until version 0.2.2
|
||||
// but KeePass/Win32 uses Windows Codepage 1252.
|
||||
passwordData = password.toUtf8();
|
||||
|
||||
if (passwordData == passwordDataCorrect) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
qWarning("Testing password encoded as UTF-8.");
|
||||
}
|
||||
}
|
||||
|
@ -341,12 +333,11 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q
|
|||
return nullptr;
|
||||
}
|
||||
if (m_encryptionFlags & KeePass1::Rijndael) {
|
||||
cipherStream.reset(new SymmetricCipherStream(m_device, SymmetricCipher::Aes256,
|
||||
SymmetricCipher::Cbc, SymmetricCipher::Decrypt));
|
||||
}
|
||||
else {
|
||||
cipherStream.reset(new SymmetricCipherStream(m_device, SymmetricCipher::Twofish,
|
||||
SymmetricCipher::Cbc, SymmetricCipher::Decrypt));
|
||||
cipherStream.reset(new SymmetricCipherStream(
|
||||
m_device, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt));
|
||||
} else {
|
||||
cipherStream.reset(new SymmetricCipherStream(
|
||||
m_device, SymmetricCipher::Twofish, SymmetricCipher::Cbc, SymmetricCipher::Decrypt));
|
||||
}
|
||||
|
||||
if (!cipherStream->init(finalKey, m_encryptionIV)) {
|
||||
|
@ -375,8 +366,7 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q
|
|||
|
||||
if (success) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cipherStream.reset();
|
||||
}
|
||||
}
|
||||
|
@ -476,8 +466,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
|
|||
case 0x0002:
|
||||
group->setName(QString::fromUtf8(fieldData.constData()));
|
||||
break;
|
||||
case 0x0003:
|
||||
{
|
||||
case 0x0003: {
|
||||
if (fieldSize != 5) {
|
||||
raiseError(tr("Incorrect group creation time field size"));
|
||||
return nullptr;
|
||||
|
@ -488,8 +477,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 0x0004:
|
||||
{
|
||||
case 0x0004: {
|
||||
if (fieldSize != 5) {
|
||||
raiseError(tr("Incorrect group modification time field size"));
|
||||
return nullptr;
|
||||
|
@ -500,8 +488,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 0x0005:
|
||||
{
|
||||
case 0x0005: {
|
||||
if (fieldSize != 5) {
|
||||
raiseError(tr("Incorrect group access time field size"));
|
||||
}
|
||||
|
@ -511,8 +498,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 0x0006:
|
||||
{
|
||||
case 0x0006: {
|
||||
if (fieldSize != 5) {
|
||||
raiseError(tr("Incorrect group expiry time field size"));
|
||||
}
|
||||
|
@ -523,8 +509,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 0x0007:
|
||||
{
|
||||
case 0x0007: {
|
||||
if (fieldSize != 4) {
|
||||
raiseError(tr("Incorrect group icon field size"));
|
||||
return nullptr;
|
||||
|
@ -533,8 +518,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
|
|||
group->setIcon(iconNumber);
|
||||
break;
|
||||
}
|
||||
case 0x0008:
|
||||
{
|
||||
case 0x0008: {
|
||||
if (fieldSize != 2) {
|
||||
raiseError(tr("Incorrect group level field size"));
|
||||
return nullptr;
|
||||
|
@ -610,8 +594,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
|
|||
}
|
||||
m_entryUuids.insert(fieldData, entry.data());
|
||||
break;
|
||||
case 0x0002:
|
||||
{
|
||||
case 0x0002: {
|
||||
if (fieldSize != 4) {
|
||||
raiseError(tr("Invalid entry group id field size"));
|
||||
return nullptr;
|
||||
|
@ -620,8 +603,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
|
|||
m_entryGroupIds.insert(entry.data(), groupId);
|
||||
break;
|
||||
}
|
||||
case 0x0003:
|
||||
{
|
||||
case 0x0003: {
|
||||
if (fieldSize != 4) {
|
||||
raiseError(tr("Invalid entry icon field size"));
|
||||
return nullptr;
|
||||
|
@ -645,8 +627,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
|
|||
case 0x0008:
|
||||
parseNotes(QString::fromUtf8(fieldData.constData()), entry.data());
|
||||
break;
|
||||
case 0x0009:
|
||||
{
|
||||
case 0x0009: {
|
||||
if (fieldSize != 5) {
|
||||
raiseError(tr("Invalid entry creation time field size"));
|
||||
return nullptr;
|
||||
|
@ -657,8 +638,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 0x000A:
|
||||
{
|
||||
case 0x000A: {
|
||||
if (fieldSize != 5) {
|
||||
raiseError(tr("Invalid entry modification time field size"));
|
||||
return nullptr;
|
||||
|
@ -669,8 +649,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 0x000B:
|
||||
{
|
||||
case 0x000B: {
|
||||
if (fieldSize != 5) {
|
||||
raiseError(tr("Invalid entry creation time field size"));
|
||||
return nullptr;
|
||||
|
@ -681,8 +660,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 0x000C:
|
||||
{
|
||||
case 0x000C: {
|
||||
if (fieldSize != 5) {
|
||||
raiseError(tr("Invalid entry expiry time field size"));
|
||||
return nullptr;
|
||||
|
@ -734,27 +712,23 @@ void KeePass1Reader::parseNotes(const QString& rawNotes, Entry* entry)
|
|||
if (sequenceRegexp.exactMatch(line)) {
|
||||
if (sequenceRegexp.cap(1).isEmpty()) {
|
||||
entry->setDefaultAutoTypeSequence(sequenceRegexp.cap(2));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sequences[sequenceRegexp.cap(1).toInt()] = sequenceRegexp.cap(2);
|
||||
}
|
||||
|
||||
lastLineAutoType = true;
|
||||
}
|
||||
else if (windowRegexp.exactMatch(line)) {
|
||||
} else if (windowRegexp.exactMatch(line)) {
|
||||
int nr;
|
||||
if (windowRegexp.cap(1).isEmpty()) {
|
||||
nr = -1; // special number that matches no other sequence
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
nr = windowRegexp.cap(1).toInt();
|
||||
}
|
||||
|
||||
windows[nr].append(windowRegexp.cap(2));
|
||||
|
||||
lastLineAutoType = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// don't add empty lines following a removed auto-type line
|
||||
if (!lastLineAutoType || !line.isEmpty()) {
|
||||
notes.append(line);
|
||||
|
@ -788,8 +762,7 @@ bool KeePass1Reader::constructGroupTree(const QList<Group*>& groups)
|
|||
|
||||
if (level == 0) {
|
||||
groups[i]->setParent(m_db->rootGroup());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
for (int j = (i - 1); j >= 0; j--) {
|
||||
if (m_groupLevels.value(groups[j]) < level) {
|
||||
if ((level - m_groupLevels.value(groups[j])) != 1) {
|
||||
|
@ -818,13 +791,11 @@ void KeePass1Reader::parseMetaStream(const Entry* entry)
|
|||
if (!parseGroupTreeState(data)) {
|
||||
qWarning("Unable to parse group tree state metastream.");
|
||||
}
|
||||
}
|
||||
else if (entry->notes() == "KPX_CUSTOM_ICONS_4") {
|
||||
} else if (entry->notes() == "KPX_CUSTOM_ICONS_4") {
|
||||
if (!parseCustomIcons4(data)) {
|
||||
qWarning("Unable to parse custom icons metastream.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
qWarning("Ignoring unknown metastream \"%s\".", entry->notes().toLocal8Bit().constData());
|
||||
}
|
||||
}
|
||||
|
@ -962,20 +933,16 @@ QDateTime KeePass1Reader::dateFromPackedStruct(const QByteArray& data)
|
|||
// check for the special "never" datetime
|
||||
if (dateTime == QDateTime(QDate(2999, 12, 28), QTime(23, 59, 59), Qt::UTC)) {
|
||||
return QDateTime();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return dateTime;
|
||||
}
|
||||
}
|
||||
|
||||
bool KeePass1Reader::isMetaStream(const Entry* entry)
|
||||
{
|
||||
return entry->attachments()->keys().contains("bin-stream")
|
||||
&& !entry->notes().isEmpty()
|
||||
&& entry->title() == "Meta-Info"
|
||||
&& entry->username() == "SYSTEM"
|
||||
&& entry->url() == "$"
|
||||
&& entry->iconNumber() == 0;
|
||||
return entry->attachments()->keys().contains("bin-stream") && !entry->notes().isEmpty()
|
||||
&& entry->title() == "Meta-Info" && entry->username() == "SYSTEM" && entry->url() == "$"
|
||||
&& entry->iconNumber() == 0;
|
||||
}
|
||||
|
||||
QByteArray KeePass1Reader::readKeyfile(QIODevice* device)
|
||||
|
@ -1002,8 +969,7 @@ QByteArray KeePass1Reader::readKeyfile(QIODevice* device)
|
|||
|
||||
if (Tools::isHex(data)) {
|
||||
return QByteArray::fromHex(data);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
device->seek(0);
|
||||
}
|
||||
}
|
||||
|
@ -1021,16 +987,13 @@ QByteArray KeePass1Reader::readKeyfile(QIODevice* device)
|
|||
return cryptoHash.result();
|
||||
}
|
||||
|
||||
|
||||
QByteArray KeePass1Key::rawKey() const
|
||||
{
|
||||
if (m_keyfileData.isEmpty()) {
|
||||
return CryptoHash::hash(m_password, CryptoHash::Sha256);
|
||||
}
|
||||
else if (m_password.isEmpty()) {
|
||||
} else if (m_password.isEmpty()) {
|
||||
return m_keyfileData;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
CryptoHash keyHash(CryptoHash::Sha256);
|
||||
keyHash.addData(CryptoHash::hash(m_password, CryptoHash::Sha256));
|
||||
keyHash.addData(m_keyfileData);
|
||||
|
|
|
@ -34,12 +34,9 @@ class KeePass1Reader
|
|||
|
||||
public:
|
||||
KeePass1Reader();
|
||||
Database* readDatabase(QIODevice* device, const QString& password,
|
||||
QIODevice* keyfileDevice);
|
||||
Database* readDatabase(QIODevice* device, const QString& password,
|
||||
const QString& keyfileName);
|
||||
Database* readDatabase(const QString& filename, const QString& password,
|
||||
const QString& keyfileName);
|
||||
Database* readDatabase(QIODevice* device, const QString& password, QIODevice* keyfileDevice);
|
||||
Database* readDatabase(QIODevice* device, const QString& password, const QString& keyfileName);
|
||||
Database* readDatabase(const QString& filename, const QString& password, const QString& keyfileName);
|
||||
bool hasError();
|
||||
QString errorString();
|
||||
|
||||
|
@ -51,8 +48,7 @@ private:
|
|||
UTF8
|
||||
};
|
||||
|
||||
SymmetricCipherStream* testKeys(const QString& password, const QByteArray& keyfileData,
|
||||
qint64 contentPos);
|
||||
SymmetricCipherStream* testKeys(const QString& password, const QByteArray& keyfileData, qint64 contentPos);
|
||||
QByteArray key(const QByteArray& password, const QByteArray& keyfileData);
|
||||
bool verifyKey(SymmetricCipherStream* cipherStream);
|
||||
Group* readGroup(QIODevice* cipherStream);
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
*/
|
||||
|
||||
#include "KeePass2.h"
|
||||
#include <QSharedPointer>
|
||||
#include "crypto/CryptoHash.h"
|
||||
#include "crypto/kdf/AesKdf.h"
|
||||
#include "crypto/kdf/Argon2Kdf.h"
|
||||
#include "crypto/CryptoHash.h"
|
||||
#include <QSharedPointer>
|
||||
|
||||
const Uuid KeePass2::CIPHER_AES = Uuid(QByteArray::fromHex("31c1f2e6bf714350be5805216afc5aff"));
|
||||
const Uuid KeePass2::CIPHER_TWOFISH = Uuid(QByteArray::fromHex("ad68f29f576f4bb9a36ad47af965346c"));
|
||||
|
@ -47,16 +47,15 @@ const QString KeePass2::KDFPARAM_ARGON2_ASSOCDATA("A");
|
|||
const QList<QPair<Uuid, QString>> KeePass2::CIPHERS{
|
||||
qMakePair(KeePass2::CIPHER_AES, QString(QT_TRANSLATE_NOOP("KeePass2", "AES: 256-bit"))),
|
||||
qMakePair(KeePass2::CIPHER_TWOFISH, QString(QT_TRANSLATE_NOOP("KeePass2", "Twofish: 256-bit"))),
|
||||
qMakePair(KeePass2::CIPHER_CHACHA20, QString(QT_TRANSLATE_NOOP("KeePass2", "ChaCha20: 256-bit")))
|
||||
};
|
||||
qMakePair(KeePass2::CIPHER_CHACHA20, QString(QT_TRANSLATE_NOOP("KeePass2", "ChaCha20: 256-bit")))};
|
||||
|
||||
const QList<QPair<Uuid, QString>> KeePass2::KDFS{
|
||||
qMakePair(KeePass2::KDF_ARGON2, QString(QT_TRANSLATE_NOOP("KeePass2", "Argon2 (KDBX 4 – recommended)"))),
|
||||
qMakePair(KeePass2::KDF_AES_KDBX4, QString(QT_TRANSLATE_NOOP("KeePass2", "AES-KDF (KDBX 4)"))),
|
||||
qMakePair(KeePass2::KDF_AES_KDBX3, QString(QT_TRANSLATE_NOOP("KeePass2", "AES-KDF (KDBX 3.1)")))
|
||||
};
|
||||
qMakePair(KeePass2::KDF_AES_KDBX3, QString(QT_TRANSLATE_NOOP("KeePass2", "AES-KDF (KDBX 3.1)")))};
|
||||
|
||||
QByteArray KeePass2::hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey) {
|
||||
QByteArray KeePass2::hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey)
|
||||
{
|
||||
CryptoHash hmacKeyHash(CryptoHash::Sha512);
|
||||
hmacKeyHash.addData(masterSeed);
|
||||
hmacKeyHash.addData(transformedMasterKey);
|
||||
|
|
|
@ -1,137 +1,137 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
|
||||
*
|
||||
* This program 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 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
|
||||
*
|
||||
* This program 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 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef KEEPASSX_KEEPASS2_H
|
||||
#define KEEPASSX_KEEPASS2_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QMap>
|
||||
#include <QVariantMap>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QSharedPointer>
|
||||
#include <QVariantMap>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "core/Uuid.h"
|
||||
#include "crypto/SymmetricCipher.h"
|
||||
#include "crypto/kdf/Kdf.h"
|
||||
#include "core/Uuid.h"
|
||||
|
||||
namespace KeePass2
|
||||
{
|
||||
|
||||
constexpr quint32 SIGNATURE_1 = 0x9AA2D903;
|
||||
constexpr quint32 SIGNATURE_2 = 0xB54BFB67;
|
||||
constexpr quint32 SIGNATURE_1 = 0x9AA2D903;
|
||||
constexpr quint32 SIGNATURE_2 = 0xB54BFB67;
|
||||
|
||||
constexpr quint32 FILE_VERSION_CRITICAL_MASK = 0xFFFF0000;
|
||||
constexpr quint32 FILE_VERSION_4 = 0x00040000;
|
||||
constexpr quint32 FILE_VERSION_3_1 = 0x00030001;
|
||||
constexpr quint32 FILE_VERSION_3 = 0x00030000;
|
||||
constexpr quint32 FILE_VERSION_2 = 0x00020000;
|
||||
constexpr quint32 FILE_VERSION_MIN = FILE_VERSION_2;
|
||||
constexpr quint32 FILE_VERSION_CRITICAL_MASK = 0xFFFF0000;
|
||||
constexpr quint32 FILE_VERSION_4 = 0x00040000;
|
||||
constexpr quint32 FILE_VERSION_3_1 = 0x00030001;
|
||||
constexpr quint32 FILE_VERSION_3 = 0x00030000;
|
||||
constexpr quint32 FILE_VERSION_2 = 0x00020000;
|
||||
constexpr quint32 FILE_VERSION_MIN = FILE_VERSION_2;
|
||||
|
||||
constexpr quint16 VARIANTMAP_VERSION = 0x0100;
|
||||
constexpr quint16 VARIANTMAP_CRITICAL_MASK = 0xFF00;
|
||||
constexpr quint16 VARIANTMAP_VERSION = 0x0100;
|
||||
constexpr quint16 VARIANTMAP_CRITICAL_MASK = 0xFF00;
|
||||
|
||||
const QSysInfo::Endian BYTEORDER = QSysInfo::LittleEndian;
|
||||
const QSysInfo::Endian BYTEORDER = QSysInfo::LittleEndian;
|
||||
|
||||
extern const Uuid CIPHER_AES;
|
||||
extern const Uuid CIPHER_TWOFISH;
|
||||
extern const Uuid CIPHER_CHACHA20;
|
||||
extern const Uuid CIPHER_AES;
|
||||
extern const Uuid CIPHER_TWOFISH;
|
||||
extern const Uuid CIPHER_CHACHA20;
|
||||
|
||||
extern const Uuid KDF_AES_KDBX3;
|
||||
extern const Uuid KDF_AES_KDBX4;
|
||||
extern const Uuid KDF_ARGON2;
|
||||
extern const Uuid KDF_AES_KDBX3;
|
||||
extern const Uuid KDF_AES_KDBX4;
|
||||
extern const Uuid KDF_ARGON2;
|
||||
|
||||
extern const QByteArray INNER_STREAM_SALSA20_IV;
|
||||
extern const QByteArray INNER_STREAM_SALSA20_IV;
|
||||
|
||||
extern const QString KDFPARAM_UUID;
|
||||
extern const QString KDFPARAM_AES_ROUNDS;
|
||||
extern const QString KDFPARAM_AES_SEED;
|
||||
extern const QString KDFPARAM_ARGON2_SALT;
|
||||
extern const QString KDFPARAM_ARGON2_PARALLELISM;
|
||||
extern const QString KDFPARAM_ARGON2_MEMORY;
|
||||
extern const QString KDFPARAM_ARGON2_ITERATIONS;
|
||||
extern const QString KDFPARAM_ARGON2_VERSION;
|
||||
extern const QString KDFPARAM_ARGON2_SECRET;
|
||||
extern const QString KDFPARAM_ARGON2_ASSOCDATA;
|
||||
extern const QString KDFPARAM_UUID;
|
||||
extern const QString KDFPARAM_AES_ROUNDS;
|
||||
extern const QString KDFPARAM_AES_SEED;
|
||||
extern const QString KDFPARAM_ARGON2_SALT;
|
||||
extern const QString KDFPARAM_ARGON2_PARALLELISM;
|
||||
extern const QString KDFPARAM_ARGON2_MEMORY;
|
||||
extern const QString KDFPARAM_ARGON2_ITERATIONS;
|
||||
extern const QString KDFPARAM_ARGON2_VERSION;
|
||||
extern const QString KDFPARAM_ARGON2_SECRET;
|
||||
extern const QString KDFPARAM_ARGON2_ASSOCDATA;
|
||||
|
||||
extern const QList<QPair<Uuid, QString>> CIPHERS;
|
||||
extern const QList<QPair<Uuid, QString>> KDFS;
|
||||
extern const QList<QPair<Uuid, QString>> CIPHERS;
|
||||
extern const QList<QPair<Uuid, QString>> KDFS;
|
||||
|
||||
enum class HeaderFieldID
|
||||
{
|
||||
EndOfHeader = 0,
|
||||
Comment = 1,
|
||||
CipherID = 2,
|
||||
CompressionFlags = 3,
|
||||
MasterSeed = 4,
|
||||
TransformSeed = 5,
|
||||
TransformRounds = 6,
|
||||
EncryptionIV = 7,
|
||||
ProtectedStreamKey = 8,
|
||||
StreamStartBytes = 9,
|
||||
InnerRandomStreamID = 10,
|
||||
KdfParameters = 11,
|
||||
PublicCustomData = 12
|
||||
};
|
||||
enum class HeaderFieldID
|
||||
{
|
||||
EndOfHeader = 0,
|
||||
Comment = 1,
|
||||
CipherID = 2,
|
||||
CompressionFlags = 3,
|
||||
MasterSeed = 4,
|
||||
TransformSeed = 5,
|
||||
TransformRounds = 6,
|
||||
EncryptionIV = 7,
|
||||
ProtectedStreamKey = 8,
|
||||
StreamStartBytes = 9,
|
||||
InnerRandomStreamID = 10,
|
||||
KdfParameters = 11,
|
||||
PublicCustomData = 12
|
||||
};
|
||||
|
||||
enum class InnerHeaderFieldID : quint8
|
||||
{
|
||||
End = 0,
|
||||
InnerRandomStreamID = 1,
|
||||
InnerRandomStreamKey = 2,
|
||||
Binary = 3
|
||||
};
|
||||
enum class InnerHeaderFieldID : quint8
|
||||
{
|
||||
End = 0,
|
||||
InnerRandomStreamID = 1,
|
||||
InnerRandomStreamKey = 2,
|
||||
Binary = 3
|
||||
};
|
||||
|
||||
enum class ProtectedStreamAlgo
|
||||
{
|
||||
ArcFourVariant = 1,
|
||||
Salsa20 = 2,
|
||||
ChaCha20 = 3,
|
||||
InvalidProtectedStreamAlgo = -1
|
||||
};
|
||||
enum class ProtectedStreamAlgo
|
||||
{
|
||||
ArcFourVariant = 1,
|
||||
Salsa20 = 2,
|
||||
ChaCha20 = 3,
|
||||
InvalidProtectedStreamAlgo = -1
|
||||
};
|
||||
|
||||
enum class VariantMapFieldType : quint8
|
||||
{
|
||||
End = 0,
|
||||
// Byte = 0x02,
|
||||
// UInt16 = 0x03,
|
||||
UInt32 = 0x04,
|
||||
UInt64 = 0x05,
|
||||
// Signed mask: 0x08
|
||||
Bool = 0x08,
|
||||
// SByte = 0x0A,
|
||||
// Int16 = 0x0B,
|
||||
Int32 = 0x0C,
|
||||
Int64 = 0x0D,
|
||||
// Float = 0x10,
|
||||
// Double = 0x11,
|
||||
// Decimal = 0x12,
|
||||
// Char = 0x17, // 16-bit Unicode character
|
||||
String = 0x18,
|
||||
// Array mask: 0x40
|
||||
ByteArray = 0x42
|
||||
};
|
||||
enum class VariantMapFieldType : quint8
|
||||
{
|
||||
End = 0,
|
||||
// Byte = 0x02,
|
||||
// UInt16 = 0x03,
|
||||
UInt32 = 0x04,
|
||||
UInt64 = 0x05,
|
||||
// Signed mask: 0x08
|
||||
Bool = 0x08,
|
||||
// SByte = 0x0A,
|
||||
// Int16 = 0x0B,
|
||||
Int32 = 0x0C,
|
||||
Int64 = 0x0D,
|
||||
// Float = 0x10,
|
||||
// Double = 0x11,
|
||||
// Decimal = 0x12,
|
||||
// Char = 0x17, // 16-bit Unicode character
|
||||
String = 0x18,
|
||||
// Array mask: 0x40
|
||||
ByteArray = 0x42
|
||||
};
|
||||
|
||||
QByteArray hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey);
|
||||
QSharedPointer<Kdf> kdfFromParameters(const QVariantMap& p);
|
||||
QVariantMap kdfToParameters(QSharedPointer<Kdf> kdf);
|
||||
QSharedPointer<Kdf> uuidToKdf(const Uuid& uuid);
|
||||
Uuid kdfToUuid(QSharedPointer<Kdf> kdf);
|
||||
ProtectedStreamAlgo idToProtectedStreamAlgo(quint32 id);
|
||||
QByteArray hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey);
|
||||
QSharedPointer<Kdf> kdfFromParameters(const QVariantMap& p);
|
||||
QVariantMap kdfToParameters(QSharedPointer<Kdf> kdf);
|
||||
QSharedPointer<Kdf> uuidToKdf(const Uuid& uuid);
|
||||
Uuid kdfToUuid(QSharedPointer<Kdf> kdf);
|
||||
ProtectedStreamAlgo idToProtectedStreamAlgo(quint32 id);
|
||||
|
||||
} // namespace KeePass2
|
||||
} // namespace KeePass2
|
||||
|
||||
#endif // KEEPASSX_KEEPASS2_H
|
||||
|
|
|
@ -30,8 +30,7 @@ bool KeePass2RandomStream::init(const QByteArray& key)
|
|||
{
|
||||
switch (m_cipher.algorithm()) {
|
||||
case SymmetricCipher::Salsa20:
|
||||
return m_cipher.init(CryptoHash::hash(key, CryptoHash::Sha256),
|
||||
KeePass2::INNER_STREAM_SALSA20_IV);
|
||||
return m_cipher.init(CryptoHash::hash(key, CryptoHash::Sha256), KeePass2::INNER_STREAM_SALSA20_IV);
|
||||
case SymmetricCipher::ChaCha20: {
|
||||
QByteArray keyIv = CryptoHash::hash(key, CryptoHash::Sha512);
|
||||
return m_cipher.init(keyIv.left(32), keyIv.mid(32, 12));
|
||||
|
@ -121,7 +120,8 @@ bool KeePass2RandomStream::loadBlock()
|
|||
return true;
|
||||
}
|
||||
|
||||
SymmetricCipher::Algorithm KeePass2RandomStream::mapAlgo(KeePass2::ProtectedStreamAlgo algo) {
|
||||
SymmetricCipher::Algorithm KeePass2RandomStream::mapAlgo(KeePass2::ProtectedStreamAlgo algo)
|
||||
{
|
||||
switch (algo) {
|
||||
case KeePass2::ProtectedStreamAlgo::ChaCha20:
|
||||
return SymmetricCipher::ChaCha20;
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
#include <QByteArray>
|
||||
|
||||
#include "crypto/SymmetricCipher.h"
|
||||
#include "KeePass2.h"
|
||||
#include "crypto/SymmetricCipher.h"
|
||||
|
||||
class KeePass2RandomStream
|
||||
{
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
*/
|
||||
|
||||
#include "format/KeePass2Reader.h"
|
||||
#include "format/KeePass1.h"
|
||||
#include "format/Kdbx3Reader.h"
|
||||
#include "format/Kdbx4Reader.h"
|
||||
#include "format/KeePass1.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
|
|
|
@ -18,21 +18,21 @@
|
|||
#ifndef KEEPASSX_KEEPASS2READER_H
|
||||
#define KEEPASSX_KEEPASS2READER_H
|
||||
|
||||
#include "format/KeePass2.h"
|
||||
#include "core/Database.h"
|
||||
#include "keys/CompositeKey.h"
|
||||
#include "KdbxReader.h"
|
||||
#include "core/Database.h"
|
||||
#include "format/KeePass2.h"
|
||||
#include "keys/CompositeKey.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QCoreApplication>
|
||||
#include <QScopedPointer>
|
||||
#include <QIODevice>
|
||||
#include <QScopedPointer>
|
||||
#include <QString>
|
||||
#include <QtGlobal>
|
||||
|
||||
class KeePass2Reader
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(KdbxReader)
|
||||
Q_DECLARE_TR_FUNCTIONS(KdbxReader)
|
||||
|
||||
public:
|
||||
Database* readDatabase(const QString& filename, const CompositeKey& key);
|
||||
|
@ -46,6 +46,7 @@ public:
|
|||
|
||||
QSharedPointer<KdbxReader> reader() const;
|
||||
quint32 version() const;
|
||||
|
||||
private:
|
||||
void raiseError(const QString& errorMessage);
|
||||
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
#include <QBuffer>
|
||||
|
||||
#include "core/Group.h"
|
||||
#include "format/Kdbx4Reader.h"
|
||||
#include "format/KdbxXmlReader.h"
|
||||
#include "format/KeePass2.h"
|
||||
#include "format/KeePass2RandomStream.h"
|
||||
#include "format/KeePass2Reader.h"
|
||||
#include "format/Kdbx4Reader.h"
|
||||
#include "format/KdbxXmlReader.h"
|
||||
|
||||
KeePass2Repair::RepairOutcome KeePass2Repair::repairDatabase(QIODevice* device, const CompositeKey& key)
|
||||
{
|
||||
|
@ -51,8 +51,7 @@ KeePass2Repair::RepairOutcome KeePass2Repair::repairDatabase(QIODevice* device,
|
|||
QRegExp encodingRegExp("encoding=\"([^\"]+)\"", Qt::CaseInsensitive, QRegExp::RegExp2);
|
||||
if (encodingRegExp.indexIn(xmlStart) != -1) {
|
||||
if (encodingRegExp.cap(1).compare("utf-8", Qt::CaseInsensitive) != 0
|
||||
&& encodingRegExp.cap(1).compare("utf8", Qt::CaseInsensitive) != 0)
|
||||
{
|
||||
&& encodingRegExp.cap(1).compare("utf8", Qt::CaseInsensitive) != 0) {
|
||||
// database is not utf-8 encoded, we don't support repairing that
|
||||
return qMakePair(RepairFailed, nullptr);
|
||||
}
|
||||
|
@ -92,8 +91,7 @@ KeePass2Repair::RepairOutcome KeePass2Repair::repairDatabase(QIODevice* device,
|
|||
|
||||
if (hasError) {
|
||||
return qMakePair(RepairFailed, nullptr);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return qMakePair(RepairSuccess, db.take());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,16 +15,16 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QFile>
|
||||
#include <QIODevice>
|
||||
|
||||
#include "core/Database.h"
|
||||
#include "core/Group.h"
|
||||
#include "core/Metadata.h"
|
||||
#include "crypto/kdf/AesKdf.h"
|
||||
#include "format/KeePass2Writer.h"
|
||||
#include "format/Kdbx3Writer.h"
|
||||
#include "format/Kdbx4Writer.h"
|
||||
#include "format/KeePass2Writer.h"
|
||||
|
||||
/**
|
||||
* Write a database to a KDBX file.
|
||||
|
@ -52,17 +52,17 @@ bool KeePass2Writer::implicitUpgradeNeeded(Database const* db) const
|
|||
return true;
|
||||
}
|
||||
|
||||
for (const auto& group: db->rootGroup()->groupsRecursive(true)) {
|
||||
for (const auto& group : db->rootGroup()->groupsRecursive(true)) {
|
||||
if (group->customData() && !group->customData()->isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const auto& entry: group->entries()) {
|
||||
for (const auto& entry : group->entries()) {
|
||||
if (entry->customData() && !entry->customData()->isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const auto& historyItem: entry->historyItems()) {
|
||||
for (const auto& historyItem : entry->historyItems()) {
|
||||
if (historyItem->customData() && !historyItem->customData()->isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -81,7 +81,8 @@ bool KeePass2Writer::implicitUpgradeNeeded(Database const* db) const
|
|||
* @return true on success
|
||||
*/
|
||||
|
||||
bool KeePass2Writer::writeDatabase(QIODevice* device, Database* db) {
|
||||
bool KeePass2Writer::writeDatabase(QIODevice* device, Database* db)
|
||||
{
|
||||
m_error = false;
|
||||
m_errorStr.clear();
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class Database;
|
|||
|
||||
class KeePass2Writer
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(KeePass2Writer)
|
||||
Q_DECLARE_TR_FUNCTIONS(KeePass2Writer)
|
||||
|
||||
public:
|
||||
bool writeDatabase(const QString& filename, Database* db);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue