如何在Android上保护数据库(加密)密码?

时间:2012-08-14 20:34:53

标签: android database security password-protection

我有一个包含私人信息的数据库,只能由我的应用程序访问。我在assets文件夹中添加了我的数据库文件,该文件夹在应用程序第一次运行时被复制到应用程序数据库目录,但是“assets”目录和“data”目录(在root设备上)可以被任何其他应用程序访问所以我决定加密数据库。 Android默认的SQLite数据库不提供数据加密,所以我决定使用SQLCipher for android http://sqlcipher.net/sqlcipher-for-android/

现在我已成功加密数据库,我可以使用特定密码访问它。但问题仍然存在......我应该在哪里存储这个密码?这样它只能被我的应用程序访问。

  1. 无法对其进行硬编码,因为即使对其进行模糊处理,它也可以在反编译后访问。
  2. 无法将其存储在文件系统中(assets / raw)
  3. 无法要求用户输入,因为用户可能是黑客
  4. 它是独立的应用程序,完全没有服务器交互

2 个答案:

答案 0 :(得分:5)

Can't ask the user to enter it as the user could be a hacker然后你无法安全地存储它。由于您已经确定的相同原因,特别是您的代码可以被反编译,您存储的任何可访问的地方都可以通过反编译找出,因此可以通过任何具有正确访问权限的代码进行检索。

用户提供的东西存储在用户存储的任何地方 - 可能是在他或她的头脑中。这不是软件可以访问的,这使其成为降低恶意软件攻击风险的理想选择。如果输入的密码有效,您无法知道用户是否被授权,但是您可以定义策略,例如最小密钥长度,最大入口尝试次数(在引入一些延迟或其他锁定之前)等等

答案 1 :(得分:2)

我不确定这个答案有多准确,但仍然发布,因为我想得到Android极客们的回应

考虑到C代码难以反编译,我使用Android NDK编写了一个简单的本机C库(.so),其中包含生成密码的算法。该算法仅在应用程序由我的证书签名时执行。如果有人在任何其他应用程序中重新使用此库,它将不会返回密码,因为证书将不匹配。我从这篇文章中得到了这个想法: 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);
}