40

我有一个与服务器通信的应用程序。当用户登录到应用程序时,会在服务器上创建一个身份验证令牌并存储在SharedPreferences应用程序中,并且每当应用程序从 Web 服务请求数据时,身份验证令牌就会被验证。

我的问题是,将身份验证令牌存储在 中是否安全SharedPreferences?我问是因为具有 root 权限的用户可以访问首选项、提取令牌并使用它。

无论如何在这方面有更多的安全性吗?

4

3 回答 3

49

简而言之,是的,这是一件完全合理的事情。

除此之外,您能做的最好的事情就是混淆。如果您将令牌保存在内存中,root 用户可以查看它。如果您对其进行加密,您还必须将加密密钥存储在设备上,否则您将无法使用令牌……并且密钥可以像令牌一样容易被盗。

如果有人在设备上拥有 root 权限,则所有赌注都将取消。不要针对这种情况进行优化。如果你的应用是超级安全的,不要让它在有根设备上运行,或者实现远程擦除功能,用户可以报告他们的设备被盗,你可以使服务器上的令牌失效。

Android 4.3 引入了Android Keystore。据称,这为加密密钥提供了安全存储。这可用于存储用于解密以传统方法存储的加密令牌的密钥。但是,引用的链接没有提到 root 设备如何影响其安全性。

2018 年更新:大多数现代 Android 设备都有硬件支持的密钥库,通过 SoC 提供的可信执行环境 (TEE)。这使得黑客无法(见下文)获得密钥库主密钥,否则需要解密您存储在 Android 密钥库中的密钥。

好吧,“不可能”是一个强有力的词。最好说“不可行”。这意味着,您需要像电子显微镜这样的东西来扫描融合到提供 TEE 的 SoC 中的位。如果你是那种数据值得关注的人,你可能会遇到更大的问题。

于 2013-10-29T21:40:54.807 回答
3

现在有一种更简单、更快捷的方法来加密数据,因为有一个 SharedPreferences 的实现可以加密键和值。您可以在 Android JetPack Security 中使用 EncryptedSharedPreferences。

只需将 AndroidX Security 添加到您的 build.gradle 中:

implementation 'androidx.security:security-crypto:1.0.0-rc01'

你可以像这样使用它:

String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);

SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
    "secret_shared_prefs",
    masterKeyAlias,
    context,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);

// use the shared preferences and editor as you normally would
SharedPreferences.Editor editor = sharedPreferences.edit();

查看更多详细信息:https ://android-developers.googleblog.com/2020/02/data-encryption-on-android-with-jetpack.html

官方文档:https ://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences

于 2021-02-18T05:23:54.347 回答
2

如果担心令牌可以从 SharedPreferences 中读取,一个好的经验法则是对正在存储的数据提供一定程度的混淆。

此响应概述了一个简单的类来混淆 SharedPreferences 数据: 在 Android 应用程序中存储用户设置的最合适的方法是什么

于 2013-10-29T21:42:59.143 回答