mirror of
https://github.com/cuberite/SQLiteCpp.git
synced 2025-08-04 09:46:02 -04:00
moved the key handling to a new function, added a check for an encrypted database
This commit is contained in:
parent
611ab22458
commit
685ff293c5
@ -84,15 +84,13 @@ public:
|
|||||||
* @param[in] aFlags SQLite::OPEN_READONLY/SQLite::OPEN_READWRITE/SQLite::OPEN_CREATE...
|
* @param[in] aFlags SQLite::OPEN_READONLY/SQLite::OPEN_READWRITE/SQLite::OPEN_CREATE...
|
||||||
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout())
|
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout())
|
||||||
* @param[in] apVfs UTF-8 name of custom VFS to use, or nullptr for sqlite3 default
|
* @param[in] apVfs UTF-8 name of custom VFS to use, or nullptr for sqlite3 default
|
||||||
* @param[in] apPass Key to decrypt (end encrypt) the database, or nullptr for unencrypted databases
|
|
||||||
*
|
*
|
||||||
* @throw SQLite::Exception in case of error
|
* @throw SQLite::Exception in case of error
|
||||||
*/
|
*/
|
||||||
Database(const char* apFilename,
|
Database(const char* apFilename,
|
||||||
const int aFlags = SQLite::OPEN_READONLY,
|
const int aFlags = SQLite::OPEN_READONLY,
|
||||||
const int aBusyTimeoutMs = 0,
|
const int aBusyTimeoutMs = 0,
|
||||||
const char* apVfs = NULL,
|
const char* apVfs = NULL);
|
||||||
const char* apPass = NULL);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Open the provided database UTF-8 filename.
|
* @brief Open the provided database UTF-8 filename.
|
||||||
@ -108,15 +106,13 @@ public:
|
|||||||
* @param[in] aFlags SQLite::OPEN_READONLY/SQLite::OPEN_READWRITE/SQLite::OPEN_CREATE...
|
* @param[in] aFlags SQLite::OPEN_READONLY/SQLite::OPEN_READWRITE/SQLite::OPEN_CREATE...
|
||||||
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout())
|
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout())
|
||||||
* @param[in] aVfs UTF-8 name of custom VFS to use, or empty string for sqlite3 default
|
* @param[in] aVfs UTF-8 name of custom VFS to use, or empty string for sqlite3 default
|
||||||
* @param[in] aPass Key to decrypt (end encrypt) the database, or empty string for unencrypted databases
|
|
||||||
*
|
*
|
||||||
* @throw SQLite::Exception in case of error
|
* @throw SQLite::Exception in case of error
|
||||||
*/
|
*/
|
||||||
Database(const std::string& aFilename,
|
Database(const std::string& aFilename,
|
||||||
const int aFlags = SQLite::OPEN_READONLY,
|
const int aFlags = SQLite::OPEN_READONLY,
|
||||||
const int aBusyTimeoutMs = 0,
|
const int aBusyTimeoutMs = 0,
|
||||||
const std::string& aVfs = "",
|
const std::string& aVfs = "");
|
||||||
const std::string& aPass = "");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Close the SQLite database connection.
|
* @brief Close the SQLite database connection.
|
||||||
@ -373,6 +369,46 @@ public:
|
|||||||
*/
|
*/
|
||||||
void loadExtension(const char* apExtensionName, const char* apEntryPointName);
|
void loadExtension(const char* apExtensionName, const char* apEntryPointName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the key for the current sqlite database instance.
|
||||||
|
*
|
||||||
|
* This is the equivalent of the sqlite3_key call and should thus be called
|
||||||
|
* directly after opening the database. If the database is unencrypted,
|
||||||
|
* this methods encrypts it immediately.
|
||||||
|
*
|
||||||
|
* @param[in] key Key to decode/encode the database
|
||||||
|
*
|
||||||
|
* @throw SQLite::Exception in case of error
|
||||||
|
*/
|
||||||
|
void key(const std::string& aKey) const noexcept; // nothrow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset the key for the current sqlite database instance.
|
||||||
|
*
|
||||||
|
* This is the equivalent of the sqlite3_rekey call and should thus be called
|
||||||
|
* after the database has been opened with a valid key. To decrypt a
|
||||||
|
* database, call this method with a NULL pointer.
|
||||||
|
*
|
||||||
|
* @param[in] nkey New key to encode the database
|
||||||
|
*
|
||||||
|
* @throw SQLite::Exception in case of error
|
||||||
|
*/
|
||||||
|
void rekey(const std::string& aNewKey) const noexcept; // nothrow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test if a file contains an unencrypted database.
|
||||||
|
*
|
||||||
|
* This is a simple test that reads the first bytes of a database file and
|
||||||
|
* compares them to the standard header for unencrypted databases. If the
|
||||||
|
* header does not match the standard string, we assume that we have an
|
||||||
|
* encrypted file.
|
||||||
|
*
|
||||||
|
* @param[in] aFilename path/uri to a file
|
||||||
|
*
|
||||||
|
* @return true if the database has the standard header.
|
||||||
|
*/
|
||||||
|
const bool isUnencrypted(const std::string& aFilename) const noexcept; // nothrow
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// @{ Database must be non-copyable
|
/// @{ Database must be non-copyable
|
||||||
Database(const Database&);
|
Database(const Database&);
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <SQLiteCpp/Exception.h>
|
#include <SQLiteCpp/Exception.h>
|
||||||
|
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#ifndef SQLITE_DETERMINISTIC
|
#ifndef SQLITE_DETERMINISTIC
|
||||||
#define SQLITE_DETERMINISTIC 0x800
|
#define SQLITE_DETERMINISTIC 0x800
|
||||||
@ -51,8 +52,7 @@ int getLibVersionNumber() noexcept // nothrow
|
|||||||
Database::Database(const char* apFilename,
|
Database::Database(const char* apFilename,
|
||||||
const int aFlags /* = SQLite::OPEN_READONLY*/,
|
const int aFlags /* = SQLite::OPEN_READONLY*/,
|
||||||
const int aBusyTimeoutMs /* = 0 */,
|
const int aBusyTimeoutMs /* = 0 */,
|
||||||
const char* apVfs /* = NULL*/,
|
const char* apVfs /* = NULL*/) :
|
||||||
const char* apPass /* = NULL*/) :
|
|
||||||
mpSQLite(NULL),
|
mpSQLite(NULL),
|
||||||
mFilename(apFilename)
|
mFilename(apFilename)
|
||||||
{
|
{
|
||||||
@ -63,25 +63,6 @@ Database::Database(const char* apFilename,
|
|||||||
sqlite3_close(mpSQLite); // close is required even in case of error on opening
|
sqlite3_close(mpSQLite); // close is required even in case of error on opening
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
#ifdef SQLITE_HAS_CODEC
|
|
||||||
if (apPass != NULL)
|
|
||||||
{
|
|
||||||
ret = sqlite3_key(mpSQLite, apPass, strlen(apPass));
|
|
||||||
if (SQLITE_OK != ret)
|
|
||||||
{
|
|
||||||
const SQLite::Exception exception(mpSQLite, ret); // must create before closing
|
|
||||||
sqlite3_close(mpSQLite); // close is required even in case of error on opening
|
|
||||||
throw exception;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (apPass != NULL)
|
|
||||||
{
|
|
||||||
const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC or remove the password from the constructor."); // must create before closing
|
|
||||||
sqlite3_close(mpSQLite); // close is required even in case of error on opening
|
|
||||||
throw exception;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (aBusyTimeoutMs > 0)
|
if (aBusyTimeoutMs > 0)
|
||||||
{
|
{
|
||||||
setBusyTimeout(aBusyTimeoutMs);
|
setBusyTimeout(aBusyTimeoutMs);
|
||||||
@ -92,8 +73,7 @@ Database::Database(const char* apFilename,
|
|||||||
Database::Database(const std::string& aFilename,
|
Database::Database(const std::string& aFilename,
|
||||||
const int aFlags /* = SQLite::OPEN_READONLY*/,
|
const int aFlags /* = SQLite::OPEN_READONLY*/,
|
||||||
const int aBusyTimeoutMs /* = 0 */,
|
const int aBusyTimeoutMs /* = 0 */,
|
||||||
const std::string& aVfs /* = "" */,
|
const std::string& aVfs /* = "" */) :
|
||||||
const std::string& aPass /* = "" */) :
|
|
||||||
mpSQLite(NULL),
|
mpSQLite(NULL),
|
||||||
mFilename(aFilename)
|
mFilename(aFilename)
|
||||||
{
|
{
|
||||||
@ -104,25 +84,6 @@ Database::Database(const std::string& aFilename,
|
|||||||
sqlite3_close(mpSQLite); // close is required even in case of error on opening
|
sqlite3_close(mpSQLite); // close is required even in case of error on opening
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
#ifdef SQLITE_HAS_CODEC
|
|
||||||
if (!aPass.empty())
|
|
||||||
{
|
|
||||||
ret = sqlite3_key(mpSQLite, aPass.data(), aPass.size());
|
|
||||||
if (SQLITE_OK != ret)
|
|
||||||
{
|
|
||||||
const SQLite::Exception exception(mpSQLite, ret); // must create before closing
|
|
||||||
sqlite3_close(mpSQLite); // close is required even in case of error on opening
|
|
||||||
throw exception;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (!aPass.empty())
|
|
||||||
{
|
|
||||||
const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC or remove the password from the constructor."); // must create before closing
|
|
||||||
sqlite3_close(mpSQLite); // close is required even in case of error on opening
|
|
||||||
throw exception;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (aBusyTimeoutMs > 0)
|
if (aBusyTimeoutMs > 0)
|
||||||
{
|
{
|
||||||
setBusyTimeout(aBusyTimeoutMs);
|
setBusyTimeout(aBusyTimeoutMs);
|
||||||
@ -267,4 +228,56 @@ void Database::loadExtension(const char* apExtensionName, const char *apEntryPoi
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Set the key for the current sqlite database instance.
|
||||||
|
void Database::key(const std::string& aKey) const noexcept // nothrow
|
||||||
|
{
|
||||||
|
int pass_len = aKey.length();
|
||||||
|
#ifdef SQLITE_HAS_CODEC
|
||||||
|
if (pass_len > 0) {
|
||||||
|
int ret = sqlite3_key(mpSQLite, aKey.c_str(), pass_len);
|
||||||
|
check(ret);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (pass_len > 0) {
|
||||||
|
const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC to use this function.");
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
#endif // SQLITE_HAS_CODEC
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the key for the current sqlite database instance.
|
||||||
|
void Database::rekey(const std::string& aNewKey) const noexcept // nothrow
|
||||||
|
{
|
||||||
|
#ifdef SQLITE_HAS_CODEC
|
||||||
|
int pass_len = aNewKey.length();
|
||||||
|
if (pass_len > 0) {
|
||||||
|
int ret = sqlite3_rekey(mpSQLite, aNewKey.c_str(), pass_len);
|
||||||
|
check(ret);
|
||||||
|
} else {
|
||||||
|
int ret = sqlite3_rekey(mpSQLite, nullptr, 0);
|
||||||
|
check(ret);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC to use this function.");
|
||||||
|
throw exception;
|
||||||
|
#endif // SQLITE_HAS_CODEC
|
||||||
|
}
|
||||||
|
|
||||||
|
//Test if a file contains an unencrypted database.
|
||||||
|
const bool Database::isUnencrypted(const std::string& aFilename) const noexcept // nothrow
|
||||||
|
{
|
||||||
|
bool encrypted_db = false;
|
||||||
|
if (aFilename.length() > 0) {
|
||||||
|
std::ifstream fileBuffer(aFilename, std::ios::in | std::ios::binary);
|
||||||
|
char header[16];
|
||||||
|
if (fileBuffer.is_open()) {
|
||||||
|
fileBuffer.seekg(0, std::ios::beg);
|
||||||
|
fileBuffer.getline(header, 16);
|
||||||
|
fileBuffer.close();
|
||||||
|
}
|
||||||
|
encrypted_db = strncmp(header, "SQLite format 3\000", 16) != 0;
|
||||||
|
}
|
||||||
|
return encrypted_db;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace SQLite
|
} // namespace SQLite
|
||||||
|
Loading…
x
Reference in New Issue
Block a user