Background:
We have a setup that has sqlcipher
installed and the ruby gem sqlite3 (a wrapper around sqlite3) is built and links to sqlcipher
.
I am in the process of testing sqlite databases (we have many) from our current production environment (that runs an older set of sqlite3/sqlcipher) in a newer development environment. I can determine that I need to run cipher_migrate
to continue to use the dbs in the new environment.
The ruby gem is built natively on installation with the --with-sqlcipher
flag and I can confirm it is linked - I can use it successfully with new encrypted databases and already migrated older encrypted databases.
In a bash shell in the environment (an Ubuntu Docker container) using sqlcipher
directly at the command line, I can successfully open the db, enter the key and run PRAGMA cipher_migrate
and the db will be migrated and returns a value of 0.
The problem:
If I open the db from within the Ruby (on Rails) console using the sqlite3
gem that is linked to the same installation of sqlcipher
, enter the key and run PRAGMA cipher_migrate
it fails with a return error of 1. If I open the db after it was migrated from the command line sqlcipher
it works as expected. I need to be able to migrate as part of the new app’s process using the ruby gem.
I suspect there is something set in the sqlite3
gem that is causing a conflict for sqlcipher
but I don’t know what it could be.
I enabled cipher_log
at “trace” level and captured what is happening in each case and you can see there is a divergence in the output but I don’t know where to go from here.
Log using sqlcipher
directly at bash command line (snipped because it is long):
sqlcipher_codec_pragma: db=0x40001ad4d0 iDb=0 pParse=0x40019ab1d0 zLeft=cipher_migrate zRight=(null) ctx=0x40001f2660
sqlcipher_malloc: calling sqlite3Malloc(22)
sqlcipher_malloc: calling sqlcipher_memset(0x40001f3c60,0,22)
sqlcipher_memset: setting 0x40001f3c60[0-22]=0)
sqlcipher_mem_lock: calling mlock(0x40001f3000,3190); _SC_PAGESIZE=4096
sqlite3_key: db=0x40001f3c80
sqlite3_key_v2: db=0x40001f3c80 zDb=main
sqlcipherCodecAttach: db=0x40001f3c80, nDb=0
sqlcipherCodecAttach: calling sqlcipher_activate()
sqlcipher_activate: entering static master mutex
sqlcipher_activate: entered static master mutex
sqlcipher_activate: leaving static master mutex
sqlcipher_activate: left static master mutex
sqlcipherCodecAttach: entering database mutex (nil)
sqlcipherCodecAttach: entered database mutex (nil)
sqlcipherCodecAttach: calling sqlcipher_codec_ctx_init()
sqlcipher_codec_ctx_init: allocating context
sqlcipher_malloc: calling sqlite3Malloc(136)
sqlcipher_malloc: calling sqlcipher_memset(0x40002038f0,0,136)
sqlcipher_memset: setting 0x40002038f0[0-136]=0)
sqlcipher_mem_lock: calling mlock(0x4000203000,2424); _SC_PAGESIZE=4096
sqlcipher_codec_ctx_init: allocating kdf_salt
sqlcipher_malloc: calling sqlite3Malloc(16)
sqlcipher_malloc: calling sqlcipher_memset(0x4000203980,0,16)
sqlcipher_memset: setting 0x4000203980[0-16]=0)
sqlcipher_mem_lock: calling mlock(0x4000203000,2448); _SC_PAGESIZE=4096
sqlcipher_codec_ctx_init: allocating hmac_kdf_salt
sqlcipher_malloc: calling sqlite3Malloc(16)
sqlcipher_malloc: calling sqlcipher_memset(0x40002039a0,0,16)
sqlcipher_memset: setting 0x40002039a0[0-16]=0)
sqlcipher_mem_lock: calling mlock(0x4000203000,2480); _SC_PAGESIZE=4096
sqlcipher_codec_ctx_init: allocating provider
sqlcipher_malloc: calling sqlite3Malloc(136)
sqlcipher_malloc: calling sqlcipher_memset(0x40002039c0,0,136)
sqlcipher_memset: setting 0x40002039c0[0-136]=0)
sqlcipher_mem_lock: calling mlock(0x4000203000,2632); _SC_PAGESIZE=4096
sqlcipher_codec_ctx_init: entering SQLCIPHER_MUTEX_PROVIDER
sqlcipher_codec_ctx_init: entered SQLCIPHER_MUTEX_PROVIDER
sqlcipher_codec_ctx_init: leaving SQLCIPHER_MUTEX_PROVIDER
sqlcipher_codec_ctx_init: left SQLCIPHER_MUTEX_PROVIDER
sqlcipher_openssl_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE
sqlcipher_openssl_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE
sqlcipher_openssl_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE
sqlcipher_openssl_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE
…snipped…
Log using sqlite3
ruby gem linked to the same sqlcipher
installation in same environment as above:
sqlcipher_codec_pragma: db=0x401e2f8830 iDb=0 pParse=0x40017ff6c0 zLeft=cipher_migrate zRight=(null) ctx=0x4020b350b0
sqlcipher_malloc: calling sqlite3Malloc(1)
sqlcipher_malloc: calling sqlcipher_memset(0x4020f93630,0,1)
sqlcipher_memset: setting 0x4020f93630[0-1]=0)
sqlcipher_mem_lock: calling mlock(0x4020f93000,1585); _SC_PAGESIZE=4096
sqlite3_key: db=0x4020bc2810
sqlite3_key_v2: db=0x4020bc2810 zDb=main
sqlite3_key_v2: no key provided
sqlite3_key: db=0x4020bc2810
sqlite3_key_v2: db=0x4020bc2810 zDb=main
sqlite3_key_v2: no key provided
sqlcipher_free: calling sqlcipher_memset(0x4020bc1c60,0,32)
sqlcipher_memset: setting 0x4020bc1c60[0-32]=0)
sqlcipher_mem_unlock: calling munlock(0x4020bc1000,3200)
sqlite3_key: db=0x4020bc2810
sqlite3_key_v2: db=0x4020bc2810 zDb=main
sqlite3_key_v2: no key provided
sqlcipher_free: calling sqlcipher_memset(0x4020f93650,0,32)
sqlcipher_memset: setting 0x4020f93650[0-32]=0)
sqlcipher_mem_unlock: calling munlock(0x4020f93000,1648)
sqlite3_key: db=0x4020bc2810
sqlite3_key_v2: db=0x4020bc2810 zDb=main
sqlite3_key_v2: no key provided
sqlcipher_free: calling sqlcipher_memset(0x4020f93680,0,32)
sqlcipher_memset: setting 0x4020f93680[0-32]=0)
sqlcipher_mem_unlock: calling munlock(0x4020f93000,1696)
Upgrade format not determined
An error occurred attempting to migrate the database - last error 1
sqlcipher_free: calling sqlcipher_memset(0x4020f93630,0,0)
sqlcipher_memset: setting 0x4020f93630[0-0]=0)
sqlcipher_codec_pragma: error occurred during cipher_migrate: 1
sqlcipher_codec_ctx_set_error: ctx=0x4020b350b0, error=1
sqlcipher_codec_pragma: db=0x401e2f8830 iDb=0 pParse=0x40017fef90 zLeft=encoding zRight=(null) ctx=0x4020b350b0
sqlcipher_codec_pragma: db=0x401e2f8830 iDb=0 pParse=0x40017fef90 zLeft=encoding zRight=(null) ctx=0x4020b350b0
1
I’ve bolded some above statements in the log I think may be clues.
As mentioned above, the underlying sqlcipher
installation is the same in both cases so I suspect some settings that the sqlite3
gem has imposed are causing the issue but I don’t know what they are.
Additional information:
The cipher_version
for the old installation (where the dbs were built): 3.4.2
The cipher_version
for the new installation: 4.5.2 community
The cipher_settings
for the new installation (I think this is not a command in old):
PRAGMA kdf_iter = 256000;
PRAGMA cipher_page_size = 4096;
PRAGMA cipher_use_hmac = 1;
PRAGMA cipher_plaintext_header_size = 0;
PRAGMA cipher_hmac_algorithm = HMAC_SHA512;
PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512;
The way the new installation’s ‘sqlcipher’ is installed in the Docker image:
RUN git clone https://github.com/sqlcipher/sqlcipher.git
RUN cd sqlcipher && ./configure
–prefix=/usr
–enable-tempstore=yes
CFLAGS=“-DSQLITE_HAS_CODEC”
LDFLAGS=“-lcrypto” &&
make &&
make install &&
cd /tmp
The ruby gem is built natively in the installation using the --with-sqlcipher
flag
Testing the built file for the ruby gem using ldd
to see that it is linked to libsqlcipher
:
ldd /.../bundle/ruby/2.6.0/bundler/gems/extensions/x86_64-linux/2.6.0/sqlite3-ruby-31ea0084ced0/sqlite3/sqlite3_native.so
libruby.so.2.6 => /usr/local/rvm/rubies/ruby-2.6.9/lib/libruby.so.2.6 (0x0000004001842000)
libsqlcipher.so.0 => /lib/libsqlcipher.so.0 (0x0000004001bd3000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000004001d00000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x0000004001ef2000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000004001f0e000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x0000004001f31000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x0000004001f3e000)
libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x0000004001f44000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x0000004001f7f000)
/lib64/ld-linux-x86-64.so.2 (0x0000004000000000)
libcrypto.so.1.1 => /lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00000040020ce000)
Note: /lib
is a symlink to /usr/lib
Can someone deduce from above what is happening here that suggests what is different and what sqlite3/sqlcipher settings should be changed to resolve?
What is the next step for troubleshooting this? Some more info needed?