如何在SQLCipher中进行加密/解密

3

我正在研究如何使用SQLCipher加密/解密数据库。

在我的代码中,我应该从哪里开始?如何开始?

如果可能的话,请编辑此代码。

我按照此链接进行操作,但不知道如何操作。 http://sqlcipher.net/sqlcipher-api/#key

我的数据库文件:

import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteOpenHelper;
import android.content.Context;
import android.util.Log;

public class DatabaseClass extends SQLiteOpenHelper 
{
    /**
     * Constants 
     */
    public final static String DATABASE_NAME ="mycipherdatabase.db";
    public final static String NAME ="name";
    public final static String ADDRESS ="address";
    public final static String CITY ="city";

    public static String pass = "1234";
    public DatabaseClass(Context context) {
        super(context, DATABASE_NAME, null, 1);
    }

    /**
     * called once
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL( "CREATE TABLE mylistdata(_id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT, address TEXT,city TEXT);");

        Log.v("inside", "oncreate");
    }

    /**
     * called when we upgrade(change)the version number of database
     * onCreate also called after changing the version
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP Table mylistdata");
        onCreate(db);
    }
}

使用此数据库的其他活动:

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

        SQLiteDatabase.loadLibs(this);
        File file = getDatabasePath(DatabaseClass.DATABASE_NAME);
        file.mkdir();
        file.delete();
        sqldb = SQLiteDatabase.openOrCreateDatabase(file,key, null);
        db = new DatabaseClass(this);

        etname = (EditText)findViewById(R.id.name);
        etadd = (EditText)findViewById(R.id.add);
        etcity = (EditText)findViewById(R.id.city);
        result = (ListView)findViewById(R.id.mylist);
    }

    /**
     *insert data in to database 
     */
    public void saveData(View v) {
        ContentValues insertData = new ContentValues();
        insertData.put(DatabaseClass.NAME, etname.getText().toString());
        insertData.put(DatabaseClass.ADDRESS, etadd.getText().toString());
        insertData.put(DatabaseClass.CITY, etcity.getText().toString());

        db.getWritableDatabase(key).insert("mylistdata", DatabaseClass.NAME , insertData);
        db.close();

        resetEditText();
        Toast.makeText(this,"Data saved", Toast.LENGTH_SHORT).show();
    }
3个回答

4
好的,代码存在很多问题,我认为您需要更好地了解Android中SQLite的结构。从技术上讲,Android SQLiteSQLCipher 看起来完全相同(除了密码)。因此,如果您编写一个标准的SQLite应用程序,可以很容易地转换为SQLCipher。
我建议您阅读这篇关于Android中SQLite的精美文章: http://www.vogella.com/articles/AndroidSQLite/article.html 提示:使用SQLiteOpenHelper时无需调用openOrCreateDatabase,调用getWritableDatabase就可以完成工作。此外,您必须拥有一个从getWritableDatabase方法获得的SQLiteDatabase对象,每次插入记录时都调用getWritableDatabase是不正确的。
其中的这些部分将被删除。
     // in onCreate method
     File file = getDatabasePath(DatabaseClass.DATABASE_NAME);
     file.mkdir();
     file.delete();
     sqldb = SQLiteDatabase.openOrCreateDatabase(file,key, null);
     db = new DatabaseClass(this);

     // in saveData method
      db.getWritableDatabase(key).insert("mylistdata", DatabaseClass.NAME ,               insertData);

相反,您必须执行以下操作:
     // in onCreate method
     try{
        sqldb = new DatabaseClass(this).getWritableDatabase(key);
     }catch(Throwable e){
        // error occurred
     }

     // in insert action
     try{
        sqldb.insert("tablename", null, contentValues);
     }catch(Throwable e){
        // error occurred
     }

这样你也可以看到是否发生了错误,记住,在捕获异常时不要使用Exception类,只使用Throwable

另外,我不建议在每个插入操作中关闭连接,最好由更高级别的代码来处理。


我不确定为什么你建议捕获Throwable而不是Exception。另一个Throwable子类(即Error)的javadoc表示,捕获错误是不合理的:http://docs.oracle.com/javase/6/docs/api/java/lang/Error.html - James Baxter
2
我们有两种Throwables,Exceptions和Errors。有时候SQLCipher会返回错误(如果缺少任何库),而不是异常。为了捕获它,您应该在catch语句中使用Throwable。即使应该在多个级别上处理它,但您应该始终记住将您的sqlcipher命令编写在Throwable catch中,以避免您的应用程序崩溃。https://dev59.com/lnE95IYBdhLWcg3wheRR - Hossein Shahdoost

1

这里的 file.mkdir 和 file.delete 是必须使用的,它们能做什么?我编辑了我的代码,请帮我审查一下,我现在的操作是正确的吗? - Monty

0

谢谢你的回复,Sean。我想我正在使用你发布的这些内容……我正在通过getWritableDatabase(pass)传递一个密钥……这是加密吗? - Monty
我没有看到你使用onConfigure方法并设置Pragmas。 - Sean McCully
好的Sean,你的意思是在onConfig()函数里面,我需要执行db.rawQuery("PRAGMA key "+some key+";");语句,对吗? - Monty
哦,我不知道,我只是从文档和我的知识中推断出来的。我没有特别做过这个。但是是的,你需要沿着这些方向做一些事情。 - Sean McCully
抱歉再次提醒,@Unknown,你已经解决了执行PRAGMA key命令的问题了吗?谢谢,我也需要它。 - Razgriz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接