2012-08-14 120 views
2

我有一個數據庫,其中包含只能由我的應用程序訪問的私人信息。我在資產文件夾中添加了我的數據庫文件,該文件夾在第一次運行應用程序時被複制到應用程序數據庫目錄,但「資產」目錄和「數據」目錄(在根設備上)可以被任何其他應用程序訪問因此,我決定加密數據庫。 Android默認SQLite數據庫不提供數據加密,所以我決定使用SQLCipher for android​​。如何在Android上保護數據庫(加密)密碼?

現在我已成功加密數據庫,並且可以使用特定密碼訪問它。但問題仍然存在......我應該在哪裏存儲此密碼?以便它只能被我的應用程序訪問。

  1. 無法對其進行硬編碼,因爲即使它被模糊處理,也無法對其進行編碼。
  2. 不能將其存儲在文件系統是(資產/ RAW)
  3. 不能要求用戶輸入其作爲用戶可能被黑客

它是獨立的應用程序沒有服務器互動在所有

+1

如果您看到用戶爲攻擊者,你不能相信在客戶端上的任何東西。就那麼簡單。你可以在這個問題上投入大量的混淆,然後希望沒人會打擾它。 – CodesInChaos 2012-08-14 20:42:48

+0

爲什麼沒有服務器交互?除非你真的有充分的理由不這樣做,否則你應該使用服務器來存儲我認爲的密鑰。 – Entreco 2012-08-14 21:08:29

回答

5

Can't ask the user to enter it as the user could be a hacker然後你沒有辦法安全地存儲它。出於同樣的原因,您已經確定,特別是您的代碼可以被反編譯,您存儲它的任何可訪問的地方都可以通過反編譯來找到,因此可以通過具有正確訪問權限的任何代碼進行檢索。

用戶提供的東西存儲在用戶存儲的任何地方 - 大概在他或她的頭上。這不是軟件可以訪問的內容,因此非常適合降低惡意軟件攻擊的風險。如果輸入的密碼有效,則無法知道用戶是否被授權,但您可以定義策略,例如最小密鑰長度,最大輸入嘗試次數(在引入延遲或其他鎖定之前)等等。

2

我不知道這個答案的精確程度,但仍張貼,因爲我想從Android的愛好者

一些響應考慮到C代碼是很難反編譯,我寫(的.so)使用一個簡單的本地C庫Android NDK包含一個算法來生成密碼。該算法僅在應用程序由我的證書籤名時纔會執行。如果有人在任何其他應用程序中重新使用此庫,則不會返回密碼,因爲證書不匹配。我有這個想法,從這個帖子: http://digital-identity.dk/2010/12/protecting-ip-in-android-applications/

這是我拿到證書:

void Java_dk_digitalidetity_android_SomeClass_SomeMethod(JNIEnv* env, jobject obj) { 
    // this.getPackageManager() 
    jclass cls = (*env)->GetObjectClass(env, obj); 
    jmethodID mid = (*env)->GetMethodID(env, cls, "getPackageManager", "()Landroid/content/pm/PackageManager;"); 
    jobject packageManager = (*env)->CallObjectMethod(env, obj, mid); 

    // this.getPackageName() 
    mid = (*env)->GetMethodID(env, cls, "getPackageName", "()Ljava/lang/String;"); 
    jstring packageName = (jstring) (*env)->CallObjectMethod(env, obj, mid); 

    // packageManager->getPackageInfo(packageName, GET_SIGNATURES); 
    cls = (*env)->GetObjectClass(env, packageManager); 
    mid = (*env)->GetMethodID(env, cls, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;"); 
    jint flags = GET_SIGNATURES; 
    jobject packageInfo = (*env)->CallObjectMethod(env, packageManager, mid, packageName, flags); 

    // packageInfo->signatures 
    cls = (*env)->GetObjectClass(env, packageInfo); 
    jfieldID fid = (*env)->GetFieldID(env, cls, "signatures", "[Landroid/content/pm/Signature;"); 
    jobject signatures = (*env)->GetObjectField(env, packageInfo, fid); 

// signatures[0] 
    jobject signature = (*env)->GetObjectArrayElement(env, signatures, 0); 

// signature->toByteArray() 
    cls = (*env)->GetObjectClass(env, signature); 
    mid = (*env)->GetMethodID(env, cls, "toByteArray", "()[B"); 
    jbytearray certificate = (*env)->CallObjectMethod(env, signature, mid); 
} 
+0

某些人認爲共享對象中的代碼更容易受到攻擊,因爲調試器可讓您輕鬆實現場景。這可以通過編寫一個純粹的C程序來連接並調用您的共享代碼,反彙編它,以及對代碼進行實時更改。一旦識別出正確的變化,二進制文件就可以被黑客入侵,並且由於Android在精靈圖像上沒有簽名,攻擊者(具有正確的能力)所需克服的障礙更少。只有一個成功的攻擊者才能打破這個計劃。 – mah 2012-09-27 11:40:09

+0

C共享對象的內部檢查內容與應用程序的簽名相匹配。如果其他人稱它永遠不會觸及敏感代碼。一個人如何調試那些永遠不會執行的代碼? – Saqib 2012-09-28 19:13:52

+0

你說的是你的apk的簽名,我說的是libXXX.so原生擴展名是無符號的。安裝應用程序時,其本機庫將被解壓縮到文件系統,並且永遠不會再次引用到apk內。關於apk簽名檢查雖然 - 可以修改.so的人同樣可以修改它來禁用apk簽名檢查,並且由於此代碼可能會通過JNI接口返回到VM中,因此定位相對比較容易。 – mah 2012-09-28 19:36:01