Skip to content

Commit 2bee23f

Browse files
committed
sqlcipher troubleshooting
1 parent e8c52be commit 2bee23f

File tree

5 files changed

+35
-11
lines changed

5 files changed

+35
-11
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

nix/libxmtp.nix

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
, zstd
2020
, llvmPackages_19
2121
, wasm-bindgen-cli
22+
, sqlcipher
2223
, ...
2324
}:
2425

@@ -70,6 +71,7 @@ mkShell {
7071
# native libs
7172
openssl
7273
sqlite
74+
sqlcipher
7375

7476
mktemp
7577
jdk21

xmtp_mls/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ xmtp_proto = { workspace = true, features = ["test-utils"] }
156156
fdlimit = { workspace = true }
157157
once_cell.workspace = true
158158

159+
[target.'cfg(not(target_arch = "wasm32"))'.build-dependencies]
160+
pkg-config = "0.3"
161+
159162
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
160163
ctor.workspace = true
161164
ethers = { workspace = true, features = ["openssl"] }

xmtp_mls/build.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#[cfg(not(target_arch = "wasm32"))]
2+
fn main() {
3+
// make sure we are statically linking sqlcipher at build time
4+
pkg_config::Config::new()
5+
.statik(true)
6+
.probe("sqlcipher")
7+
.unwrap();
8+
}

xmtp_mls/src/storage/encrypted_store/sqlcipher_connection.rs

+21-11
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl EncryptedConnection {
4646
/// Creates a file for the salt and stores it
4747
pub fn new(key: EncryptionKey, opts: &StorageOption) -> Result<Self, StorageError> {
4848
use super::StorageOption::*;
49-
Self::check_for_sqlcipher(opts)?;
49+
Self::check_for_sqlcipher(opts, None)?;
5050

5151
let salt = match opts {
5252
Ephemeral => None,
@@ -222,28 +222,28 @@ impl EncryptedConnection {
222222
}
223223
}
224224

225-
fn check_for_sqlcipher(opts: &StorageOption) -> Result<(), StorageError> {
225+
fn check_for_sqlcipher(
226+
opts: &StorageOption,
227+
conn: Option<SqliteConnection>,
228+
) -> Result<CipherVersion, StorageError> {
226229
if let Some(path) = opts.path() {
227230
let exists = std::path::Path::new(path).exists();
228231
tracing::debug!("db @ [{}] exists? [{}]", path, exists);
229232
}
230-
let conn = &mut opts.conn()?;
231-
let cipher_version = sql_query("PRAGMA cipher_version").load::<CipherVersion>(conn)?;
233+
let conn = &mut conn.unwrap_or(opts.conn()?);
234+
let mut cipher_version = sql_query("PRAGMA cipher_version").load::<CipherVersion>(conn)?;
232235
if cipher_version.is_empty() {
233236
return Err(StorageError::SqlCipherNotLoaded);
234237
}
235-
Ok(())
238+
Ok(cipher_version.pop().expect("checked for empty"))
236239
}
237240
}
238241

239242
impl super::native::ValidatedConnection for EncryptedConnection {
240243
fn validate(&self, opts: &StorageOption) -> Result<(), StorageError> {
241244
let conn = &mut opts.conn()?;
242245

243-
let cipher_version = sql_query("PRAGMA cipher_version").load::<CipherVersion>(conn)?;
244-
if cipher_version.is_empty() {
245-
return Err(StorageError::SqlCipherNotLoaded);
246-
}
246+
let cipher_version = EncryptedConnection::check_for_sqlcipher(opts, None)?;
247247

248248
// test the key according to
249249
// https://www.zetetic.net/sqlcipher/sqlcipher-api/#testing-the-key
@@ -259,8 +259,8 @@ impl super::native::ValidatedConnection for EncryptedConnection {
259259
} = sql_query("PRAGMA cipher_provider_version")
260260
.get_result::<CipherProviderVersion>(conn)?;
261261
tracing::info!(
262-
"Sqlite cipher_version={:?}, cipher_provider_version={:?}",
263-
cipher_version.first().as_ref().map(|v| &v.cipher_version),
262+
"Sqlite cipher_version={}, cipher_provider_version={:?}",
263+
cipher_version.cipher_version,
264264
cipher_provider_version
265265
);
266266
if tracing::enabled!(tracing::Level::DEBUG) {
@@ -314,6 +314,16 @@ mod tests {
314314
const SQLITE3_PLAINTEXT_HEADER: &str = "SQLite format 3\0";
315315
use StorageOption::*;
316316

317+
#[tokio::test]
318+
async fn test_sqlcipher_version() {
319+
let db_path = tmp_path();
320+
{
321+
let opts = Persistent(db_path.clone());
322+
let v = EncryptedConnection::check_for_sqlcipher(&opts, None).unwrap();
323+
println!("SQLCipher Version {}", v.cipher_version);
324+
}
325+
}
326+
317327
#[tokio::test]
318328
async fn test_db_creates_with_plaintext_header() {
319329
let db_path = tmp_path();

0 commit comments

Comments
 (0)