FMDB + SQLCipher

2,236 views
Skip to first unread message

Arnaud Schloune

unread,
Apr 10, 2013, 6:16:30 PM4/10/13
to fm...@googlegroups.com

Hi All,

I'm trying to use SQLCipher with FMDB. Anyone has an idea, or a tutorial with the whole process ?

Thanks a lot !

Phillip Kast

unread,
Apr 10, 2013, 8:40:44 PM4/10/13
to fm...@googlegroups.com
Arnaud,

I've just worked through this in the last couple months. SQLCipher's own tutorial is a good starting point: http://sqlcipher.net/ios-tutorial/

If there's something you're stuck on I'm happy to answer questions.

Arnaud Schloune

unread,
Apr 11, 2013, 7:52:39 AM4/11/13
to fm...@googlegroups.com
Hi Phillip,

Thanks for your reply.

I've used the tutorial to integrate the libs in my project. It works fine, I can compile the app on the device or on the simulator.

But my question is how to combine the code with FMDB. The code displayed in the tutorial (Integration Code) doesn't use FMDB.

Would you have any sample code ?

What's the process ? Should I first encrypt the database before adding it to the project ?

Thanks for your help !

Arnaud

Phillip Kast

unread,
Apr 11, 2013, 1:49:08 PM4/11/13
to fm...@googlegroups.com
FMDB has support built in for keying your database. Check out -setKey: -- you'd use it something like:

