【轉】使用SQLCipher進行加解密

來源:互聯網
上載者:User

標籤:

我們都知道,Android系統內建了SQLite資料庫,並且提供了一整套的API用於對資料庫進行增刪改查操作。資料庫儲存是我們經常會使用到的一種儲存方式,相信大多數朋友對它的使用方法都已經比較熟悉了吧。在Android中,我們既可以使用原生的SQL語句來對資料進行操作,也可以使用Android API提供的CRUD方法來對資料庫進行操作,兩種方式各有特點,選擇使用哪一種就全憑個人喜好了。

不過,使用SQLite來儲存資料卻存在著一個問題。因為大多數的Android手機都是Root過的,而Root過的手機都可以進入到/data/data/<package_name>/databases目錄下面,在這裡就可以查看到資料庫中儲存的所有資料。如果是一般的資料還好,但是當涉及到一些帳號密碼,或者聊天內容的時候,我們的程式就會面臨嚴重的安全性漏洞隱患。那麼今天,就讓我們一起研究一下如何藉助SQLCipher來解決這個安全性問題。

SQLCipher是一個在SQLite基礎之上進行擴充的開來源資料庫,它主要是在SQLite的基礎之上增加了資料加密功能,如果我們在項目中使用它來儲存資料的話,就可以大大提高程式的安全性。SQLCipher支援很多種不同的平台,這裡我們要學習的自然是Android中SQLCipher的用法了。

下面我們就開始吧,首先要把Android項目所依賴的SQLCipher工具包下載下來,是:

https://s3.amazonaws.com/sqlcipher/SQLCipher+for+Android+v2.2.2.zip

接著解壓這個工具包,會看到裡面有assets和libs這兩個目錄,稍後需要將這兩個目錄中的內容添加到Android項目當中。那麼現在我們就來建立一個Android項目,項目名就叫SQLCipherTest。

觀察SQLCipherTest的項目結構,發現裡面也分別有一個assets目錄和一個libs目錄,那麼現在就可以把SQLCipher工具包中這兩個目錄裡的內容複寫過來。並不需要複製全部檔案,選擇必要的檔案進行複製就可以了,完成以後項目結構圖如下所示,圖中顯示的檔案都是必要的。

                    

到這裡準備工作就全部完成了,接下來我們開始編寫代碼。首先建立一個MyDatabaseHelper繼承自SQLiteOpenHelper,注意這裡使用的並不是Android API中的SQLiteOpenHelper,而是net.sqlcipher.database包下的SQLiteOpenHelper,代碼如下所示:

import android.content.Context;  import net.sqlcipher.database.SQLiteDatabase;  import net.sqlcipher.database.SQLiteDatabase.CursorFactory;  import net.sqlcipher.database.SQLiteOpenHelper;    public class MyDatabaseHelper extends SQLiteOpenHelper {            public static final String CREATE_TABLE = "create table Book(name text, pages integer)";        public MyDatabaseHelper(Context context, String name, CursorFactory factory, int version) {          super(context, name, factory, version);      }        @Override      public void onCreate(SQLiteDatabase db) {          db.execSQL(CREATE_TABLE);      }        @Override      public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {        }    }  

除了引入的包不一樣了,其它的用法和傳統的SQLiteOpenHelper都是完全相同的。可以看到,我們在onCreate()方法中建立了一張Book表,Book表裡有name和pages這兩個列。

 

接著,開啟或建立activity_main.xml作為程式的主布局檔案,代碼如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="match_parent"      android:layout_height="match_parent"      android:orientation="vertical" >            <Button           android:id="@+id/add_data"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:text="添加資料"          />            <Button           android:id="@+id/query_data"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:text="查詢資料"          />    </LinearLayout>  

這裡只是簡單地放置了兩個按鈕,分別用於添加和查詢資料。接下來開啟或建立MainActivity作為程式主Activity,代碼如下所示:

