Decrypt a SQLCipher database to a Plaintext Database

3,477 views
Skip to first unread message

chen li

unread,
May 4, 2012, 7:13:23 AM5/4/12
to SQLCipher Users
hi, i have a problem while follow the link as:

http://sqlcipher.net/sqlcipher-api/#key

and

http://sqlcipher.net/sqlcipher-for-android/

while executing

database.execSQL("ATTACH DATABASE '/data/data/com.SqlcipherSample/
databases/plaintext.db' AS plaintext KEY '';");

it keeping telling me that


05-04 19:00:02.312: ERROR/AndroidRuntime(16691): Caused by:
info.guardianproject.database.sqlcipher.SQLiteException: unable to
open database: plaintext.db: ATTACH DATABASE 'plaintext.db' AS
plaintext KEY '';

below is my complete file, is there any way to fix it?

Thanks very much.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package com.SqlcipherSample;

import java.io.File;
import java.io.IOException;

import android.app.Activity;
import info.guardianproject.database.sqlcipher.SQLiteDatabase;
import android.os.Bundle;

public class main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
InitializeSQLCipher();
}

private void InitializeSQLCipher() {
SQLiteDatabase.loadLibs(this);
File databaseFile = getDatabasePath("demo.db");
databaseFile.mkdirs();
databaseFile.delete();
SQLiteDatabase database =
SQLiteDatabase.openOrCreateDatabase(databaseFile, "test123", null);
database.execSQL("create table t1(a, b)");
database.execSQL("insert into t1(a, b) values(?, ?)", new
Object[]{"one for the money",

"two for the show"});

File plaintextFile = getDatabasePath("plaintext.db");
try {
plaintextFile.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
database.execSQL("PRAGMA key = 'test123'");
database.execSQL("ATTACH DATABASE '/data/data/
com.SqlcipherSample/databases/plaintext.db' AS plaintext KEY '';");
database.execSQL("SELECT sqlcipher_export('plaintext'); ");
database.execSQL("DETACH DATABASE plaintext;");
}
}

Nick Parker

unread,
May 4, 2012, 7:41:50 AM5/4/12
to sqlc...@googlegroups.com, chen li
Hi Chen,

You shouldn't need to call createNewFile() on the File provided from
getDatabasePath(...). We have a couple of examples attaching both an
existing database as well as attaching with a non-existent database
[1][2]. Also, to use the sqlcipher_export convenience function, you
would need to upgrade your libraries from the 1.1 version you are using
to the 2.0, currently RC5. You can get those binaries here [3].


1.
https://github.com/sqlcipher/sqlcipher-android-tests/blob/master/src/main/java/net/zetetic/tests/AttachExistingDatabaseTest.java
2.
https://github.com/sqlcipher/sqlcipher-android-tests/blob/master/src/main/java/net/zetetic/tests/AttachNewDatabaseTest.java
3.
https://github.com/downloads/sqlcipher/android-database-sqlcipher/SQLCipher%20for%20Android%202.0.0-RC5.zip
--
Nick Parker

chen li

unread,
May 4, 2012, 7:39:50 PM5/4/12
to SQLCipher Users
So Great, Nick, you are wonderful!!

i follow what you said, and it works. I will try some big sqlite
legacy database (>1mb) for our development. any good suggestions?

BTW, below is my code:

~~~~~~~~~~~~~~~~~~~~~

package com.SqlcipherSample;

import java.io.File;
import java.io.IOException;

import net.sqlcipher.database.SQLiteDatabase;

import android.app.Activity;
import android.os.Bundle;

public class main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
InitializeSQLCipher();
}