- (void)setupEncryption:(FMDatabase *)db
{
[db setKey:@"my-secret-passphrase";
}

You need to do that when you open the database. If you setKey: a new database with nothing written to disk yet, it will get encrypted.

When you've done this, you should check that it's working. SQLCipher's tutorial has some instructions for that. The gist is that you want to pop open your database file in a hex editor or something -- unencrypted databases have lots of human readable stuff, encrypted ones don't.

By the way, the example above is what you want to do if you've got a text passphrase (like if the user enters a password to unlock their database). If you plan to randomly generate the database key, I have a pull request to add a -setKeyWithData: that you might want to look at -- it will work better with random bytes.

--
You received this message because you are subscribed to a topic in the Google Groups "FMDB" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/fmdb/d7EFu9-RWuE/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to fmdb+uns...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Arnaud Schloune

unread,
Apr 12, 2013, 2:31:32 AM4/12/13
to fm...@googlegroups.com
Hi Phillip,

Thanks again for your help.

Everytime I try to insert a row in the DB, i get this error : 

DB Error: 26 "file is encrypted or is not a database"


Should I use "setKey" only at creation time ? Does my database first need to be crypted with another tool ?

When i try to insert a row, first I use setKey, then I open the database.

If i first open the database before setKey, no datas are crypted. The otherway, i get the error "DB Error: 26 "file is encrypted or is not a database"

Can you please help me ?


Thanks a lot !

Arnaud

Phillip Kast

unread,
Apr 12, 2013, 12:42:42 PM4/12/13
to fm...@googlegroups.com
setKey: should be the first thing you call whenever you open the db.

For example (if you're using an FMDatabaseQueue):

_sharedDatabaseQueue = [FMDatabaseQueue databaseQueueWithPath:[self databasePath]];
[_sharedDatabaseQueue inDatabase:^(FMDatabase *db) {
    [db setKey:[self databaseKey]];
}];

From the error you're getting, sounds like you aren't setting the key when you re-open an existing database.

Arnaud Schloune

unread,
Apr 12, 2013, 3:57:30 PM4/12/13
to fm...@googlegroups.com
Whatever I do, i always get the error. I'll explain you my whole process, please correct me when I'm wrong :

In my xCode project, I have an empty sqlite file, with empty tables. This file is not encrypted at all.

When the app launches, i check if the database is copied in the Documents folder. If not, i copy it using this code :

if([[NSFileManager defaultManager] fileExistsAtPath:self.databasePath])
        return;
    NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:self.databaseName];
    [[NSFileManager defaultManager] createFileAtPath:self.databasePath contents:[NSData dataWithContentsOfFile:databasePathFromApp] attributes:nil];


After this step, i have my sqlite file in the App's documents folder. I can open this file, it's not encrypted.

Then, i make :

self.db = [FMDatabase databaseWithPath:self.databasePath];
[self.db setKey:secretKEY];

 After this, I should be able to use my database.

Here's how i try, but get an error :

[[DB sharedInstance] encryptDB]; //setKey()
[[[DB sharedInstance] db] open];            
BOOL inserted = [[[DB sharedInstance] db] executeUpdate:sql withParameterDictionary:datas];
[[[DB sharedInstance] db] close];

Can you see something wrong ?

I'm going crazy!

Thanks a lot for your help ! 

August Mueller

unread,
Apr 12, 2013, 4:01:54 PM4/12/13
to fm...@googlegroups.com
On Apr 12, 2013, at 12:57 PM, Arnaud Schloune <arnaud....@gmail.com> wrote:

Whatever I do, i always get the error. I'll explain you my whole process, please correct me when I'm wrong :

In my xCode project, I have an empty sqlite file, with empty tables. This file is not encrypted at all.

When the app launches, i check if the database is copied in the Documents folder. If not, i copy it using this code :

So you're wanting to encrypt a document that's not already encrypted.  You'll want to use rekey: instead of setKey: to convert a regular sqlite db to an encrypted one.

-gus

Arnaud Schloune

unread,
Apr 12, 2013, 4:19:25 PM4/12/13
to fm...@googlegroups.com
Hi August,

So, after having copied the file in the documents folder, i make :

[self.db rekey:secretKEY];

(secretKey is a NSString object)

but i get this error :

2013-04-12 22:17:54.770 App[11827:c07] error on rekey: 1

2013-04-12 22:17:54.771 App[11827:c07] out of memory

Any ideas ?




2013/4/12 August Mueller <g...@flyingmeat.com>

--

August Mueller

unread,
Apr 12, 2013, 4:38:52 PM4/12/13
to fm...@googlegroups.com
Did you open the database?

You received this message because you are subscribed to the Google Groups "FMDB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fmdb+uns...@googlegroups.com.

Arnaud Schloune

unread,
Apr 12, 2013, 4:51:04 PM4/12/13
to fm...@googlegroups.com
In fact, I was not opening before rekey()

Now that i open the database before rekey, i have no more error.

But the database file is not encrypted...


2013/4/12 August Mueller <g...@flyingmeat.com>

August Mueller

unread,
Apr 12, 2013, 6:29:22 PM4/12/13
to fm...@googlegroups.com
On Apr 12, 2013, at 1:51 PM, Arnaud Schloune <arnaud....@gmail.com> wrote:

In fact, I was not opening before rekey()

Now that i open the database before rekey, i have no more error.

But the database file is not encrypted...

I've not used SQLCipher, so I'm not sure if it's a problem with it or FMDB.  If you can figure it out and if it's a problem on FMDB's side, let me know.

-gus

Phillip Kast

unread,
Apr 12, 2013, 6:43:15 PM4/12/13
to fm...@googlegroups.com
Definitely not an FMDB problem -- SQLCipher cannot do this.

If you check out sqlite3.c:13521-13530 in the latest release, you'll see the following comment:

/* sqlite3_rekey 
** Given a database, this will reencrypt the database using a new key.
** There is only one possible modes of operation - to encrypt a database
** that is already encrpyted. If the database is not already encrypted
** this should do nothing
** The proposed logic for this function follows:
** 1. Determine if the database is already encryptped
** 2. If there is NOT already a key present do nothing
** 3. If there is a key present, re-encrypt the database with the new key
*/

They don't advertise this too widely in their docs, unfortunately. 

Arnaud: you probably want to bundle a db encrypted with a default key then use -rekey:, or else bundle an unencrypted db or flatfile or whatever, then create an encrypted database and import. You'll have to test it yourself, but I'd guess rekeying will be much faster.


Message has been deleted

Arnaud Schloune

unread,
Apr 25, 2013, 4:42:41 PM4/25/13
to fm...@googlegroups.com
Hi all,

I finally found a solution to make it work.
If someone has the same problem, i can send you parts of code.

Many thanks for your help !

Ashish Upadhyay

unread,
May 2, 2013, 10:18:01 PM5/2/13
to fm...@googlegroups.com
can you please share the code

thanks

Davide

unread,
Jun 10, 2013, 5:02:07 AM6/10/13
to fm...@googlegroups.com
Hi Arnaud, good work!
Please, can you tell us how you solved?
Thanks a lot!

Billy Gray

unread,
Jul 30, 2013, 12:01:44 AM7/30/13
to fm...@googlegroups.com
Hi all, 

Sorry to revive a dead thread, I'm a little late here, but I was doing some research into FMDB and how very nice it is (FMDatabaseQueue is awesome) when I saw this thread and thought maybe I could help out. I work at Zetetic and while I'm not a regular committer to SQLCipher, I can at least make mention of a few things:

* Definitely not a problem with FMDB
* To confirm: you can't re-key an existing, plain-text database that has no key, as noted earlier in the thread
* We don't encourage using sqlite3_rekey() to change the key or cipher settings (kdf_iter, etc), instead:
* If you want to encrypt a plain-text database, use ATTACH with KEY, and call sqlcipher_export() to copy your schema and data [1]
* If you want to change the key and/or cipher settings on an encrypted database, use ATTACH with KEY and call sqlcipher_export() [1]

It's true that we could have done a better job in the docs in the past and are endeavoring to do so, but our documentation for rekey() has been updated and attempts to point this out.[1a] rekey() works just fine, but it's for a very specific scenario: only changing the key on an existing database (e.g. password reset.)

In Arnaud's case, you'd open the plain-text sample db from the bundle resources, ATTACH a new db with a KEY set (hopefully from the user, and not a hard-coded value in the app) in the app's document root, and then use that as the app's datasource going forward. 

I'll be at Passwords13 and some of Defcon this week if anybody wants to ask some questions about SQLCipher (if I can't answer I'll forward on), or if you'd like one of the many nifty stickers I've brought with me. You can find me on twitter at @billymeltdown.

I have an implementation of a re-key using sqlcipher_export()[2] that you can check out, with the caveat that it needs some love (the very first "return NO;" sans any error object is a good example of what I mean.)

Check out the SQLCipher users mailing list ;-) [3]

