mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Add keyfile option to keepassxc cli import cmd (#5402)
Fixes #5311 Added the keyFile logic from the create command to the import command and moved the loadFileKey() function to the Utils class since it is now used in both create & import classes.
This commit is contained in:
parent
bf2cad28af
commit
fd3cc7e8c3
@ -83,7 +83,12 @@ It provides the ability to query and modify the entries of a KeePass database, d
|
|||||||
Displays a list of available commands, or detailed information about the specified command.
|
Displays a list of available commands, or detailed information about the specified command.
|
||||||
|
|
||||||
*import* [_options_] <__xml__> <__database__>::
|
*import* [_options_] <__xml__> <__database__>::
|
||||||
Imports the contents of an XML database to the target database.
|
Imports the contents of an XML exported database to a new created database
|
||||||
|
with a password and/or key file.
|
||||||
|
The key file will be created if the file that is referred to does not exist.
|
||||||
|
If both the key file and password are empty, no database will be created.
|
||||||
|
The new database will be in kdbx 4 format.
|
||||||
|
|
||||||
|
|
||||||
*locate* [_options_] <__database__> <__term__>::
|
*locate* [_options_] <__database__> <__term__>::
|
||||||
Locates all the entries that match a specific search term in a database.
|
Locates all the entries that match a specific search term in a database.
|
||||||
@ -219,7 +224,7 @@ The same password generation options as documented for the generate command can
|
|||||||
If a unique matching entry is found it will be copied to the clipboard.
|
If a unique matching entry is found it will be copied to the clipboard.
|
||||||
If multiple entries are found they will be listed to refine the search. (no clip performed)
|
If multiple entries are found they will be listed to refine the search. (no clip performed)
|
||||||
|
|
||||||
=== Create options
|
=== Create and Import options
|
||||||
*-k*, *--set-key-file* <__path__>::
|
*-k*, *--set-key-file* <__path__>::
|
||||||
Set the key file for the database.
|
Set the key file for the database.
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "core/Database.h"
|
#include "core/Database.h"
|
||||||
|
|
||||||
#include "keys/CompositeKey.h"
|
#include "keys/CompositeKey.h"
|
||||||
|
#include "keys/FileKey.h"
|
||||||
#include "keys/Key.h"
|
#include "keys/Key.h"
|
||||||
|
|
||||||
const QCommandLineOption Create::DecryptionTimeOption =
|
const QCommandLineOption Create::DecryptionTimeOption =
|
||||||
@ -57,6 +58,84 @@ Create::Create()
|
|||||||
options.append(Create::DecryptionTimeOption);
|
options.append(Create::DecryptionTimeOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSharedPointer<Database> Create::initializeDatabaseFromOptions(const QSharedPointer<QCommandLineParser>& parser)
|
||||||
|
{
|
||||||
|
if (parser.isNull()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& out = parser->isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT;
|
||||||
|
auto& err = Utils::STDERR;
|
||||||
|
|
||||||
|
// Validate the decryption time before asking for a password.
|
||||||
|
QString decryptionTimeValue = parser->value(Create::DecryptionTimeOption);
|
||||||
|
int decryptionTime = 0;
|
||||||
|
if (decryptionTimeValue.length() != 0) {
|
||||||
|
decryptionTime = decryptionTimeValue.toInt();
|
||||||
|
if (decryptionTime <= 0) {
|
||||||
|
err << QObject::tr("Invalid decryption time %1.").arg(decryptionTimeValue) << endl;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (decryptionTime < Kdf::MIN_ENCRYPTION_TIME || decryptionTime > Kdf::MAX_ENCRYPTION_TIME) {
|
||||||
|
err << QObject::tr("Target decryption time must be between %1 and %2.")
|
||||||
|
.arg(QString::number(Kdf::MIN_ENCRYPTION_TIME), QString::number(Kdf::MAX_ENCRYPTION_TIME))
|
||||||
|
<< endl;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto key = QSharedPointer<CompositeKey>::create();
|
||||||
|
|
||||||
|
if (parser->isSet(Create::SetPasswordOption)) {
|
||||||
|
auto passwordKey = Utils::getConfirmedPassword();
|
||||||
|
if (passwordKey.isNull()) {
|
||||||
|
err << QObject::tr("Failed to set database password.") << endl;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
key->addKey(passwordKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser->isSet(Create::SetKeyFileOption)) {
|
||||||
|
QSharedPointer<FileKey> fileKey;
|
||||||
|
|
||||||
|
if (!Utils::loadFileKey(parser->value(Create::SetKeyFileOption), fileKey)) {
|
||||||
|
err << QObject::tr("Loading the key file failed") << endl;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileKey.isNull()) {
|
||||||
|
key->addKey(fileKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key->isEmpty()) {
|
||||||
|
err << QObject::tr("No key is set. Aborting database creation.") << endl;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto db = QSharedPointer<Database>::create();
|
||||||
|
db->setKey(key);
|
||||||
|
|
||||||
|
if (decryptionTime != 0) {
|
||||||
|
auto kdf = db->kdf();
|
||||||
|
Q_ASSERT(kdf);
|
||||||
|
|
||||||
|
out << QObject::tr("Benchmarking key derivation function for %1ms delay.").arg(decryptionTimeValue) << endl;
|
||||||
|
int rounds = kdf->benchmark(decryptionTime);
|
||||||
|
out << QObject::tr("Setting %1 rounds for key derivation function.").arg(QString::number(rounds)) << endl;
|
||||||
|
kdf->setRounds(rounds);
|
||||||
|
|
||||||
|
bool ok = db->changeKdf(kdf);
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
err << QObject::tr("error while setting database key derivation settings.") << endl;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return db;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a database file using the command line. A key file and/or
|
* Create a database file using the command line. A key file and/or
|
||||||
* password can be specified to encrypt the password. If none is
|
* password can be specified to encrypt the password. If none is
|
||||||
@ -88,71 +167,10 @@ int Create::execute(const QStringList& arguments)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the decryption time before asking for a password.
|
QSharedPointer<Database> db = Create::initializeDatabaseFromOptions(parser);
|
||||||
QString decryptionTimeValue = parser->value(Create::DecryptionTimeOption);
|
if (!db) {
|
||||||
int decryptionTime = 0;
|
|
||||||
if (decryptionTimeValue.length() != 0) {
|
|
||||||
decryptionTime = decryptionTimeValue.toInt();
|
|
||||||
if (decryptionTime <= 0) {
|
|
||||||
err << QObject::tr("Invalid decryption time %1.").arg(decryptionTimeValue) << endl;
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
if (decryptionTime < Kdf::MIN_ENCRYPTION_TIME || decryptionTime > Kdf::MAX_ENCRYPTION_TIME) {
|
|
||||||
err << QObject::tr("Target decryption time must be between %1 and %2.")
|
|
||||||
.arg(QString::number(Kdf::MIN_ENCRYPTION_TIME), QString::number(Kdf::MAX_ENCRYPTION_TIME))
|
|
||||||
<< endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto key = QSharedPointer<CompositeKey>::create();
|
|
||||||
|
|
||||||
if (parser->isSet(Create::SetPasswordOption)) {
|
|
||||||
auto passwordKey = Utils::getConfirmedPassword();
|
|
||||||
if (passwordKey.isNull()) {
|
|
||||||
err << QObject::tr("Failed to set database password.") << endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
key->addKey(passwordKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser->isSet(Create::SetKeyFileOption)) {
|
|
||||||
QSharedPointer<FileKey> fileKey;
|
|
||||||
|
|
||||||
if (!loadFileKey(parser->value(Create::SetKeyFileOption), fileKey)) {
|
|
||||||
err << QObject::tr("Loading the key file failed") << endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fileKey.isNull()) {
|
|
||||||
key->addKey(fileKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key->isEmpty()) {
|
|
||||||
err << QObject::tr("No key is set. Aborting database creation.") << endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<Database> db(new Database);
|
|
||||||
db->setKey(key);
|
|
||||||
|
|
||||||
if (decryptionTime != 0) {
|
|
||||||
auto kdf = db->kdf();
|
|
||||||
Q_ASSERT(kdf);
|
|
||||||
|
|
||||||
out << QObject::tr("Benchmarking key derivation function for %1ms delay.").arg(decryptionTimeValue) << endl;
|
|
||||||
int rounds = kdf->benchmark(decryptionTime);
|
|
||||||
out << QObject::tr("Setting %1 rounds for key derivation function.").arg(QString::number(rounds)) << endl;
|
|
||||||
kdf->setRounds(rounds);
|
|
||||||
|
|
||||||
bool ok = db->changeKdf(kdf);
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
err << QObject::tr("error while setting database key derivation settings.") << endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
if (!db->saveAs(databaseFilename, &errorMessage, true, false)) {
|
if (!db->saveAs(databaseFilename, &errorMessage, true, false)) {
|
||||||
@ -161,40 +179,5 @@ int Create::execute(const QStringList& arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
out << QObject::tr("Successfully created new database.") << endl;
|
out << QObject::tr("Successfully created new database.") << endl;
|
||||||
currentDatabase = db;
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Load a key file from disk. When the path specified does not exist a
|
|
||||||
* new file will be generated. No folders will be generated so the parent
|
|
||||||
* folder of the specified file nees to exist
|
|
||||||
*
|
|
||||||
* If the key file cannot be loaded or created the function will fail.
|
|
||||||
*
|
|
||||||
* @param path Path to the key file to be loaded
|
|
||||||
* @param fileKey Resulting fileKey
|
|
||||||
* @return true if the key file was loaded succesfully
|
|
||||||
*/
|
|
||||||
bool Create::loadFileKey(const QString& path, QSharedPointer<FileKey>& fileKey)
|
|
||||||
{
|
|
||||||
auto& err = Utils::STDERR;
|
|
||||||
QString error;
|
|
||||||
fileKey = QSharedPointer<FileKey>(new FileKey());
|
|
||||||
|
|
||||||
if (!QFileInfo::exists(path)) {
|
|
||||||
fileKey->create(path, &error);
|
|
||||||
|
|
||||||
if (!error.isEmpty()) {
|
|
||||||
err << QObject::tr("Creating KeyFile %1 failed: %2").arg(path, error) << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fileKey->load(path, &error)) {
|
|
||||||
err << QObject::tr("Loading KeyFile %1 failed: %2").arg(path, error) << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
@ -20,20 +20,17 @@
|
|||||||
|
|
||||||
#include "Command.h"
|
#include "Command.h"
|
||||||
|
|
||||||
#include "keys/FileKey.h"
|
|
||||||
|
|
||||||
class Create : public Command
|
class Create : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Create();
|
Create();
|
||||||
int execute(const QStringList& arguments) override;
|
int execute(const QStringList& arguments) override;
|
||||||
|
|
||||||
|
static QSharedPointer<Database> initializeDatabaseFromOptions(const QSharedPointer<QCommandLineParser>& parser);
|
||||||
|
|
||||||
static const QCommandLineOption SetKeyFileOption;
|
static const QCommandLineOption SetKeyFileOption;
|
||||||
static const QCommandLineOption SetPasswordOption;
|
static const QCommandLineOption SetPasswordOption;
|
||||||
static const QCommandLineOption DecryptionTimeOption;
|
static const QCommandLineOption DecryptionTimeOption;
|
||||||
|
|
||||||
private:
|
|
||||||
bool loadFileKey(const QString& path, QSharedPointer<FileKey>& fileKey);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEEPASSXC_CREATE_H
|
#endif // KEEPASSXC_CREATE_H
|
||||||
|
@ -22,12 +22,14 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
|
||||||
|
#include "Create.h"
|
||||||
#include "Import.h"
|
#include "Import.h"
|
||||||
|
|
||||||
#include "cli/TextStream.h"
|
#include "cli/TextStream.h"
|
||||||
#include "cli/Utils.h"
|
#include "cli/Utils.h"
|
||||||
#include "core/Database.h"
|
#include "core/Database.h"
|
||||||
#include "keys/CompositeKey.h"
|
#include "keys/CompositeKey.h"
|
||||||
|
#include "keys/FileKey.h"
|
||||||
#include "keys/Key.h"
|
#include "keys/Key.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,12 +42,16 @@
|
|||||||
*
|
*
|
||||||
* @return EXIT_SUCCESS on success, or EXIT_FAILURE on failure
|
* @return EXIT_SUCCESS on success, or EXIT_FAILURE on failure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Import::Import()
|
Import::Import()
|
||||||
{
|
{
|
||||||
name = QString("import");
|
name = QString("import");
|
||||||
description = QObject::tr("Import the contents of an XML database.");
|
description = QObject::tr("Import the contents of an XML database.");
|
||||||
positionalArguments.append({QString("xml"), QObject::tr("Path of the XML database export."), QString("")});
|
positionalArguments.append({QString("xml"), QObject::tr("Path of the XML database export."), QString("")});
|
||||||
positionalArguments.append({QString("database"), QObject::tr("Path of the new database."), QString("")});
|
positionalArguments.append({QString("database"), QObject::tr("Path of the new database."), QString("")});
|
||||||
|
options.append(Create::SetKeyFileOption);
|
||||||
|
options.append(Create::SetPasswordOption);
|
||||||
|
options.append(Create::DecryptionTimeOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Import::execute(const QStringList& arguments)
|
int Import::execute(const QStringList& arguments)
|
||||||
@ -67,31 +73,18 @@ int Import::execute(const QStringList& arguments)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto key = QSharedPointer<CompositeKey>::create();
|
QSharedPointer<Database> db = Create::initializeDatabaseFromOptions(parser);
|
||||||
|
if (!db) {
|
||||||
auto passwordKey = Utils::getConfirmedPassword();
|
|
||||||
if (passwordKey.isNull()) {
|
|
||||||
err << QObject::tr("Failed to set database password.") << endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
key->addKey(passwordKey);
|
|
||||||
|
|
||||||
if (key->isEmpty()) {
|
|
||||||
err << QObject::tr("No key is set. Aborting database creation.") << endl;
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
Database db;
|
if (!db->import(xmlExportPath, &errorMessage)) {
|
||||||
db.setKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2));
|
|
||||||
db.setKey(key);
|
|
||||||
|
|
||||||
if (!db.import(xmlExportPath, &errorMessage)) {
|
|
||||||
err << QObject::tr("Unable to import XML database: %1").arg(errorMessage) << endl;
|
err << QObject::tr("Unable to import XML database: %1").arg(errorMessage) << endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!db.saveAs(dbPath, &errorMessage, true, false)) {
|
if (!db->saveAs(dbPath, &errorMessage, true, false)) {
|
||||||
err << QObject::tr("Failed to save the database: %1.").arg(errorMessage) << endl;
|
err << QObject::tr("Failed to save the database: %1.").arg(errorMessage) << endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -371,4 +371,37 @@ namespace Utils
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a key file from disk. When the path specified does not exist a
|
||||||
|
* new file will be generated. No folders will be generated so the parent
|
||||||
|
* folder of the specified file needs to exist
|
||||||
|
*
|
||||||
|
* If the key file cannot be loaded or created the function will fail.
|
||||||
|
*
|
||||||
|
* @param path Path to the key file to be loaded
|
||||||
|
* @param fileKey Resulting fileKey
|
||||||
|
* @return true if the key file was loaded succesfully
|
||||||
|
*/
|
||||||
|
bool loadFileKey(const QString& path, QSharedPointer<FileKey>& fileKey)
|
||||||
|
{
|
||||||
|
auto& err = Utils::STDERR;
|
||||||
|
QString error;
|
||||||
|
fileKey = QSharedPointer<FileKey>(new FileKey());
|
||||||
|
|
||||||
|
if (!QFileInfo::exists(path)) {
|
||||||
|
fileKey->create(path, &error);
|
||||||
|
|
||||||
|
if (!error.isEmpty()) {
|
||||||
|
err << QObject::tr("Creating KeyFile %1 failed: %2").arg(path, error) << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileKey->load(path, &error)) {
|
||||||
|
err << QObject::tr("Loading KeyFile %1 failed: %2").arg(path, error) << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
@ -36,6 +36,7 @@ namespace Utils
|
|||||||
void setDefaultTextStreams();
|
void setDefaultTextStreams();
|
||||||
|
|
||||||
void setStdinEcho(bool enable);
|
void setStdinEcho(bool enable);
|
||||||
|
bool loadFileKey(const QString& path, QSharedPointer<FileKey>& fileKey);
|
||||||
QString getPassword(bool quiet = false);
|
QString getPassword(bool quiet = false);
|
||||||
QSharedPointer<PasswordKey> getConfirmedPassword();
|
QSharedPointer<PasswordKey> getConfirmedPassword();
|
||||||
int clipText(const QString& text);
|
int clipText(const QString& text);
|
||||||
|
@ -1057,7 +1057,7 @@ void TestCli::testImport()
|
|||||||
QString databaseFilename = testDir->path() + "/testImport1.kdbx";
|
QString databaseFilename = testDir->path() + "/testImport1.kdbx";
|
||||||
|
|
||||||
setInput({"a", "a"});
|
setInput({"a", "a"});
|
||||||
execCmd(importCmd, {"import", m_xmlFile->fileName(), databaseFilename});
|
execCmd(importCmd, {"import", m_xmlFile->fileName(), databaseFilename, "-p"});
|
||||||
|
|
||||||
QCOMPARE(m_stderr->readLine(), QByteArray("Enter password to encrypt database (optional): \n"));
|
QCOMPARE(m_stderr->readLine(), QByteArray("Enter password to encrypt database (optional): \n"));
|
||||||
QCOMPARE(m_stderr->readLine(), QByteArray("Repeat password: \n"));
|
QCOMPARE(m_stderr->readLine(), QByteArray("Repeat password: \n"));
|
||||||
@ -1076,12 +1076,67 @@ void TestCli::testImport()
|
|||||||
QString errorMessage = QString("File " + databaseFilename + " already exists.\n");
|
QString errorMessage = QString("File " + databaseFilename + " already exists.\n");
|
||||||
QCOMPARE(m_stderr->readAll(), errorMessage.toUtf8());
|
QCOMPARE(m_stderr->readAll(), errorMessage.toUtf8());
|
||||||
|
|
||||||
|
// Testing import with non-existing keyfile
|
||||||
|
databaseFilename = testDir->path() + "/testImport2.kdbx";
|
||||||
|
QString keyfilePath = testDir->path() + "/keyfile.txt";
|
||||||
|
setInput({"a", "a"});
|
||||||
|
execCmd(importCmd, {"import", "-p", "-k", keyfilePath, m_xmlFile->fileName(), databaseFilename});
|
||||||
|
|
||||||
|
QCOMPARE(m_stderr->readLine(), QByteArray("Enter password to encrypt database (optional): \n"));
|
||||||
|
QCOMPARE(m_stderr->readLine(), QByteArray("Repeat password: \n"));
|
||||||
|
QCOMPARE(m_stdout->readLine(), QByteArray("Successfully imported database.\n"));
|
||||||
|
|
||||||
|
db = readDatabase(databaseFilename, "a", keyfilePath);
|
||||||
|
QVERIFY(db);
|
||||||
|
|
||||||
|
// Testing import with existing keyfile
|
||||||
|
databaseFilename = testDir->path() + "/testImport3.kdbx";
|
||||||
|
setInput({"a", "a"});
|
||||||
|
execCmd(importCmd, {"import", "-p", "-k", keyfilePath, m_xmlFile->fileName(), databaseFilename});
|
||||||
|
|
||||||
|
QCOMPARE(m_stderr->readLine(), QByteArray("Enter password to encrypt database (optional): \n"));
|
||||||
|
QCOMPARE(m_stderr->readLine(), QByteArray("Repeat password: \n"));
|
||||||
|
QCOMPARE(m_stdout->readLine(), QByteArray("Successfully imported database.\n"));
|
||||||
|
|
||||||
|
db = readDatabase(databaseFilename, "a", keyfilePath);
|
||||||
|
QVERIFY(db);
|
||||||
|
|
||||||
|
// Invalid decryption time (format).
|
||||||
|
databaseFilename = testDir->path() + "/testCreate_time.kdbx";
|
||||||
|
execCmd(importCmd, {"import", "-p", "-t", "NAN", m_xmlFile->fileName(), databaseFilename});
|
||||||
|
|
||||||
|
QCOMPARE(m_stdout->readAll(), QByteArray());
|
||||||
|
QCOMPARE(m_stderr->readAll(), QByteArray("Invalid decryption time NAN.\n"));
|
||||||
|
|
||||||
|
// Invalid decryption time (range).
|
||||||
|
execCmd(importCmd, {"import", "-p", "-t", "10", m_xmlFile->fileName(), databaseFilename});
|
||||||
|
|
||||||
|
QCOMPARE(m_stdout->readAll(), QByteArray());
|
||||||
|
QVERIFY(m_stderr->readAll().contains(QByteArray("Target decryption time must be between")));
|
||||||
|
|
||||||
|
int encryptionTime = 500;
|
||||||
|
// Custom encryption time
|
||||||
|
setInput({"a", "a"});
|
||||||
|
int epochBefore = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
execCmd(importCmd,
|
||||||
|
{"import", "-p", "-t", QString::number(encryptionTime), m_xmlFile->fileName(), databaseFilename});
|
||||||
|
// Removing 100ms to make sure we account for changes in computation time.
|
||||||
|
QVERIFY(QDateTime::currentMSecsSinceEpoch() > (epochBefore + encryptionTime - 100));
|
||||||
|
|
||||||
|
QCOMPARE(m_stderr->readLine(), QByteArray("Enter password to encrypt database (optional): \n"));
|
||||||
|
QCOMPARE(m_stderr->readLine(), QByteArray("Repeat password: \n"));
|
||||||
|
QCOMPARE(m_stdout->readLine(), QByteArray("Benchmarking key derivation function for 500ms delay.\n"));
|
||||||
|
QVERIFY(m_stdout->readLine().contains(QByteArray("rounds for key derivation function.\n")));
|
||||||
|
|
||||||
|
db = readDatabase(databaseFilename, "a");
|
||||||
|
QVERIFY(db);
|
||||||
|
|
||||||
// Quiet option
|
// Quiet option
|
||||||
QScopedPointer<QTemporaryDir> testDirQuiet(new QTemporaryDir());
|
QScopedPointer<QTemporaryDir> testDirQuiet(new QTemporaryDir());
|
||||||
QString databaseFilenameQuiet = testDirQuiet->path() + "/testImport2.kdbx";
|
QString databaseFilenameQuiet = testDirQuiet->path() + "/testImport2.kdbx";
|
||||||
|
|
||||||
setInput({"a", "a"});
|
setInput({"a", "a"});
|
||||||
execCmd(importCmd, {"import", "-q", m_xmlFile->fileName(), databaseFilenameQuiet});
|
execCmd(importCmd, {"import", "-p", "-q", m_xmlFile->fileName(), databaseFilenameQuiet});
|
||||||
|
|
||||||
QCOMPARE(m_stderr->readLine(), QByteArray("Enter password to encrypt database (optional): \n"));
|
QCOMPARE(m_stderr->readLine(), QByteArray("Enter password to encrypt database (optional): \n"));
|
||||||
QCOMPARE(m_stderr->readLine(), QByteArray("Repeat password: \n"));
|
QCOMPARE(m_stderr->readLine(), QByteArray("Repeat password: \n"));
|
||||||
|
Loading…
Reference in New Issue
Block a user