private void InitializeSQLCipher() {
SQLiteDatabase.loadLibs(this);
File databaseFile = getDatabasePath("demo.db");
databaseFile.mkdirs();
databaseFile.delete();
SQLiteDatabase database =
SQLiteDatabase.openOrCreateDatabase(databaseFile, "test123", null);
database.execSQL("create table t1(a, b)");
database.execSQL("insert into t1(a, b) values(?, ?)", new
Object[]{"one for the money",

"two for the show"});
/*
File plaintextFile = getDatabasePath("plaintext.db");
try {
plaintextFile.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
database.execSQL("PRAGMA key = 'test123'");
database.execSQL("ATTACH DATABASE '/data/data/
com.SqlcipherSample/databases/plaintext.db' AS plaintext KEY '';");
database.rawQuery("SELECT sqlcipher_export('plaintext');",
null);
> 1.https://github.com/sqlcipher/sqlcipher-android-tests/blob/master/src/...
> 2.https://github.com/sqlcipher/sqlcipher-android-tests/blob/master/src/...
> 3.https://github.com/downloads/sqlcipher/android-database-sqlcipher/SQL...

chen li

unread,
May 4, 2012, 8:28:09 PM5/4/12
to SQLCipher Users
Problems again...

Above, i had successfully migrate a new created encrypted database to
non-encryted database.

but when i tried migrating a legacy sqlite to encrypted, it shows no
errors, but the new db file is 0 byte...

is there any problems, please?

below is my code:

~~~~~~~~~~~~~~~~~~~~~~~

private void create(Context c){
//db=null;
try
{
String dirName="/data/data/"+c.getPackageName() + "/";//
getString(R.string.DATABASE_PATH);
String databaseFileName = "1.db"; // the existing sqlite,
400k
if (!sDatabaseFileName.equals("")){
databaseFileName = sDatabaseFileName;
}
sDatabaseFileName = databaseFileName;
File dbFile = c.getDatabasePath(databaseFileName);
String fullDBName = dbFile.getAbsolutePath();
if(!dbFile.exists()){
dbFile.createNewFile();

InputStream is =
c.getResources().openRawResource(R.raw.laiqian);
FileOutputStream fos = new FileOutputStream(fullDBName);
byte[] buffer = new byte[8192];
int count=0;
while((count=is.read(buffer))>0)
{
fos.write(buffer,0,count);
}
fos.close();
is.close();
}

//SQLiteDatabase.loadLibs(c);
db = SQLiteDatabase.openOrCreateDatabase(fullDBName,"",null);
//db.rawExecSQL("PRAGMA key = ''");
Cursor c1 = db.rawQuery("SELECT count(*) FROM t_string;", null);
c1.moveToFirst();
Toast.makeText(c, c1.getString(0), Toast.LENGTH_SHORT).show();//
it works
//move it to a new encrypted database
//db.execSQL("PRAGMA key = ''");
File newDatabasePath = c.getDatabasePath("encryted.db");
//db.rawExecSQL("pragma cipher_default_use_hmac = off");
db.execSQL("PRAGMA key = '';");
db.execSQL("ATTACH DATABASE '"+newDatabasePath.getAbsolutePath()
+"' AS encrypt1 KEY '123456';");
db.rawQuery("SELECT sqlcipher_export('encrypt1');", null);
db.execSQL("DETACH DATABASE encrypt1;");
}
catch (Exception e){
e.printStackTrace();

Georgie Casey

unread,
May 5, 2012, 3:17:44 PM5/5/12
to SQLCipher Users
Chen,

You're getting pretty good, quick, and *free* support already so I
wouldn't double post because you didn't get a reply within 3 hours.

I didn't go through all your code, it looks like it was copied and
pasted from various corner of the Internet. But I do see straightaway
that you attach a database called 'encryted.db' then try and export a
database called 'encrypt1' so fix that first of all and come back with
the inevitable errors. And you've a catch in your code so your code
won't crash but there should be something in your LogCat, copy that
here as well if you want help.

Georgie

Nick Parker

unread,
May 8, 2012, 9:02:56 AM5/8/12
to sqlc...@googlegroups.com, chen li
Hi Chen,

Since you are now using the 2.0 RC version of the libraries, we have
included a class method off the SQLiteDatabase class called
upgradeDatabaseFormatFromVersion1To2, you should consider using that to
perform a migration to a new encrypted database. If you choose not to
do so, you may consider calling rawExecSQL when executing the
sqlcipher_export convenience method. This will keep certain SQL queries
from bubbling up an exception when sqlite3_step does not return
SQLITE_ROW. Finally can you confirm that your source database contains
data to migrate before the upgrade process. Thanks!
--
Nick Parker
Reply all
Reply to author
Forward
0 new messages