Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[RFC] Minimal SQLCipher support #77

Merged
merged 7 commits into from
Feb 16, 2017

Conversation

zauguin
Copy link
Collaborator

@zauguin zauguin commented Feb 1, 2017

Is there any interest in SQLCipher support?
How should this be tested? I don't really want to introduce a SQLCipher dependency just for the tests.

@aminroosta
Copy link
Collaborator

@zauguin I have no experiment with SQLCipher.

Here is @polesapart comment about this issue (from #10)

IIRC sqlcipher just needs an extra call (to set the encryption keyword), everything else is api compatible to sqlite, i.e. you can replace sqlite3.c & sqlite3.h from those from sqlcipher and insert the extra call in the right sequence and nothing else is required for compiling. But for link you need the openssl's libcrypto.


void set_key(const std::string &key) {
if(auto ret = sqlite3_key(_db.get(), key.data(), key.size()))
exceptions::throw_sqlite_error(ret);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a custom exception class for sqlcipher.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no such thing.
SQLCipher isn't very good at error reporting.
For example if the key is wrong, it still returns SQLITE_OK and fails only if you try to access the database for the first time with the existing SQLITE_NOTADB.
The key and rekey functions only fail, if you pass them nullpointers, but this can't happen here.
So actually this are noops, but the functions are a part of sqlites more generic codec interface and other implementations may choose to fail here, so we should at least check the return code.

database(const std::string &db_name, const std::string &key): database(db_name) {
set_key(key);
}
database(const std::u16string &db_name, const std::string &key): database(db_name) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zauguin Make the second parameter of the constructor an instance of struct sqlite_config { std::string key; };. The reason i suggest this is that we might pass other flags in the future, an example is #72 which i've implemented in #71 but is not merged yet.

#ifdef SQLITE_HAS_CODEC
if(!config.key.empty()) set_key(config.key);
#else
assert(config.key.empty() && "Encryption supported is disabled.");
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use an exception instead, but passing a key without encryption support is IMO a strong indication, that the application is compiled with the wrong settings.

@zauguin zauguin self-assigned this Feb 1, 2017
@polesapart
Copy link

I use sqlcipher - by including it's header instead of sqlite and arranging proper ldflags - and using PRAGMAS instead of it's extended C api. While I don't see any problems with conditionally adding that support to sqlite_modern_cpp, it's not strictly necessary either.

Please note that sqlcipher is not the only project using SQLITE_HAS_CODEC and relying on it for autodetection may lead to incompatibilities in case someone uses one of these other extensions to sqlite.

@zauguin
Copy link
Collaborator Author

zauguin commented Feb 1, 2017

SQLITE_HAS_CODEC is used for autodetection, because I think this works for every system using SQLITE_HAS_CODEC.
But I can't test it with other projects using this feature right now.

@polesapart
Copy link

polesapart commented Feb 1, 2017

At least "see" (sqlite's own encrypted version, which is proprietary and requires license) uses SQLITE_HAS_CODEC for the same purposes. One wouldn't be able to use "see" transparently with this library, as it has no 1:1 API compatibility with sqlcipher (altough there's a common subset). I suggest you disable autodetection and require the user to pass a specific define, i.e. HAVE_SQLCIPHER or something.

@aminroosta aminroosta mentioned this pull request Feb 9, 2017
@aminroosta
Copy link
Collaborator

@polesapart @zauguin We are adding new #define for optional features.
We already have _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT and now ENABLE_SQLCIPHER (which should be renamed to _MODERN_SQLITE_ENABLE_SQLCIPHER).

I wonder if you think there is an easy way to include new .h files that extend the core library.
Adding a hdr/sqlite_modern_cpp/sqlcipher.h should enable sqlcipher and a similar header to enable boost support.

@aminroosta
Copy link
Collaborator

aminroosta commented Feb 9, 2017

@zauguin How about struct sqlcipher_database : public sqlite:database { ... }; in the new hder/sqlite_modern_cpp/sqlcipher.h file? Do you think that makes sense ?

@zauguin
Copy link
Collaborator Author

zauguin commented Feb 13, 2017

I like this approach, but if we want to add additional features like this we may need virtual inheritance so that the features can be combined.

@aminroosta
Copy link
Collaborator

@zauguin Nicely done! Looks good to me 👍
@polesapart Any comment before we merge this?

@aminroosta
Copy link
Collaborator

@zauguin Is it possible (& easy) to write a test for this?

@zauguin
Copy link
Collaborator Author

zauguin commented Feb 14, 2017

Writing a test is easy but running it isn't. We could either require SQLCipher for our test suite or only test it if SQLCipher is available. I prefer the second option, but I don't know how to implement it with autotools. We might have to change our testing system too, because the other test should not run against SQLCipher.

@aminroosta
Copy link
Collaborator

@zauguin I see that you have already implemented Skipped tests to Makefile.in.

Add a test for sqlcipher and skip it by default in Makefile.in.

@zauguin
Copy link
Collaborator Author

zauguin commented Feb 16, 2017

I added the test which only executes if ENABLE_SQLCIPHER_TESTS is defined and added a hack for travis to check using SQLite3 and SQLCipher.

@aminroosta aminroosta merged commit 1ba1ef4 into SqliteModernCpp:master Feb 16, 2017
@polesapart
Copy link

@aminroosta I came late to the party, but everything seems ok from where I stand. Thanks to @zauguin for his efforts!

@zauguin zauguin deleted the sqlcipher branch February 19, 2017 11:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants