Sqlcipher db migration from version 3.7.9 to 3.28.0

I am trying to open the sqlcipher db created with sqlcipher based on sqlite version 3.7.9 with sqlcipher based on sqlite version 3.28.0. Is this even possible? I know that the time difference between versions is 8 years…

I have tried following commands:

sqlite> PRAGMA key = 'myPassword';
sqlite> .schema 
Error: file is not a database
sqlite> PRAGMA cipher_migrate;
1
sqlite> .schema
Error: file is not a database
sqlite> PRAGMA cipher_compatibility = 1;
sqlite> .schema
Error: out of memory

How could I investigate why exactly the migration fails?

Hello @flukson - 3.7.9 was the baseline for SQLCipher 2. It should be migratable, but checking the schema after setting the key is likely interfering. Try the following

sqlite> PRAGMA key = 'myPassword';
sqlite> PRAGMA cipher_migrate;

Alternately, for backwards compatibility, try:

sqlite> PRAGMA key = 'myPassword';
sqlite> PRAGMA cipher_compatibility = 2;

If those don’t work you may be using some custom settings, and it would be most useful to check the code that created the database to see if there were any PRAGMA statements in use that adjusted things like the KDF iterations, HMAC, etc.

@sjlombardo, thank you for your answer.
I have tried both these methods. Unfortunately I get the “file is not a database” or “out of memory” errors. Is there any way to print more useful information about what exactly happens?

These errors (especially first one) are quite generic. Because of that I have built the sqlcipher with flags:

-DSQLITE_DEBUG
-DSQLITE_ENABLE_EXPLAIN_COMMENTS
-DSQLITE_ENABLE_SELECTTRACE
-DSQLITE_ENABLE_WHERETRACE

When I try to migrate the database, I get following output:

sqlite> .eqp full
sqlite> PRAGMA key = ‘myPassword’;
addr opcode p1 p2 p3 p4 p5 comment
0 Init 0 1 0 00 Start at 1
1 Halt 0 0 0 00
sqlite> PRAGMA cipher_migrate;
addr opcode p1 p2 p3 p4 p5 comment
0 Init 0 1 0 00 Start at 1
1 String8 0 1 0 1 00 r[1]=‘1’
2 ResultRow 1 1 0 00 output=r[1]
3 Halt 0 0 0 00
1
sqlite> .schema
Error: file is not a database

Unfortunately, I do not know what it means and if it is useful…

And are you sure that this was SQLCipher version 2? As far as I interpret the ‘git log’ properly, it was rather SQLCipher version 1.1.9 (maybe both 1.1.9 and 2.0.0 were based on Sqlite 3.7.9).

Hello @flukson - you are right, I believe that SQLite 3.7.9 spanned two major releases. A thought occurred to me about this. There was a short period between 1.1.9 and 2.0.0 where a beta version fo 2.0 contained settings that were ultimately different in the release version of 2.0.0. If you happened to be using SQLCipher from that brief window, you may not be using standard defaults. Can you try to pen the database using the following?

    PRAGMA key = 'myPassword';
    PRAGMA kdf_iter = 4000;
    PRAGMA fast_kdf_iter = 4000;
    PRAGMA cipher_hmac_salt_mask = "x'00'";
    PRAGMA cipher_page_size = 1024;
    PRAGMA cipher_hmac_algorithm = HMAC_SHA1;
    PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;

Also, just to rule this out, I noticed that the example you pasted in used curly single quotes around myPassword. That will not work properly with SQLCipher. I suspect this was some sort of autocorrection when you wrote/pasted, but just to verify, please make sure you are using standard ASCII single quote characters around myPassword.

Let me know if either of those suggestions proves fruitful.

Hi, @sjlombardo - thank you for your last message. I have tried your suggestions but unfortunately they do not work. Additionally, some of these settings give messages that they are deprecated.

I will describe my situation since the beginning:
I have an application that uses sqlcipher 1.1.9 or 2.0 in amalgamation version. After updating the sqlcipher to version 4.3.0 (latest one), the application does not work with the old database. Fortunately, it has a mechanism that recreates the db so when I remove the old db by hand, the app recreates it (using new sqlcipher). Then the application works properly. Both amalgamation versions were taken without any important changes.

Additionally, I have built the sqlcipher (in version 4.3.0) as a separate binary. Using the command line tool I can properly open the database created by the updated version of an app. However, I cannot open the old database although the key is the same.

The ideal situation would be to migrate somehow old database to new one.

Here I have some questions: is there any way to print all settings of the sqlcipher in the cmd line tool? Is there any api in c++ to use in the code to print the sqlcipher settings? Do settings for the amalgamation version differ from the settings for the standalone version?