public class MainActivity extends Activity {            private SQLiteDatabase db;        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);          SQLiteDatabase.loadLibs(this);          MyDatabaseHelper dbHelper = new MyDatabaseHelper(this, "demo.db", null, 1);          db = dbHelper.getWritableDatabase("secret_key");          Button addData = (Button) findViewById(R.id.add_data);          Button queryData = (Button) findViewById(R.id.query_data);          addData.setOnClickListener(new OnClickListener() {              @Override              public void onClick(View v) {                  ContentValues values = new ContentValues();                  values.put("name", "達芬奇密碼");                  values.put("pages", 566);                  db.insert("Book", null, values);              }          });          queryData.setOnClickListener(new OnClickListener() {              @Override              public void onClick(View v) {                  Cursor cursor = db.query("Book", null, null, null, null, null, null);                  if (cursor != null) {                      while (cursor.moveToNext()) {                          String name = cursor.getString(cursor.getColumnIndex("name"));                          int pages = cursor.getInt(cursor.getColumnIndex("pages"));                          Log.d("TAG", "book name is " + name);                          Log.d("TAG", "book pages is " + pages);                      }                  }                  cursor.close();              }          });      }    }  

可以看到,在onCreate()方法中首先調用了SQLiteDatabase的loadLibs()靜態方法將SQLCipher所依賴的so庫載入進來,注意這裡使用的是net.sqlcipher.database包下的SQLiteDatabase。然後我們建立了MyDatabaseHelper的執行個體,並調用getWritableDatabase()方法去擷取SQLiteDatabase對象。這裡在調用getWritableDatabase()方法的時候傳入了一個字串參數,它就是SQLCipher所依賴的key,在對資料庫進行加解密的時候SQLCipher都將使用這裡指定的key。

 

在添加資料按鈕的點擊事件裡面,我們通過ContentValues構建了一條資料,然後調用SQLiteDatabase的insert()方法將這條資料插入到Book表中。

在查詢資料按鈕的點擊事件裡面,我們調用SQLiteDatabase的query()方法來查詢Book表中的資料,查詢到的結果會存放在Cursor對象中,注意這裡使用的是net.sqlcipher包下的Cursor。然後對Cursor對象進行遍曆,並將查詢到的結果列印出來。

現在運行一下程式,先點擊添加資料按鈕,再點擊查詢資料按鈕,剛剛添加的那條資料就應該在控制台裡列印出來了。

有沒有感覺到使用SQLCipher提供的API和使用Android原生的資料庫API,操作起來幾乎是一模一樣的。沒錯,SQLCipher對Android SDK中所有與資料庫相關的API都製作了一份鏡像,使得開發人員可以像操作普遍的資料庫檔案一樣來操作SQLCipher,而所有的資料加解密操作,SQLCipher都在背後幫我們處理好了。

話說寫到這裡,我們都一直還沒體驗一下SQLCipher加密後的效果呢,現在就來看一看吧,首先通過命令列的方式來訪問demo.db這個資料庫檔案:

adb shell  cd /data/data/com.example.sqlciphertest/databases  sqlite3 -line demo.db  .table  

嘗試查看demo.db中的所有表,結果返回如所示:

  

可以看出,當執行.table命令的時候被拒絕了,原因是資料庫檔案已加密。

除了使用命令列的方式,我們還可以嘗試使用Root Explorer來開啟資料庫檔案,結果如所示:

                                        

意料之中,果然開啟失敗了。這就足以說明,目前資料庫中的資料是非常安全的,只有在應用程式裡通過SQLCipher提供的API才可以訪問到資料庫裡的資料,使用其它的方式都無法擷取其資料。

需要提醒的一點是,項目中引入了SQLCipher之後,會讓你的程式體積驟然增加,打成APK後大概會變大好幾M,是更側重於檔案大小,還是更側重於程式安全,你應該根據具體的需求做出合適的判斷。

【轉】使用SQLCipher進行加解密

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.