mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-25 15:29:44 -05:00
Reformat code, fix minor style issues, make kdf() getter const
This commit is contained in:
parent
d1a19a1009
commit
0d6ca0945b
@ -485,7 +485,7 @@ QString Database::saveToFile(QString filePath)
|
||||
}
|
||||
}
|
||||
|
||||
Kdf* Database::kdf() {
|
||||
Kdf* Database::kdf() const {
|
||||
return m_data.kdf;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ public:
|
||||
|
||||
Uuid cipher() const;
|
||||
Database::CompressionAlgorithm compressionAlgo() const;
|
||||
Kdf* kdf();
|
||||
Kdf* kdf() const;
|
||||
QByteArray transformedMasterKey() const;
|
||||
const CompositeKey& key() const;
|
||||
QByteArray challengeResponseKey() const;
|
||||
|
@ -28,10 +28,7 @@ public:
|
||||
int hashLen;
|
||||
};
|
||||
|
||||
CryptoHash::CryptoHash(CryptoHash::Algorithm algo)
|
||||
: CryptoHash::CryptoHash(algo, false) {}
|
||||
|
||||
CryptoHash::CryptoHash(CryptoHash::Algorithm algo, bool hmac)
|
||||
CryptoHash::CryptoHash(Algorithm algo, bool hmac)
|
||||
: d_ptr(new CryptoHashPrivate())
|
||||
{
|
||||
Q_D(CryptoHash);
|
||||
@ -86,14 +83,14 @@ void CryptoHash::addData(const QByteArray& data)
|
||||
return;
|
||||
}
|
||||
|
||||
gcry_md_write(d->ctx, data.constData(), data.size());
|
||||
gcry_md_write(d->ctx, data.constData(), static_cast<size_t>(data.size()));
|
||||
}
|
||||
|
||||
void CryptoHash::setKey(const QByteArray& data)
|
||||
{
|
||||
Q_D(CryptoHash);
|
||||
|
||||
gcry_error_t error = gcry_md_setkey(d->ctx, data.constData(), data.size());
|
||||
gcry_error_t error = gcry_md_setkey(d->ctx, data.constData(), static_cast<size_t>(data.size()));
|
||||
if (error) {
|
||||
qWarning("Gcrypt error (setKey): %s", gcry_strerror(error));
|
||||
qWarning("Gcrypt error (setKey): %s", gcry_strsource(error));
|
||||
@ -112,11 +109,11 @@ QByteArray CryptoHash::result() const
|
||||
{
|
||||
Q_D(const CryptoHash);
|
||||
|
||||
const char* result = reinterpret_cast<const char*>(gcry_md_read(d->ctx, 0));
|
||||
const auto* result = reinterpret_cast<const char*>(gcry_md_read(d->ctx, 0));
|
||||
return QByteArray(result, d->hashLen);
|
||||
}
|
||||
|
||||
QByteArray CryptoHash::hash(const QByteArray& data, CryptoHash::Algorithm algo)
|
||||
QByteArray CryptoHash::hash(const QByteArray& data, Algorithm algo)
|
||||
{
|
||||
// replace with gcry_md_hash_buffer()?
|
||||
CryptoHash cryptoHash(algo);
|
||||
@ -124,7 +121,7 @@ QByteArray CryptoHash::hash(const QByteArray& data, CryptoHash::Algorithm algo)
|
||||
return cryptoHash.result();
|
||||
}
|
||||
|
||||
QByteArray CryptoHash::hmac(const QByteArray& data, const QByteArray& key, CryptoHash::Algorithm algo)
|
||||
QByteArray CryptoHash::hmac(const QByteArray& data, const QByteArray& key, Algorithm algo)
|
||||
{
|
||||
// replace with gcry_md_hash_buffer()?
|
||||
CryptoHash cryptoHash(algo, true);
|
||||
|
@ -31,15 +31,14 @@ public:
|
||||
Sha512
|
||||
};
|
||||
|
||||
explicit CryptoHash(CryptoHash::Algorithm algo);
|
||||
explicit CryptoHash(CryptoHash::Algorithm algo, bool hmac);
|
||||
explicit CryptoHash(Algorithm algo, bool hmac = false);
|
||||
~CryptoHash();
|
||||
void addData(const QByteArray& data);
|
||||
void reset();
|
||||
QByteArray result() const;
|
||||
void setKey(const QByteArray& data);
|
||||
|
||||
static QByteArray hash(const QByteArray& data, CryptoHash::Algorithm algo);
|
||||
static QByteArray hash(const QByteArray& data, Algorithm algo);
|
||||
static QByteArray hmac(const QByteArray& data, const QByteArray& key, Algorithm algo);
|
||||
|
||||
private:
|
||||
|
@ -20,8 +20,7 @@
|
||||
#include "config-keepassx.h"
|
||||
#include "crypto/SymmetricCipherGcrypt.h"
|
||||
|
||||
SymmetricCipher::SymmetricCipher(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
|
||||
SymmetricCipher::Direction direction)
|
||||
SymmetricCipher::SymmetricCipher(Algorithm algo, Mode mode, Direction direction)
|
||||
: m_backend(createBackend(algo, mode, direction))
|
||||
, m_initialized(false)
|
||||
, m_algo(algo)
|
||||
@ -55,14 +54,13 @@ bool SymmetricCipher::isInitalized() const
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
SymmetricCipherBackend* SymmetricCipher::createBackend(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
|
||||
SymmetricCipher::Direction direction)
|
||||
SymmetricCipherBackend* SymmetricCipher::createBackend(Algorithm algo, Mode mode, Direction direction)
|
||||
{
|
||||
switch (algo) {
|
||||
case SymmetricCipher::Aes256:
|
||||
case SymmetricCipher::Twofish:
|
||||
case SymmetricCipher::Salsa20:
|
||||
case SymmetricCipher::ChaCha20:
|
||||
case Aes256:
|
||||
case Twofish:
|
||||
case Salsa20:
|
||||
case ChaCha20:
|
||||
return new SymmetricCipherGcrypt(algo, mode, direction);
|
||||
|
||||
default:
|
||||
@ -94,25 +92,25 @@ QString SymmetricCipher::errorString() const
|
||||
SymmetricCipher::Algorithm SymmetricCipher::cipherToAlgorithm(Uuid cipher)
|
||||
{
|
||||
if (cipher == KeePass2::CIPHER_AES) {
|
||||
return SymmetricCipher::Aes256;
|
||||
return Aes256;
|
||||
} else if (cipher == KeePass2::CIPHER_CHACHA20) {
|
||||
return SymmetricCipher::ChaCha20;
|
||||
return ChaCha20;
|
||||
} else if (cipher == KeePass2::CIPHER_TWOFISH) {
|
||||
return SymmetricCipher::Twofish;
|
||||
return Twofish;
|
||||
}
|
||||
|
||||
qWarning("SymmetricCipher::cipherToAlgorithm: invalid Uuid %s", cipher.toByteArray().toHex().data());
|
||||
return InvalidAlgorithm;
|
||||
}
|
||||
|
||||
Uuid SymmetricCipher::algorithmToCipher(SymmetricCipher::Algorithm algo)
|
||||
Uuid SymmetricCipher::algorithmToCipher(Algorithm algo)
|
||||
{
|
||||
switch (algo) {
|
||||
case SymmetricCipher::Aes256:
|
||||
case Aes256:
|
||||
return KeePass2::CIPHER_AES;
|
||||
case SymmetricCipher::ChaCha20:
|
||||
case ChaCha20:
|
||||
return KeePass2::CIPHER_CHACHA20;
|
||||
case SymmetricCipher::Twofish:
|
||||
case Twofish:
|
||||
return KeePass2::CIPHER_TWOFISH;
|
||||
default:
|
||||
qWarning("SymmetricCipher::algorithmToCipher: invalid algorithm %d", algo);
|
||||
@ -120,12 +118,14 @@ Uuid SymmetricCipher::algorithmToCipher(SymmetricCipher::Algorithm algo)
|
||||
}
|
||||
}
|
||||
|
||||
int SymmetricCipher::algorithmIvSize(SymmetricCipher::Algorithm algo) {
|
||||
int SymmetricCipher::algorithmIvSize(Algorithm algo)
|
||||
{
|
||||
switch (algo) {
|
||||
case SymmetricCipher::ChaCha20:
|
||||
case ChaCha20:
|
||||
return 12;
|
||||
case SymmetricCipher::Aes256:
|
||||
case SymmetricCipher::Twofish:
|
||||
case Aes256:
|
||||
return 16;
|
||||
case Twofish:
|
||||
return 16;
|
||||
default:
|
||||
qWarning("SymmetricCipher::algorithmIvSize: invalid algorithm %d", algo);
|
||||
@ -133,19 +133,21 @@ int SymmetricCipher::algorithmIvSize(SymmetricCipher::Algorithm algo) {
|
||||
}
|
||||
}
|
||||
|
||||
SymmetricCipher::Mode SymmetricCipher::algorithmMode(SymmetricCipher::Algorithm algo) {
|
||||
SymmetricCipher::Mode SymmetricCipher::algorithmMode(Algorithm algo)
|
||||
{
|
||||
switch (algo) {
|
||||
case SymmetricCipher::ChaCha20:
|
||||
return SymmetricCipher::Stream;
|
||||
case SymmetricCipher::Aes256:
|
||||
case SymmetricCipher::Twofish:
|
||||
return SymmetricCipher::Cbc;
|
||||
case ChaCha20:
|
||||
return Stream;
|
||||
case Aes256:
|
||||
case Twofish:
|
||||
return Cbc;
|
||||
default:
|
||||
qWarning("SymmetricCipher::algorithmMode: invalid algorithm %d", algo);
|
||||
return SymmetricCipher::InvalidMode;
|
||||
return InvalidMode;
|
||||
}
|
||||
}
|
||||
|
||||
SymmetricCipher::Algorithm SymmetricCipher::algorithm() const {
|
||||
SymmetricCipher::Algorithm SymmetricCipher::algorithm() const
|
||||
{
|
||||
return m_algo;
|
||||
}
|
||||
|
@ -53,22 +53,25 @@ public:
|
||||
Encrypt
|
||||
};
|
||||
|
||||
SymmetricCipher(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
|
||||
SymmetricCipher::Direction direction);
|
||||
SymmetricCipher(Algorithm algo, Mode mode, Direction direction);
|
||||
~SymmetricCipher();
|
||||
Q_DISABLE_COPY(SymmetricCipher)
|
||||
|
||||
bool init(const QByteArray& key, const QByteArray& iv);
|
||||
bool isInitalized() const;
|
||||
|
||||
inline QByteArray process(const QByteArray& data, bool* ok) {
|
||||
inline QByteArray process(const QByteArray& data, bool* ok)
|
||||
{
|
||||
return m_backend->process(data, ok);
|
||||
}
|
||||
|
||||
Q_REQUIRED_RESULT inline bool processInPlace(QByteArray& data) {
|
||||
Q_REQUIRED_RESULT inline bool processInPlace(QByteArray& data)
|
||||
{
|
||||
return m_backend->processInPlace(data);
|
||||
}
|
||||
|
||||
Q_REQUIRED_RESULT inline bool processInPlace(QByteArray& data, quint64 rounds) {
|
||||
Q_REQUIRED_RESULT inline bool processInPlace(QByteArray& data, quint64 rounds)
|
||||
{
|
||||
Q_ASSERT(rounds > 0);
|
||||
return m_backend->processInPlace(data, rounds);
|
||||
}
|
||||
@ -85,14 +88,11 @@ public:
|
||||
static Mode algorithmMode(Algorithm algo);
|
||||
|
||||
private:
|
||||
static SymmetricCipherBackend* createBackend(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
|
||||
SymmetricCipher::Direction direction);
|
||||
static SymmetricCipherBackend* createBackend(Algorithm algo, Mode mode, Direction direction);
|
||||
|
||||
const QScopedPointer<SymmetricCipherBackend> m_backend;
|
||||
bool m_initialized;
|
||||
Algorithm m_algo;
|
||||
|
||||
Q_DISABLE_COPY(SymmetricCipher)
|
||||
};
|
||||
|
||||
#endif // KEEPASSX_SYMMETRICCIPHER_H
|
||||
|
@ -145,8 +145,7 @@ QByteArray SymmetricCipherGcrypt::process(const QByteArray& data, bool* ok)
|
||||
|
||||
if (m_direction == SymmetricCipher::Decrypt) {
|
||||
error = gcry_cipher_decrypt(m_ctx, result.data(), data.size(), data.constData(), data.size());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
error = gcry_cipher_encrypt(m_ctx, result.data(), data.size(), data.constData(), data.size());
|
||||
}
|
||||
|
||||
@ -154,7 +153,7 @@ QByteArray SymmetricCipherGcrypt::process(const QByteArray& data, bool* ok)
|
||||
setErrorString(error);
|
||||
*ok = false;
|
||||
} else {
|
||||
*ok = true;
|
||||
*ok = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -168,8 +167,7 @@ bool SymmetricCipherGcrypt::processInPlace(QByteArray& data)
|
||||
|
||||
if (m_direction == SymmetricCipher::Decrypt) {
|
||||
error = gcry_cipher_decrypt(m_ctx, data.data(), data.size(), nullptr, 0);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
error = gcry_cipher_encrypt(m_ctx, data.data(), data.size(), nullptr, 0);
|
||||
}
|
||||
|
||||
@ -199,8 +197,7 @@ bool SymmetricCipherGcrypt::processInPlace(QByteArray& data, quint64 rounds)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
for (quint64 i = 0; i != rounds; ++i) {
|
||||
error = gcry_cipher_encrypt(m_ctx, rawData, size, nullptr, 0);
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "crypto/SymmetricCipher.h"
|
||||
#include "crypto/SymmetricCipherBackend.h"
|
||||
|
||||
class SymmetricCipherGcrypt : public SymmetricCipherBackend
|
||||
class SymmetricCipherGcrypt: public SymmetricCipherBackend
|
||||
{
|
||||
public:
|
||||
SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 KeePassXC Team
|
||||
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* 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
|
||||
@ -28,7 +28,7 @@ const QList<Kdf::Field> AesKdf::FIELDS = AesKdf::initFields();
|
||||
QList<Kdf::Field> AesKdf::initFields()
|
||||
{
|
||||
return QList<Kdf::Field> {
|
||||
Kdf::Field(static_cast<quint32>(Fields::ROUNDS), "Transform rounds", 1, UINT64_MAX, true),
|
||||
Kdf::Field(static_cast<quint32>(Fields::ROUNDS), "Transform rounds", 1, UINT64_MAX, true),
|
||||
};
|
||||
}
|
||||
|
||||
@ -67,7 +67,8 @@ bool AesKdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, quin
|
||||
*result = key;
|
||||
|
||||
if (!cipher.processInPlace(*result, rounds)) {
|
||||
qWarning("AesKdf::transformKeyRaw: error in SymmetricCipher::processInPlace: %s", cipher.errorString().toUtf8().data());
|
||||
qWarning("AesKdf::transformKeyRaw: error in SymmetricCipher::processInPlace: %s",
|
||||
cipher.errorString().toUtf8().data());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -129,20 +130,20 @@ const QList<Kdf::Field> AesKdf::fields() const
|
||||
quint64 AesKdf::field(quint32 id) const
|
||||
{
|
||||
switch (static_cast<Fields>(id)) {
|
||||
case Fields::ROUNDS:
|
||||
return m_rounds;
|
||||
default:
|
||||
return 0;
|
||||
case Fields::ROUNDS:
|
||||
return m_rounds;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool AesKdf::setField(quint32 id, quint64 val)
|
||||
{
|
||||
switch (static_cast<Fields>(id)) {
|
||||
case Fields::ROUNDS:
|
||||
return setRounds(val);
|
||||
default:
|
||||
return false;
|
||||
case Fields::ROUNDS:
|
||||
return setRounds(val);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,7 +166,8 @@ int AesKdf::benchmarkImpl(int msec) const
|
||||
break;
|
||||
}
|
||||
rounds += 10000;
|
||||
} while (!t.hasExpired(msec));
|
||||
}
|
||||
while (!t.hasExpired(msec));
|
||||
|
||||
return rounds;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 KeePassXC Team
|
||||
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* 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
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
#include "Kdf.h"
|
||||
|
||||
class AesKdf : public Kdf
|
||||
class AesKdf: public Kdf
|
||||
{
|
||||
public:
|
||||
AesKdf();
|
||||
@ -40,7 +40,7 @@ public:
|
||||
bool setRounds(quint64 rounds);
|
||||
bool setSeed(const QByteArray& seed);
|
||||
|
||||
enum class Fields : quint32
|
||||
enum class Fields: quint32
|
||||
{
|
||||
ROUNDS,
|
||||
SEED
|
||||
@ -55,7 +55,10 @@ private:
|
||||
quint64 m_rounds;
|
||||
QByteArray m_seed;
|
||||
|
||||
static bool transformKeyRaw(const QByteArray& key, const QByteArray& seed, quint64 rounds, QByteArray* result) Q_REQUIRED_RESULT;
|
||||
static bool transformKeyRaw(const QByteArray& key,
|
||||
const QByteArray& seed,
|
||||
quint64 rounds,
|
||||
QByteArray* result) Q_REQUIRED_RESULT;
|
||||
static QList<Kdf::Field> initFields();
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 KeePassXC Team
|
||||
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* 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
|
||||
@ -23,11 +23,11 @@
|
||||
#include <QtConcurrent>
|
||||
|
||||
Kdf::Field::Field(quint32 id, const QString& name, quint64 min, quint64 max, bool benchmark)
|
||||
: m_id(id)
|
||||
, m_name(name)
|
||||
, m_min(min)
|
||||
, m_max(max)
|
||||
, m_benchmark(benchmark)
|
||||
: m_id(id)
|
||||
, m_name(name)
|
||||
, m_min(min)
|
||||
, m_max(max)
|
||||
, m_benchmark(benchmark)
|
||||
{
|
||||
}
|
||||
|
||||
@ -71,8 +71,7 @@ int Kdf::benchmark(int msec) const
|
||||
}
|
||||
|
||||
Kdf::BenchmarkThread::BenchmarkThread(int msec, const Kdf* kdf)
|
||||
: m_msec(msec)
|
||||
, m_kdf(kdf)
|
||||
: m_msec(msec), m_kdf(kdf)
|
||||
{
|
||||
}
|
||||
|
||||
@ -81,6 +80,7 @@ int Kdf::BenchmarkThread::rounds()
|
||||
return m_rounds;
|
||||
}
|
||||
|
||||
void Kdf::BenchmarkThread::run() {
|
||||
void Kdf::BenchmarkThread::run()
|
||||
{
|
||||
m_rounds = m_kdf->benchmarkImpl(m_msec);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 KeePassXC Team
|
||||
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* 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
|
||||
@ -25,11 +25,13 @@
|
||||
class Kdf
|
||||
{
|
||||
public:
|
||||
enum class Type {
|
||||
enum class Type
|
||||
{
|
||||
AES
|
||||
};
|
||||
|
||||
class Field {
|
||||
class Field
|
||||
{
|
||||
public:
|
||||
Field(quint32 id, const QString& name, quint64 min, quint64 max, bool benchmark = false);
|
||||
|
||||
@ -48,9 +50,11 @@ public:
|
||||
};
|
||||
|
||||
virtual ~Kdf() {}
|
||||
|
||||
virtual QByteArray seed() const = 0;
|
||||
virtual Type type() const = 0;
|
||||
virtual bool transform(const QByteArray& raw, QByteArray& result) const = 0;
|
||||
virtual void randomizeTransformSalt() = 0;
|
||||
virtual Type type() const = 0;
|
||||
virtual Kdf* clone() const = 0;
|
||||
|
||||
virtual const QList<Field> fields() const = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 KeePassXC Team
|
||||
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* 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
|
||||
@ -22,9 +22,9 @@
|
||||
#ifndef KEEPASSXC_KDF_P_H
|
||||
#define KEEPASSXC_KDF_P_H
|
||||
|
||||
class Kdf::BenchmarkThread : public QThread
|
||||
class Kdf::BenchmarkThread: public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BenchmarkThread(int msec, const Kdf* kdf);
|
||||
|
@ -71,18 +71,17 @@ Database* Kdbx3Reader::readDatabase(QIODevice* device, const CompositeKey& key,
|
||||
quint32 signature2 = Endian::readSizedInt<quint32>(m_headerStream, KeePass2::BYTEORDER, &ok);
|
||||
if (ok && signature2 == KeePass1::SIGNATURE_2) {
|
||||
raiseError(tr("The selected file is an old KeePass 1 database (.kdb).\n\n"
|
||||
"You can import it by clicking on Database > 'Import KeePass 1 database...'.\n"
|
||||
"This is a one-way migration. You won't be able to open the imported "
|
||||
"database with the old KeePassX 0.4 version."));
|
||||
"You can import it by clicking on Database > 'Import KeePass 1 database...'.\n"
|
||||
"This is a one-way migration. You won't be able to open the imported "
|
||||
"database with the old KeePassX 0.4 version."));
|
||||
return nullptr;
|
||||
}
|
||||
else if (!ok || signature2 != KeePass2::SIGNATURE_2) {
|
||||
} else if (!ok || signature2 != KeePass2::SIGNATURE_2) {
|
||||
raiseError(tr("Not a KeePass database."));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
quint32 version = Endian::readSizedInt<quint32>(m_headerStream, KeePass2::BYTEORDER, &ok)
|
||||
& KeePass2::FILE_VERSION_CRITICAL_MASK;
|
||||
& KeePass2::FILE_VERSION_CRITICAL_MASK;
|
||||
quint32 maxVersion = KeePass2::FILE_VERSION & KeePass2::FILE_VERSION_CRITICAL_MASK;
|
||||
if (!ok || (version < KeePass2::FILE_VERSION_MIN) || (version > maxVersion)) {
|
||||
raiseError(tr("Unsupported KeePass KDBX 2 or 3 database version."));
|
||||
@ -100,8 +99,8 @@ Database* Kdbx3Reader::readDatabase(QIODevice* device, const CompositeKey& key,
|
||||
|
||||
// check if all required headers were present
|
||||
if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty()
|
||||
|| m_streamStartBytes.isEmpty() || m_protectedStreamKey.isEmpty()
|
||||
|| m_db->cipher().isNull()) {
|
||||
|| m_streamStartBytes.isEmpty() || m_protectedStreamKey.isEmpty()
|
||||
|| m_db->cipher().isNull()) {
|
||||
raiseError("missing database headers");
|
||||
return nullptr;
|
||||
}
|
||||
@ -152,8 +151,7 @@ Database* Kdbx3Reader::readDatabase(QIODevice* device, const CompositeKey& key,
|
||||
|
||||
if (m_db->compressionAlgo() == Database::CompressionNone) {
|
||||
xmlDevice = &hashedStream;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ioCompressor.reset(new QtIOCompressor(&hashedStream));
|
||||
ioCompressor->setStreamFormat(QtIOCompressor::GzipFormat);
|
||||
if (!ioCompressor->open(QIODevice::ReadOnly)) {
|
||||
@ -185,8 +183,7 @@ Database* Kdbx3Reader::readDatabase(QIODevice* device, const CompositeKey& key,
|
||||
raiseError(xmlReader.errorString());
|
||||
if (keepDatabase) {
|
||||
return db.take();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -297,14 +294,12 @@ void Kdbx3Reader::setCompressionFlags(const QByteArray& data)
|
||||
{
|
||||
if (data.size() != 4) {
|
||||
raiseError("Invalid compression flags length");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
quint32 id = Endian::bytesToSizedInt<quint32>(data, KeePass2::BYTEORDER);
|
||||
|
||||
if (id > Database::CompressionAlgorithmMax) {
|
||||
raiseError("Unsupported compression algorithm");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
m_db->setCompressionAlgo(static_cast<Database::CompressionAlgorithm>(id));
|
||||
}
|
||||
}
|
||||
@ -314,8 +309,7 @@ void Kdbx3Reader::setMasterSeed(const QByteArray& data)
|
||||
{
|
||||
if (data.size() != 32) {
|
||||
raiseError("Invalid master seed size");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
m_masterSeed = data;
|
||||
}
|
||||
}
|
||||
@ -324,8 +318,7 @@ void Kdbx3Reader::setTransformSeed(const QByteArray& data)
|
||||
{
|
||||
if (data.size() != 32) {
|
||||
raiseError("Invalid transform seed size");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
AesKdf* aesKdf;
|
||||
if (m_db->kdf()->type() == Kdf::Type::AES) {
|
||||
aesKdf = static_cast<AesKdf*>(m_db->kdf());
|
||||
@ -342,8 +335,7 @@ void Kdbx3Reader::setTransformRounds(const QByteArray& data)
|
||||
{
|
||||
if (data.size() != 8) {
|
||||
raiseError("Invalid transform rounds size");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
quint64 rounds = Endian::bytesToSizedInt<quint64>(data, KeePass2::BYTEORDER);
|
||||
|
||||
AesKdf* aesKdf;
|
||||
@ -352,10 +344,10 @@ void Kdbx3Reader::setTransformRounds(const QByteArray& data)
|
||||
} else {
|
||||
aesKdf = new AesKdf();
|
||||
m_db->setKdf(aesKdf);
|
||||
}
|
||||
}
|
||||
|
||||
aesKdf->setRounds(rounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Kdbx3Reader::setEncryptionIV(const QByteArray& data)
|
||||
@ -372,8 +364,7 @@ void Kdbx3Reader::setStreamStartBytes(const QByteArray& data)
|
||||
{
|
||||
if (data.size() != 32) {
|
||||
raiseError("Invalid start bytes size");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
m_streamStartBytes = data;
|
||||
}
|
||||
}
|
||||
|
@ -26,9 +26,9 @@
|
||||
class Database;
|
||||
class QIODevice;
|
||||
|
||||
class Kdbx3Reader : public BaseKeePass2Reader
|
||||
class Kdbx3Reader: public BaseKeePass2Reader
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx3Reader)
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx3Reader)
|
||||
|
||||
public:
|
||||
Kdbx3Reader();
|
||||
|
@ -78,20 +78,20 @@ bool Kdbx3Writer::writeDatabase(QIODevice* device, Database* db)
|
||||
|
||||
CHECK_RETURN_FALSE(writeHeaderField(KeePass2::CipherID, db->cipher().toByteArray()));
|
||||
CHECK_RETURN_FALSE(writeHeaderField(KeePass2::CompressionFlags,
|
||||
Endian::sizedIntToBytes<qint32>(db->compressionAlgo(),
|
||||
KeePass2::BYTEORDER)));
|
||||
Endian::sizedIntToBytes<qint32>(db->compressionAlgo(),
|
||||
KeePass2::BYTEORDER)));
|
||||
AesKdf* kdf = static_cast<AesKdf*>(db->kdf());
|
||||
CHECK_RETURN_FALSE(writeHeaderField(KeePass2::MasterSeed, masterSeed));
|
||||
CHECK_RETURN_FALSE(writeHeaderField(KeePass2::TransformSeed, kdf->seed()));
|
||||
CHECK_RETURN_FALSE(writeHeaderField(KeePass2::TransformRounds,
|
||||
Endian::sizedIntToBytes<qint64>(kdf->rounds(),
|
||||
KeePass2::BYTEORDER)));
|
||||
Endian::sizedIntToBytes<qint64>(kdf->rounds(),
|
||||
KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(writeHeaderField(KeePass2::EncryptionIV, encryptionIV));
|
||||
CHECK_RETURN_FALSE(writeHeaderField(KeePass2::ProtectedStreamKey, protectedStreamKey));
|
||||
CHECK_RETURN_FALSE(writeHeaderField(KeePass2::StreamStartBytes, startBytes));
|
||||
CHECK_RETURN_FALSE(writeHeaderField(KeePass2::InnerRandomStreamID,
|
||||
Endian::sizedIntToBytes<qint32>(KeePass2::Salsa20,
|
||||
KeePass2::BYTEORDER)));
|
||||
Endian::sizedIntToBytes<qint32>(KeePass2::Salsa20,
|
||||
KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(writeHeaderField(KeePass2::EndOfHeader, endOfHeader));
|
||||
|
||||
header.close();
|
||||
@ -120,8 +120,7 @@ bool Kdbx3Writer::writeDatabase(QIODevice* device, Database* db)
|
||||
|
||||
if (db->compressionAlgo() == Database::CompressionNone) {
|
||||
m_device = &hashedStream;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ioCompressor.reset(new QtIOCompressor(&hashedStream));
|
||||
ioCompressor->setStreamFormat(QtIOCompressor::GzipFormat);
|
||||
if (!ioCompressor->open(QIODevice::WriteOnly)) {
|
||||
@ -166,8 +165,7 @@ bool Kdbx3Writer::writeData(const QByteArray& data)
|
||||
if (m_device->write(data) != data.size()) {
|
||||
raiseError(m_device->errorString());
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -180,7 +178,7 @@ bool Kdbx3Writer::writeHeaderField(KeePass2::HeaderFieldID fieldId, const QByteA
|
||||
fieldIdArr[0] = fieldId;
|
||||
CHECK_RETURN_FALSE(writeData(fieldIdArr));
|
||||
CHECK_RETURN_FALSE(writeData(Endian::sizedIntToBytes<qint16>(static_cast<quint16>(data.size()),
|
||||
KeePass2::BYTEORDER)));
|
||||
KeePass2::BYTEORDER)));
|
||||
CHECK_RETURN_FALSE(writeData(data));
|
||||
|
||||
return true;
|
||||
|
@ -27,9 +27,9 @@
|
||||
class Database;
|
||||
class QIODevice;
|
||||
|
||||
class Kdbx3Writer : public BaseKeePass2Writer
|
||||
class Kdbx3Writer: public BaseKeePass2Writer
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx3Writer)
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx3Writer)
|
||||
|
||||
public:
|
||||
Kdbx3Writer();
|
||||
|
@ -150,14 +150,12 @@ QString Kdbx3XmlReader::errorString()
|
||||
{
|
||||
if (m_error) {
|
||||
return m_errorStr;
|
||||
}
|
||||
else if (m_xml.hasError()) {
|
||||
} else if (m_xml.hasError()) {
|
||||
return QString("XML error:\n%1\nLine %2, column %3")
|
||||
.arg(m_xml.errorString())
|
||||
.arg(m_xml.lineNumber())
|
||||
.arg(m_xml.columnNumber());
|
||||
}
|
||||
else {
|
||||
.arg(m_xml.errorString())
|
||||
.arg(m_xml.lineNumber())
|
||||
.arg(m_xml.columnNumber());
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
@ -183,18 +181,15 @@ bool Kdbx3XmlReader::parseKeePassFile()
|
||||
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||
if (m_xml.name() == "Meta") {
|
||||
parseMeta();
|
||||
}
|
||||
else if (m_xml.name() == "Root") {
|
||||
} else if (m_xml.name() == "Root") {
|
||||
if (rootElementFound) {
|
||||
rootParsedSuccessfully = false;
|
||||
raiseError("Multiple root elements");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
rootParsedSuccessfully = parseRoot();
|
||||
rootElementFound = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -209,95 +204,67 @@ void Kdbx3XmlReader::parseMeta()
|
||||
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||
if (m_xml.name() == "Generator") {
|
||||
m_meta->setGenerator(readString());
|
||||
}
|
||||
else if (m_xml.name() == "HeaderHash") {
|
||||
} else if (m_xml.name() == "HeaderHash") {
|
||||
m_headerHash = readBinary();
|
||||
}
|
||||
else if (m_xml.name() == "DatabaseName") {
|
||||
} else if (m_xml.name() == "DatabaseName") {
|
||||
m_meta->setName(readString());
|
||||
}
|
||||
else if (m_xml.name() == "DatabaseNameChanged") {
|
||||
} else if (m_xml.name() == "DatabaseNameChanged") {
|
||||
m_meta->setNameChanged(readDateTime());
|
||||
}
|
||||
else if (m_xml.name() == "DatabaseDescription") {
|
||||
} else if (m_xml.name() == "DatabaseDescription") {
|
||||
m_meta->setDescription(readString());
|
||||
}
|
||||
else if (m_xml.name() == "DatabaseDescriptionChanged") {
|
||||
} else if (m_xml.name() == "DatabaseDescriptionChanged") {
|
||||
m_meta->setDescriptionChanged(readDateTime());
|
||||
}
|
||||
else if (m_xml.name() == "DefaultUserName") {
|
||||
} else if (m_xml.name() == "DefaultUserName") {
|
||||
m_meta->setDefaultUserName(readString());
|
||||
}
|
||||
else if (m_xml.name() == "DefaultUserNameChanged") {
|
||||
} else if (m_xml.name() == "DefaultUserNameChanged") {
|
||||
m_meta->setDefaultUserNameChanged(readDateTime());
|
||||
}
|
||||
else if (m_xml.name() == "MaintenanceHistoryDays") {
|
||||
} else if (m_xml.name() == "MaintenanceHistoryDays") {
|
||||
m_meta->setMaintenanceHistoryDays(readNumber());
|
||||
}
|
||||
else if (m_xml.name() == "Color") {
|
||||
} else if (m_xml.name() == "Color") {
|
||||
m_meta->setColor(readColor());
|
||||
}
|
||||
else if (m_xml.name() == "MasterKeyChanged") {
|
||||
} else if (m_xml.name() == "MasterKeyChanged") {
|
||||
m_meta->setMasterKeyChanged(readDateTime());
|
||||
}
|
||||
else if (m_xml.name() == "MasterKeyChangeRec") {
|
||||
} else if (m_xml.name() == "MasterKeyChangeRec") {
|
||||
m_meta->setMasterKeyChangeRec(readNumber());
|
||||
}
|
||||
else if (m_xml.name() == "MasterKeyChangeForce") {
|
||||
} else if (m_xml.name() == "MasterKeyChangeForce") {
|
||||
m_meta->setMasterKeyChangeForce(readNumber());
|
||||
}
|
||||
else if (m_xml.name() == "MemoryProtection") {
|
||||
} else if (m_xml.name() == "MemoryProtection") {
|
||||
parseMemoryProtection();
|
||||
}
|
||||
else if (m_xml.name() == "CustomIcons") {
|
||||
} else if (m_xml.name() == "CustomIcons") {
|
||||
parseCustomIcons();
|
||||
}
|
||||
else if (m_xml.name() == "RecycleBinEnabled") {
|
||||
} else if (m_xml.name() == "RecycleBinEnabled") {
|
||||
m_meta->setRecycleBinEnabled(readBool());
|
||||
}
|
||||
else if (m_xml.name() == "RecycleBinUUID") {
|
||||
} else if (m_xml.name() == "RecycleBinUUID") {
|
||||
m_meta->setRecycleBin(getGroup(readUuid()));
|
||||
}
|
||||
else if (m_xml.name() == "RecycleBinChanged") {
|
||||
} else if (m_xml.name() == "RecycleBinChanged") {
|
||||
m_meta->setRecycleBinChanged(readDateTime());
|
||||
}
|
||||
else if (m_xml.name() == "EntryTemplatesGroup") {
|
||||
} else if (m_xml.name() == "EntryTemplatesGroup") {
|
||||
m_meta->setEntryTemplatesGroup(getGroup(readUuid()));
|
||||
}
|
||||
else if (m_xml.name() == "EntryTemplatesGroupChanged") {
|
||||
} else if (m_xml.name() == "EntryTemplatesGroupChanged") {
|
||||
m_meta->setEntryTemplatesGroupChanged(readDateTime());
|
||||
}
|
||||
else if (m_xml.name() == "LastSelectedGroup") {
|
||||
} else if (m_xml.name() == "LastSelectedGroup") {
|
||||
m_meta->setLastSelectedGroup(getGroup(readUuid()));
|
||||
}
|
||||
else if (m_xml.name() == "LastTopVisibleGroup") {
|
||||
} else if (m_xml.name() == "LastTopVisibleGroup") {
|
||||
m_meta->setLastTopVisibleGroup(getGroup(readUuid()));
|
||||
}
|
||||
else if (m_xml.name() == "HistoryMaxItems") {
|
||||
} else if (m_xml.name() == "HistoryMaxItems") {
|
||||
int value = readNumber();
|
||||
if (value >= -1) {
|
||||
m_meta->setHistoryMaxItems(value);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
raiseError("HistoryMaxItems invalid number");
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "HistoryMaxSize") {
|
||||
} else if (m_xml.name() == "HistoryMaxSize") {
|
||||
int value = readNumber();
|
||||
if (value >= -1) {
|
||||
m_meta->setHistoryMaxSize(value);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
raiseError("HistoryMaxSize invalid number");
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "Binaries") {
|
||||
} else if (m_xml.name() == "Binaries") {
|
||||
parseBinaries();
|
||||
}
|
||||
else if (m_xml.name() == "CustomData") {
|
||||
} else if (m_xml.name() == "CustomData") {
|
||||
parseCustomData();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -310,20 +277,15 @@ void Kdbx3XmlReader::parseMemoryProtection()
|
||||
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||
if (m_xml.name() == "ProtectTitle") {
|
||||
m_meta->setProtectTitle(readBool());
|
||||
}
|
||||
else if (m_xml.name() == "ProtectUserName") {
|
||||
} else if (m_xml.name() == "ProtectUserName") {
|
||||
m_meta->setProtectUsername(readBool());
|
||||
}
|
||||
else if (m_xml.name() == "ProtectPassword") {
|
||||
} else if (m_xml.name() == "ProtectPassword") {
|
||||
m_meta->setProtectPassword(readBool());
|
||||
}
|
||||
else if (m_xml.name() == "ProtectURL") {
|
||||
} else if (m_xml.name() == "ProtectURL") {
|
||||
m_meta->setProtectUrl(readBool());
|
||||
}
|
||||
else if (m_xml.name() == "ProtectNotes") {
|
||||
} else if (m_xml.name() == "ProtectNotes") {
|
||||
m_meta->setProtectNotes(readBool());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -336,8 +298,7 @@ void Kdbx3XmlReader::parseCustomIcons()
|
||||
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||
if (m_xml.name() == "Icon") {
|
||||
parseIcon();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -356,20 +317,17 @@ void Kdbx3XmlReader::parseIcon()
|
||||
if (m_xml.name() == "UUID") {
|
||||
uuid = readUuid();
|
||||
uuidSet = !uuid.isNull();
|
||||
}
|
||||
else if (m_xml.name() == "Data") {
|
||||
} else if (m_xml.name() == "Data") {
|
||||
icon.loadFromData(readBinary());
|
||||
iconSet = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
if (uuidSet && iconSet) {
|
||||
m_meta->addCustomIcon(uuid, icon);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
raiseError("Missing icon uuid or data");
|
||||
}
|
||||
}
|
||||
@ -387,8 +345,7 @@ void Kdbx3XmlReader::parseBinaries()
|
||||
QByteArray data;
|
||||
if (attr.value("Compressed").compare(QLatin1String("True"), Qt::CaseInsensitive) == 0) {
|
||||
data = readCompressedBinary();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
data = readBinary();
|
||||
}
|
||||
|
||||
@ -398,8 +355,7 @@ void Kdbx3XmlReader::parseBinaries()
|
||||
}
|
||||
|
||||
m_binaryPool.insert(id, data);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -412,8 +368,7 @@ void Kdbx3XmlReader::parseCustomData()
|
||||
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||
if (m_xml.name() == "Item") {
|
||||
parseCustomDataItem();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -432,20 +387,17 @@ void Kdbx3XmlReader::parseCustomDataItem()
|
||||
if (m_xml.name() == "Key") {
|
||||
key = readString();
|
||||
keySet = true;
|
||||
}
|
||||
else if (m_xml.name() == "Value") {
|
||||
} else if (m_xml.name() == "Value") {
|
||||
value = readString();
|
||||
valueSet = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
if (keySet && valueSet) {
|
||||
m_meta->addCustomField(key, value);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
raiseError("Missing custom data key or value");
|
||||
}
|
||||
}
|
||||
@ -474,11 +426,9 @@ bool Kdbx3XmlReader::parseRoot()
|
||||
}
|
||||
|
||||
groupElementFound = true;
|
||||
}
|
||||
else if (m_xml.name() == "DeletedObjects") {
|
||||
} else if (m_xml.name() == "DeletedObjects") {
|
||||
parseDeletedObjects();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -500,99 +450,77 @@ Group* Kdbx3XmlReader::parseGroup()
|
||||
if (uuid.isNull()) {
|
||||
if (m_strictMode) {
|
||||
raiseError("Null group uuid");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
group->setUuid(Uuid::random());
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
group->setUuid(uuid);
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "Name") {
|
||||
} else if (m_xml.name() == "Name") {
|
||||
group->setName(readString());
|
||||
}
|
||||
else if (m_xml.name() == "Notes") {
|
||||
} else if (m_xml.name() == "Notes") {
|
||||
group->setNotes(readString());
|
||||
}
|
||||
else if (m_xml.name() == "IconID") {
|
||||
} else if (m_xml.name() == "IconID") {
|
||||
int iconId = readNumber();
|
||||
if (iconId < 0) {
|
||||
if (m_strictMode) {
|
||||
raiseError("Invalid group icon number");
|
||||
}
|
||||
iconId = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (iconId >= DatabaseIcons::IconCount) {
|
||||
qWarning("Kdbx3XmlReader::parseGroup: icon id \"%d\" not supported", iconId);
|
||||
}
|
||||
group->setIcon(iconId);
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "CustomIconUUID") {
|
||||
} else if (m_xml.name() == "CustomIconUUID") {
|
||||
Uuid uuid = readUuid();
|
||||
if (!uuid.isNull()) {
|
||||
group->setIcon(uuid);
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "Times") {
|
||||
} else if (m_xml.name() == "Times") {
|
||||
group->setTimeInfo(parseTimes());
|
||||
}
|
||||
else if (m_xml.name() == "IsExpanded") {
|
||||
} else if (m_xml.name() == "IsExpanded") {
|
||||
group->setExpanded(readBool());
|
||||
}
|
||||
else if (m_xml.name() == "DefaultAutoTypeSequence") {
|
||||
} else if (m_xml.name() == "DefaultAutoTypeSequence") {
|
||||
group->setDefaultAutoTypeSequence(readString());
|
||||
}
|
||||
else if (m_xml.name() == "EnableAutoType") {
|
||||
} else if (m_xml.name() == "EnableAutoType") {
|
||||
QString str = readString();
|
||||
|
||||
if (str.compare("null", Qt::CaseInsensitive) == 0) {
|
||||
group->setAutoTypeEnabled(Group::Inherit);
|
||||
}
|
||||
else if (str.compare("true", Qt::CaseInsensitive) == 0) {
|
||||
} else if (str.compare("true", Qt::CaseInsensitive) == 0) {
|
||||
group->setAutoTypeEnabled(Group::Enable);
|
||||
}
|
||||
else if (str.compare("false", Qt::CaseInsensitive) == 0) {
|
||||
} else if (str.compare("false", Qt::CaseInsensitive) == 0) {
|
||||
group->setAutoTypeEnabled(Group::Disable);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
raiseError("Invalid EnableAutoType value");
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "EnableSearching") {
|
||||
} else if (m_xml.name() == "EnableSearching") {
|
||||
QString str = readString();
|
||||
|
||||
if (str.compare("null", Qt::CaseInsensitive) == 0) {
|
||||
group->setSearchingEnabled(Group::Inherit);
|
||||
}
|
||||
else if (str.compare("true", Qt::CaseInsensitive) == 0) {
|
||||
} else if (str.compare("true", Qt::CaseInsensitive) == 0) {
|
||||
group->setSearchingEnabled(Group::Enable);
|
||||
}
|
||||
else if (str.compare("false", Qt::CaseInsensitive) == 0) {
|
||||
} else if (str.compare("false", Qt::CaseInsensitive) == 0) {
|
||||
group->setSearchingEnabled(Group::Disable);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
raiseError("Invalid EnableSearching value");
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "LastTopVisibleEntry") {
|
||||
} else if (m_xml.name() == "LastTopVisibleEntry") {
|
||||
group->setLastTopVisibleEntry(getEntry(readUuid()));
|
||||
}
|
||||
else if (m_xml.name() == "Group") {
|
||||
} else if (m_xml.name() == "Group") {
|
||||
Group* newGroup = parseGroup();
|
||||
if (newGroup) {
|
||||
children.append(newGroup);
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "Entry") {
|
||||
} else if (m_xml.name() == "Entry") {
|
||||
Entry* newEntry = parseEntry(false);
|
||||
if (newEntry) {
|
||||
entries.append(newEntry);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -607,8 +535,7 @@ Group* Kdbx3XmlReader::parseGroup()
|
||||
group->copyDataFrom(tmpGroup);
|
||||
group->setUpdateTimeinfo(false);
|
||||
delete tmpGroup;
|
||||
}
|
||||
else if (!hasError()) {
|
||||
} else if (!hasError()) {
|
||||
raiseError("No group uuid found");
|
||||
}
|
||||
|
||||
@ -630,8 +557,7 @@ void Kdbx3XmlReader::parseDeletedObjects()
|
||||
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||
if (m_xml.name() == "DeletedObject") {
|
||||
parseDeletedObject();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -650,23 +576,19 @@ void Kdbx3XmlReader::parseDeletedObject()
|
||||
if (m_strictMode) {
|
||||
raiseError("Null DeleteObject uuid");
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
delObj.uuid = uuid;
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "DeletionTime") {
|
||||
} else if (m_xml.name() == "DeletionTime") {
|
||||
delObj.deletionTime = readDateTime();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
if (!delObj.uuid.isNull() && !delObj.deletionTime.isNull()) {
|
||||
m_db->addDeletedObject(delObj);
|
||||
}
|
||||
else if (m_strictMode) {
|
||||
} else if (m_strictMode) {
|
||||
raiseError("Missing DeletedObject uuid or time");
|
||||
}
|
||||
}
|
||||
@ -686,69 +608,53 @@ Entry* Kdbx3XmlReader::parseEntry(bool history)
|
||||
if (uuid.isNull()) {
|
||||
if (m_strictMode) {
|
||||
raiseError("Null entry uuid");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
entry->setUuid(Uuid::random());
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
entry->setUuid(uuid);
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "IconID") {
|
||||
} else if (m_xml.name() == "IconID") {
|
||||
int iconId = readNumber();
|
||||
if (iconId < 0) {
|
||||
if (m_strictMode) {
|
||||
raiseError("Invalid entry icon number");
|
||||
}
|
||||
iconId = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
entry->setIcon(iconId);
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "CustomIconUUID") {
|
||||
} else if (m_xml.name() == "CustomIconUUID") {
|
||||
Uuid uuid = readUuid();
|
||||
if (!uuid.isNull()) {
|
||||
entry->setIcon(uuid);
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "ForegroundColor") {
|
||||
} else if (m_xml.name() == "ForegroundColor") {
|
||||
entry->setForegroundColor(readColor());
|
||||
}
|
||||
else if (m_xml.name() == "BackgroundColor") {
|
||||
} else if (m_xml.name() == "BackgroundColor") {
|
||||
entry->setBackgroundColor(readColor());
|
||||
}
|
||||
else if (m_xml.name() == "OverrideURL") {
|
||||
} else if (m_xml.name() == "OverrideURL") {
|
||||
entry->setOverrideUrl(readString());
|
||||
}
|
||||
else if (m_xml.name() == "Tags") {
|
||||
} else if (m_xml.name() == "Tags") {
|
||||
entry->setTags(readString());
|
||||
}
|
||||
else if (m_xml.name() == "Times") {
|
||||
} else if (m_xml.name() == "Times") {
|
||||
entry->setTimeInfo(parseTimes());
|
||||
}
|
||||
else if (m_xml.name() == "String") {
|
||||
} else if (m_xml.name() == "String") {
|
||||
parseEntryString(entry);
|
||||
}
|
||||
else if (m_xml.name() == "Binary") {
|
||||
} else if (m_xml.name() == "Binary") {
|
||||
QPair<QString, QString> ref = parseEntryBinary(entry);
|
||||
if (!ref.first.isNull() && !ref.second.isNull()) {
|
||||
binaryRefs.append(ref);
|
||||
}
|
||||
}
|
||||
else if (m_xml.name() == "AutoType") {
|
||||
} else if (m_xml.name() == "AutoType") {
|
||||
parseAutoType(entry);
|
||||
}
|
||||
else if (m_xml.name() == "History") {
|
||||
} else if (m_xml.name() == "History") {
|
||||
if (history) {
|
||||
raiseError("History element in history entry");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
historyItems = parseEntryHistory();
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -760,8 +666,7 @@ Entry* Kdbx3XmlReader::parseEntry(bool history)
|
||||
if (!entry->uuid().isNull()) {
|
||||
if (history) {
|
||||
entry->setUpdateTimeinfo(false);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Entry* tmpEntry = entry;
|
||||
|
||||
entry = getEntry(tmpEntry->uuid());
|
||||
@ -770,8 +675,7 @@ Entry* Kdbx3XmlReader::parseEntry(bool history)
|
||||
|
||||
delete tmpEntry;
|
||||
}
|
||||
}
|
||||
else if (!hasError()) {
|
||||
} else if (!hasError()) {
|
||||
raiseError("No entry uuid found");
|
||||
}
|
||||
|
||||
@ -807,8 +711,7 @@ void Kdbx3XmlReader::parseEntryString(Entry* entry)
|
||||
if (m_xml.name() == "Key") {
|
||||
key = readString();
|
||||
keySet = true;
|
||||
}
|
||||
else if (m_xml.name() == "Value") {
|
||||
} else if (m_xml.name() == "Value") {
|
||||
QXmlStreamAttributes attr = m_xml.attributes();
|
||||
value = readString();
|
||||
|
||||
@ -823,20 +726,17 @@ void Kdbx3XmlReader::parseEntryString(Entry* entry)
|
||||
if (!ok) {
|
||||
value.clear();
|
||||
raiseError(m_randomStream->errorString());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
value = QString::fromUtf8(plaintext);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
raiseError("Unable to decrypt entry string");
|
||||
}
|
||||
}
|
||||
|
||||
protect = isProtected || protectInMemory;
|
||||
valueSet = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -845,12 +745,10 @@ void Kdbx3XmlReader::parseEntryString(Entry* entry)
|
||||
// the default attributes are always there so additionally check if it's empty
|
||||
if (entry->attributes()->hasKey(key) && !entry->attributes()->value(key).isEmpty()) {
|
||||
raiseError("Duplicate custom attribute found");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
entry->attributes()->set(key, value, protect);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
raiseError("Entry string key or value missing");
|
||||
}
|
||||
}
|
||||
@ -870,19 +768,17 @@ QPair<QString, QString> Kdbx3XmlReader::parseEntryBinary(Entry* entry)
|
||||
if (m_xml.name() == "Key") {
|
||||
key = readString();
|
||||
keySet = true;
|
||||
}
|
||||
else if (m_xml.name() == "Value") {
|
||||
} else if (m_xml.name() == "Value") {
|
||||
QXmlStreamAttributes attr = m_xml.attributes();
|
||||
|
||||
if (attr.hasAttribute("Ref")) {
|
||||
poolRef = qMakePair(attr.value("Ref").toString(), key);
|
||||
m_xml.skipCurrentElement();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// format compatibility
|
||||
value = readBinary();
|
||||
bool isProtected = attr.hasAttribute("Protected")
|
||||
&& (attr.value("Protected") == "True");
|
||||
&& (attr.value("Protected") == "True");
|
||||
|
||||
if (isProtected && !value.isEmpty()) {
|
||||
if (!m_randomStream->processInPlace(value)) {
|
||||
@ -892,8 +788,7 @@ QPair<QString, QString> Kdbx3XmlReader::parseEntryBinary(Entry* entry)
|
||||
}
|
||||
|
||||
valueSet = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -901,12 +796,10 @@ QPair<QString, QString> Kdbx3XmlReader::parseEntryBinary(Entry* entry)
|
||||
if (keySet && valueSet) {
|
||||
if (entry->attachments()->hasKey(key)) {
|
||||
raiseError("Duplicate attachment found");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
entry->attachments()->set(key, value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
raiseError("Entry binary key or value missing");
|
||||
}
|
||||
|
||||
@ -920,17 +813,13 @@ void Kdbx3XmlReader::parseAutoType(Entry* entry)
|
||||
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||
if (m_xml.name() == "Enabled") {
|
||||
entry->setAutoTypeEnabled(readBool());
|
||||
}
|
||||
else if (m_xml.name() == "DataTransferObfuscation") {
|
||||
} else if (m_xml.name() == "DataTransferObfuscation") {
|
||||
entry->setAutoTypeObfuscation(readNumber());
|
||||
}
|
||||
else if (m_xml.name() == "DefaultSequence") {
|
||||
} else if (m_xml.name() == "DefaultSequence") {
|
||||
entry->setDefaultAutoTypeSequence(readString());
|
||||
}
|
||||
else if (m_xml.name() == "Association") {
|
||||
} else if (m_xml.name() == "Association") {
|
||||
parseAutoTypeAssoc(entry);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -948,20 +837,17 @@ void Kdbx3XmlReader::parseAutoTypeAssoc(Entry* entry)
|
||||
if (m_xml.name() == "Window") {
|
||||
assoc.window = readString();
|
||||
windowSet = true;
|
||||
}
|
||||
else if (m_xml.name() == "KeystrokeSequence") {
|
||||
} else if (m_xml.name() == "KeystrokeSequence") {
|
||||
assoc.sequence = readString();
|
||||
sequenceSet = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
if (windowSet && sequenceSet) {
|
||||
entry->autoTypeAssociations()->add(assoc);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
raiseError("Auto-type association window or sequence missing");
|
||||
}
|
||||
}
|
||||
@ -975,8 +861,7 @@ QList<Entry*> Kdbx3XmlReader::parseEntryHistory()
|
||||
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||
if (m_xml.name() == "Entry") {
|
||||
historyItems.append(parseEntry(true));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -992,26 +877,19 @@ TimeInfo Kdbx3XmlReader::parseTimes()
|
||||
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||
if (m_xml.name() == "LastModificationTime") {
|
||||
timeInfo.setLastModificationTime(readDateTime());
|
||||
}
|
||||
else if (m_xml.name() == "CreationTime") {
|
||||
} else if (m_xml.name() == "CreationTime") {
|
||||
timeInfo.setCreationTime(readDateTime());
|
||||
}
|
||||
else if (m_xml.name() == "LastAccessTime") {
|
||||
} else if (m_xml.name() == "LastAccessTime") {
|
||||
timeInfo.setLastAccessTime(readDateTime());
|
||||
}
|
||||
else if (m_xml.name() == "ExpiryTime") {
|
||||
} else if (m_xml.name() == "ExpiryTime") {
|
||||
timeInfo.setExpiryTime(readDateTime());
|
||||
}
|
||||
else if (m_xml.name() == "Expires") {
|
||||
} else if (m_xml.name() == "Expires") {
|
||||
timeInfo.setExpires(readBool());
|
||||
}
|
||||
else if (m_xml.name() == "UsageCount") {
|
||||
} else if (m_xml.name() == "UsageCount") {
|
||||
timeInfo.setUsageCount(readNumber());
|
||||
}
|
||||
else if (m_xml.name() == "LocationChanged") {
|
||||
} else if (m_xml.name() == "LocationChanged") {
|
||||
timeInfo.setLocationChanged(readDateTime());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -1030,14 +908,11 @@ bool Kdbx3XmlReader::readBool()
|
||||
|
||||
if (str.compare("True", Qt::CaseInsensitive) == 0) {
|
||||
return true;
|
||||
}
|
||||
else if (str.compare("False", Qt::CaseInsensitive) == 0) {
|
||||
} else if (str.compare("False", Qt::CaseInsensitive) == 0) {
|
||||
return false;
|
||||
}
|
||||
else if (str.length() == 0) {
|
||||
} else if (str.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
raiseError("Invalid bool value");
|
||||
return false;
|
||||
}
|
||||
@ -1051,8 +926,7 @@ QDateTime Kdbx3XmlReader::readDateTime()
|
||||
if (!dt.isValid()) {
|
||||
if (m_strictMode) {
|
||||
raiseError("Invalid date time value");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
dt = QDateTime::currentDateTimeUtc();
|
||||
}
|
||||
}
|
||||
@ -1077,7 +951,7 @@ QColor Kdbx3XmlReader::readColor()
|
||||
|
||||
QColor color;
|
||||
for (int i = 0; i <= 2; i++) {
|
||||
QString rgbPartStr = colorStr.mid(1 + 2*i, 2);
|
||||
QString rgbPartStr = colorStr.mid(1 + 2 * i, 2);
|
||||
bool ok;
|
||||
int rgbPart = rgbPartStr.toInt(&ok, 16);
|
||||
if (!ok || rgbPart > 255) {
|
||||
@ -1089,11 +963,9 @@ QColor Kdbx3XmlReader::readColor()
|
||||
|
||||
if (i == 0) {
|
||||
color.setRed(rgbPart);
|
||||
}
|
||||
else if (i == 1) {
|
||||
} else if (i == 1) {
|
||||
color.setGreen(rgbPart);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
color.setBlue(rgbPart);
|
||||
}
|
||||
}
|
||||
@ -1116,14 +988,12 @@ Uuid Kdbx3XmlReader::readUuid()
|
||||
QByteArray uuidBin = readBinary();
|
||||
if (uuidBin.isEmpty()) {
|
||||
return Uuid();
|
||||
}
|
||||
else if (uuidBin.length() != Uuid::Length) {
|
||||
} else if (uuidBin.length() != Uuid::Length) {
|
||||
if (m_strictMode) {
|
||||
raiseError("Invalid uuid value");
|
||||
}
|
||||
return Uuid();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return Uuid(uuidBin);
|
||||
}
|
||||
}
|
||||
@ -1159,8 +1029,7 @@ Group* Kdbx3XmlReader::getGroup(const Uuid& uuid)
|
||||
|
||||
if (m_groups.contains(uuid)) {
|
||||
return m_groups.value(uuid);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Group* group = new Group();
|
||||
group->setUpdateTimeinfo(false);
|
||||
group->setUuid(uuid);
|
||||
@ -1178,8 +1047,7 @@ Entry* Kdbx3XmlReader::getEntry(const Uuid& uuid)
|
||||
|
||||
if (m_entries.contains(uuid)) {
|
||||
return m_entries.value(uuid);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Entry* entry = new Entry();
|
||||
entry->setUpdateTimeinfo(false);
|
||||
entry->setUuid(uuid);
|
||||
|
@ -36,7 +36,7 @@ class Metadata;
|
||||
|
||||
class Kdbx3XmlReader
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx3XmlReader)
|
||||
Q_DECLARE_TR_FUNCTIONS(Kdbx3XmlReader)
|
||||
|
||||
public:
|
||||
Kdbx3XmlReader();
|
||||
|
@ -36,7 +36,7 @@ Kdbx3XmlWriter::Kdbx3XmlWriter()
|
||||
}
|
||||
|
||||
void Kdbx3XmlWriter::writeDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream,
|
||||
const QByteArray& headerHash)
|
||||
const QByteArray& headerHash)
|
||||
{
|
||||
m_db = db;
|
||||
m_meta = db->metadata();
|
||||
@ -66,7 +66,7 @@ void Kdbx3XmlWriter::writeDatabase(QIODevice* device, Database* db, KeePass2Rand
|
||||
void Kdbx3XmlWriter::writeDatabase(const QString& filename, Database* db)
|
||||
{
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::WriteOnly|QIODevice::Truncate);
|
||||
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||
writeDatabase(&file, db);
|
||||
}
|
||||
|
||||
@ -202,8 +202,7 @@ void Kdbx3XmlWriter::writeBinaries()
|
||||
|
||||
buffer.seek(0);
|
||||
data = buffer.readAll();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
data = i.key();
|
||||
}
|
||||
|
||||
@ -346,12 +345,12 @@ void Kdbx3XmlWriter::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);
|
||||
|
||||
@ -367,13 +366,11 @@ void Kdbx3XmlWriter::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);
|
||||
}
|
||||
|
||||
@ -449,8 +446,7 @@ void Kdbx3XmlWriter::writeString(const QString& qualifiedName, const QString& st
|
||||
{
|
||||
if (string.isEmpty()) {
|
||||
m_xml.writeEmptyElement(qualifiedName);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
m_xml.writeTextElement(qualifiedName, stripInvalidXml10Chars(string));
|
||||
}
|
||||
}
|
||||
@ -464,8 +460,7 @@ void Kdbx3XmlWriter::writeBool(const QString& qualifiedName, bool b)
|
||||
{
|
||||
if (b) {
|
||||
writeString(qualifiedName, "True");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
writeString(qualifiedName, "False");
|
||||
}
|
||||
}
|
||||
@ -494,8 +489,7 @@ void Kdbx3XmlWriter::writeUuid(const QString& qualifiedName, const Group* group)
|
||||
{
|
||||
if (group) {
|
||||
writeUuid(qualifiedName, group->uuid());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
writeUuid(qualifiedName, Uuid());
|
||||
}
|
||||
}
|
||||
@ -504,8 +498,7 @@ void Kdbx3XmlWriter::writeUuid(const QString& qualifiedName, const Entry* entry)
|
||||
{
|
||||
if (entry) {
|
||||
writeUuid(qualifiedName, entry->uuid());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
writeUuid(qualifiedName, Uuid());
|
||||
}
|
||||
}
|
||||
@ -520,9 +513,9 @@ void Kdbx3XmlWriter::writeColor(const QString& qualifiedName, const QColor& colo
|
||||
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);
|
||||
@ -534,11 +527,9 @@ void Kdbx3XmlWriter::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";
|
||||
}
|
||||
|
||||
@ -564,13 +555,12 @@ QString Kdbx3XmlWriter::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);
|
||||
|
@ -48,24 +48,24 @@ Kdf* KeePass2::uuidToKdf(const Uuid& uuid) {
|
||||
Uuid KeePass2::kdfToUuid(const Kdf& kdf)
|
||||
{
|
||||
switch (kdf.type()) {
|
||||
case Kdf::Type::AES:
|
||||
return KDF_AES;
|
||||
default:
|
||||
return Uuid();
|
||||
case Kdf::Type::AES:
|
||||
return KDF_AES;
|
||||
default:
|
||||
return Uuid();
|
||||
}
|
||||
}
|
||||
|
||||
KeePass2::ProtectedStreamAlgo KeePass2::idToProtectedStreamAlgo(quint32 id)
|
||||
{
|
||||
switch (id) {
|
||||
case static_cast<quint32>(KeePass2::ArcFourVariant):
|
||||
return KeePass2::ArcFourVariant;
|
||||
case static_cast<quint32>(KeePass2::Salsa20):
|
||||
return KeePass2::Salsa20;
|
||||
case static_cast<quint32>(KeePass2::ChaCha20):
|
||||
return KeePass2::ChaCha20;
|
||||
default:
|
||||
return KeePass2::InvalidProtectedStreamAlgo;
|
||||
case static_cast<quint32>(KeePass2::ArcFourVariant):
|
||||
return KeePass2::ArcFourVariant;
|
||||
case static_cast<quint32>(KeePass2::Salsa20):
|
||||
return KeePass2::Salsa20;
|
||||
case static_cast<quint32>(KeePass2::ChaCha20):
|
||||
return KeePass2::ChaCha20;
|
||||
default:
|
||||
return KeePass2::InvalidProtectedStreamAlgo;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,16 +29,16 @@ KeePass2RandomStream::KeePass2RandomStream(KeePass2::ProtectedStreamAlgo algo)
|
||||
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);
|
||||
case SymmetricCipher::ChaCha20: {
|
||||
QByteArray keyIv = CryptoHash::hash(key, CryptoHash::Sha512);
|
||||
return m_cipher.init(keyIv.left(32), keyIv.mid(32, 12));
|
||||
}
|
||||
default:
|
||||
qWarning("Invalid stream algorithm (%d)", m_cipher.algorithm());
|
||||
break;
|
||||
case SymmetricCipher::Salsa20:
|
||||
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));
|
||||
}
|
||||
default:
|
||||
qWarning("Invalid stream algorithm (%d)", m_cipher.algorithm());
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 KeePassXC Team
|
||||
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* 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
|
||||
@ -24,7 +24,7 @@ const QSysInfo::Endian HmacBlockStream::ByteOrder = QSysInfo::LittleEndian;
|
||||
|
||||
HmacBlockStream::HmacBlockStream(QIODevice* baseDevice, QByteArray key)
|
||||
: LayeredStream(baseDevice)
|
||||
, m_blockSize(1024*1024)
|
||||
, m_blockSize(1024 * 1024)
|
||||
, m_key(key)
|
||||
{
|
||||
init();
|
||||
@ -94,8 +94,7 @@ qint64 HmacBlockStream::readData(char* data, qint64 maxSize)
|
||||
{
|
||||
if (m_error) {
|
||||
return -1;
|
||||
}
|
||||
else if (m_eof) {
|
||||
} else if (m_eof) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -107,8 +106,7 @@ qint64 HmacBlockStream::readData(char* data, qint64 maxSize)
|
||||
if (!readHashedBlock()) {
|
||||
if (m_error) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return maxSize - bytesRemaining;
|
||||
}
|
||||
}
|
||||
@ -204,8 +202,7 @@ qint64 HmacBlockStream::writeData(const char* data, qint64 maxSize)
|
||||
if (!writeHashedBlock()) {
|
||||
if (m_error) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return maxSize - bytesRemaining;
|
||||
}
|
||||
}
|
||||
@ -249,11 +246,13 @@ bool HmacBlockStream::writeHashedBlock()
|
||||
return true;
|
||||
}
|
||||
|
||||
QByteArray HmacBlockStream::getCurrentHmacKey() const {
|
||||
QByteArray HmacBlockStream::getCurrentHmacKey() const
|
||||
{
|
||||
return getHmacKey(m_blockIndex, m_key);
|
||||
}
|
||||
|
||||
QByteArray HmacBlockStream::getHmacKey(quint64 blockIndex, QByteArray key) {
|
||||
QByteArray HmacBlockStream::getHmacKey(quint64 blockIndex, QByteArray key)
|
||||
{
|
||||
Q_ASSERT(key.size() == 64);
|
||||
QByteArray indexBytes = Endian::sizedIntToBytes<quint64>(blockIndex, ByteOrder);
|
||||
CryptoHash hasher(CryptoHash::Sha512);
|
||||
@ -262,6 +261,7 @@ QByteArray HmacBlockStream::getHmacKey(quint64 blockIndex, QByteArray key) {
|
||||
return hasher.result();
|
||||
}
|
||||
|
||||
bool HmacBlockStream::atEnd() const {
|
||||
bool HmacBlockStream::atEnd() const
|
||||
{
|
||||
return m_eof;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 KeePassXC Team
|
||||
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* 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
|
||||
@ -22,9 +22,9 @@
|
||||
|
||||
#include "streams/LayeredStream.h"
|
||||
|
||||
class HmacBlockStream : public LayeredStream
|
||||
class HmacBlockStream: public LayeredStream
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit HmacBlockStream(QIODevice* baseDevice, QByteArray key);
|
||||
|
Loading…
Reference in New Issue
Block a user