Kind regards,
Billy Gray

Gus Mueller

unread,
Jul 30, 2013, 5:48:53 PM7/30/13
to fm...@googlegroups.com
On Jul 29, 2013, at 9:01 PM, Billy Gray <wg...@zetetic.net> wrote:

> Sorry to revive a dead thread, I'm a little late here, but I was doing some
> research into FMDB and how very nice it is (FMDatabaseQueue is awesome)
> when I saw this thread and thought maybe I could help out. I work at
> Zetetic and while I'm not a regular committer to SQLCipher, I can at least
> make mention of a few things:

Awesome- thanks for the info Billy. This will certainly help folks out in the future.

-gus

Arnaud Schloune

unread,
Aug 8, 2013, 5:48:02 AM8/8/13
to fm...@googlegroups.com
Hi Davide,

I'll try to publish the code to github this evening, and share it with all of you.

Best regards,
Arnaud

gyu...@gmail.com

unread,
Aug 21, 2013, 5:14:49 AM8/21/13
to fm...@googlegroups.com
Can you please share the code?I need it very much.Thanks!

在 2013年8月8日星期四UTC+8下午5时48分02秒,Arnaud Schloune写道:

Jesus V.

unread,
Oct 8, 2013, 7:00:48 AM10/8/13
to fm...@googlegroups.com
Can you share your code, please?

John Ryan

unread,
Jan 20, 2014, 3:06:20 PM1/20/14
to fm...@googlegroups.com
Arnaud, did you ever post sample code for this?

Thanks,
John

Guilherme Mogames

unread,
Feb 20, 2014, 6:36:43 PM2/20/14
to fm...@googlegroups.com
I was able to finally find a solution. i created a tutorial here:

PBhatt

unread,
Feb 25, 2015, 11:38:15 AM2/25/15
to fm...@googlegroups.com

Hi All,
I am using this link http://www.guilmo.com/fmdb-with-sqlcipher-tutorial/ for unencrypted to encrypted DB migration , I have successfully created encrypted.sqlite file which contains old data in encrypted form. but the problem is I am not able to access it , I am trying to access it through coredata using the same passphrase key through which I encrypted the DB. Although If I used sqlcipher encryption as a standalone app(or a fresh install scenario where there is no old db) db gets encrypted and I can access it with coredata using passphrase key , all I am stuck is upgrade scenario . Please guide me where I am doing wrong .

John Ryan

unread,
Feb 25, 2015, 3:45:12 PM2/25/15
to fm...@googlegroups.com
Have you tried manually setting the key to open the db before trying to open it with core data? I don't have much experience using fmdb with core data but that could be causing the problem.

--
You received this message because you are subscribed to a topic in the Google Groups "FMDB" group.

To unsubscribe from this group and all its topics, send an email to fmdb+uns...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages