0

I am using SQLCipher to encrypt SQLite databases. I seem to run into trouble to ATTACH an encrypted database with a custom cipher_page_size (different from the default value of 1024).

Here is my code

- (void) database:(sqlite3*) database execute:(NSString*) sql {
    if (sqlite3_exec(database, [sql UTF8String], NULL, NULL, NULL) == SQLITE_OK) {
        NSLog(@"\"%@\" successfully executed", sql);
    } else {
        NSLog(@"Could not execute \"%@\" (%s)", sql, sqlite3_errmsg(database));
    }
}

- (void)test {

    sqlite3 *database1;
    sqlite3 *database2;

    NSString *path1 = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
                        stringByAppendingPathComponent:@"database1.sqlite"];
    NSString *path2 = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
                        stringByAppendingPathComponent:@"database2.sqlite"];

    if (sqlite3_open([path1 UTF8String], &database1) == SQLITE_OK) {
        NSLog(@"database1 opened successfully");
        [self database:database1 execute:@"PRAGMA key = 'password1';"];
        //[self database:database1 execute:@"PRAGMA cipher_page_size = 2048;"];
        [self database:database1 execute:@"CREATE TABLE IF NOT EXISTS table1 (id INTEGER PRIMARY KEY, name TEXT);"];
        [self database:database1 execute:@"INSERT INTO table1 (name) VALUES ('bob');"];
        sqlite3_close(database1);
    } else {
        sqlite3_close(database1);
        NSLog(@"Failed to open database1 with message '%s'.", sqlite3_errmsg(database1));
    }

    if (sqlite3_open([path2 UTF8String], &database2) == SQLITE_OK) {
        NSLog(@"database2 opened successfully");
        [self database:database2 execute:@"PRAGMA key = 'password2';"];
        //[self database:database2 execute:@"PRAGMA cipher_page_size = 2048;"];
        [self database:database2 execute:@"CREATE TABLE IF NOT EXISTS table2 (id INTEGER PRIMARY KEY, name TEXT);"];
        [self database:database2 execute:@"INSERT INTO table2 (name) VALUES ('john');"];

        [self database:database2 execute:[NSString stringWithFormat:@"ATTACH DATABASE '%@' AS database1 KEY 'password1';", path1]];
        [self database:database2 execute:@"DETACH DATABASE database1;"];

        sqlite3_close(database2);
    } else {
        sqlite3_close(database2);
        NSLog(@"Failed to open database2 with message '%s'.", sqlite3_errmsg(database2));
    }
}

When the lines about changing the cipher_page_size are commented the code works as expected. When they are commented out I get error SQLITE_NOTADB (database is encrypted or not a database file).

1 Answer 1

1

You should explicitly set the page size for the attached database immediately after you attach it, i.e.:

ATTACH DATABASE 'db1.db' AS database1 KEY 'password1';
PRAGMA database1.cipher_page_size = 2048;
Sign up to request clarification or add additional context in comments.

5 Comments

Unfortunately that does not work as the error arises on the ATTACH statement itself.
This is a bug, the core library is using the default page size during the attach. I've logged it and we'll take a closer look into it. For the time being, do you have the option to use the default page size of 1024?
Thanks. Yes I got around the problem by changing slightly my data structure and now do not need to ATTACH. Thanks for submitting the bug.
@StephenLombardo what is the difference between cipher_page_size added in SQLCipher and the original page_size declared in SQLite3? If I changed the SQLITE_DEFAULT_PAGE_SIZE declared in SQLite source code, which I think it is equivalent to "PRAGMA page_size = xxx", does it have nothing to do with cipher_page_size used by SQLCipher?
@gzh the SQLITE_DEFAULT_PAGE_SIZE is only used for non-encrypted databases. SQLCipher uses a separate page size setting for encrypted databases, which is 4096 by default in SQLCipher 4.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.