-
Notifications
You must be signed in to change notification settings - Fork 115
Conversation
I have relatively strong feelings that a misconfiguration — trying to build a key-using Mentat application against a non-crypto Mentat — should fail to build or panic at launch (the behavior that will result with bad run-time linking) rather than yielding a runtime error; after all, we have a wonderful compiler to help us, and the consequences of accidentally muffling the error (especially if someone writes expedient fallback code!) are potentially severe. I don’t think it’s too onerous to specify a An additional layer of runtime checks, as |
I can get a patch up for this relatively easily because I did it this way first, before deciding that it was annoying. My concerns are basically:
Neither of these may actually matter, though.
I'm not sure how to check this at runtime in a way that gives a descriptive result and isn't sort of disgusting. I can think of:
It's likely that I'm either unaware of or forgetting a substantially easier way to do this. (Ideally there would be a way that just requires running SQL!) |
…e compiled with sqlcipher support
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer the feature gunk, even if it is onerous, so let's fold that in to the landing.
This looked exactly as I expected, so I just have a few nits and minor naming requests.
A test fixture to ensure we don't regress loading and a simple query would go a long way. Somewhere in the db
crate is most appropriate. Can we create in-memory encrypted databases? (I assume so.) An additional test that runs over an in-memory DB would be appreciated too.
Please reference #118 (close it, if appropriate) in your landing.
I'll add you as a collaborator so you can commit to master
.
Thanks, Thom!
db/src/errors.rs
Outdated
|
||
/// Attempted to perform an operation on the database that requires sqlcipher support. | ||
SqlCipherMissing { | ||
description("sqlcipher support required to use a database key, but this build does not have it") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it
is a little ambiguous: maybe "database key provided, but sqlcipher not enabled in sqlite library"?
src/conn.rs
Outdated
/// Variant of `open` that allows a key (for encryption/decryption) to be | ||
/// supplied. Fails unless linked against sqlcipher (or something else that | ||
/// supports the Sqlite Encryption Extension). | ||
pub fn open_with_key(path: &str, key: &str) -> Result<Store> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can we always use encryption_key
, for names and parameters? "key" can mean many things; let's make grep
do work for ourselves in the future.
tools/cli/src/mentat_cli/repl.rs
Outdated
if self.path.is_empty() || path != self.path { | ||
let next = Store::open(path.as_str())?; | ||
let next = if let Some(k) = key { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block might be more pleasant as a match
.
tools/cli/src/mentat_cli/repl.rs
Outdated
let next = if let Some(_k) = key { | ||
#[cfg(not(feature = "sqlcipher"))] | ||
{ | ||
bail!(".open_encrypted and .empty_encrypted require builds with sqlcipher support"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"builds" could refer to Mentat or to the underlying SQLite library. Perhaps, ".*_encrypted require the sqlcipher
Mentat feature."
Whelp, I have no clue how to get travis working with sqlcipher. AFAICT the version of ubuntu on travis means that For now I've abandoned testing on travis, and will file a bug about that. |
Just FYI, this doesn't build with stable Rust. I'll fix and push follow-up. |
Sorry, with Rust 1.25:
Our minimum version is set in Line 22 in 6a1a265
|
I've addressed this in f041dfe. |
This adds a
sqlcipher
feature (which is incompatible with thebundled_sqlite3
) support for opening aStore
with a key, changing the key of an open Store, and support for it through the CLI and (in theory) the FFI. It's based some on @mhammond's branch, and on debugging we did on Wednesday.The additional APIs aren't behind
cfg(feature = "sqlcipher")
mostly because it seems like that's a big pain to use and requires callers add a lot of similarcfg
's. Instead, we emit aResult::Err
when you try to do something that would require sqlcipher when we weren't build with support for it. I could easily be convinced we should do things the other way.It's easy-ish to try on mac, since you can
brew install sqlcipher --with-fts
, thencargo build --no-default-features --features sqlcipher
. See caveat number 1 about building/running the cli or building the ffi, though (needs to be done from the directory in question due to a cargo bug). On other platforms this is trickier.Some caveats:
Until New behavior of
--feature
+--package
combination rust-lang/cargo#5364 is fixed, building nested crates that depend on mentat itself (e.g. tools/cli and ffi) must be done inside the directory of those crates. Specificallycargo build --no-default-features --features sqlcipher -p mentat_cli
will apply the--features
and--no-default-features
flags to the wrong package.cd tools/cli; cargo build --no-default-features --features sqlcipher; cd '-';
works instead. Ditto substitutingtools/cli
withffi
. Yes, this is annoying.PRAGMA page_size
doesn't seem to be valid in all cases when used in conjunction withPRAGMA cipher_page_size
. I can't find official documentation on this. What I have found is:page_size
but notcipher_page_size
seems never to be valid.cipher_page_size
is a positive integer multiple ofpage_size
(I didn't check this very thoroughly though).page_size
, thecipher_page_size
is not simply an optimization detail! Having the correctcipher_page_size
is required to read the contents of a database, e.g. if you open a DB with cipher_page_size at 8192 (for example) that's the value it must always have in order for reads/writes to be successful.I set it to the value we were using for
page_size
before, and made the code use bothcipher_page_size
andpage_size
when using sqlcipher. It's not at all clear to me this was the right choice, though.There are no tests outside the CLI parsing changes. I'm open to suggestions about how best to test this, though. Maybe adding an encrypted db in fixtures and making sure that we can open it would be enough?