如何安全存储访问令牌和机密在 Android?

我将使用 oAuth 从谷歌获取邮件和联系人。我不想要求用户每次登录获得访问令牌和机密。根据我的理解,我需要将它们与我的应用程序一起存储在数据库或 SharedPreferences中。但我有点担心安全方面的问题。我知道你可以加密和解密令牌,但是攻击者很容易反编译你的 apk 和类并获得加密密钥。
在 Android 中安全存储这些令牌的最佳方法是什么?

90804 次浏览

存储为 共同的喜好。这些都是默认私有的,其他应用程序无法访问它们。在有根设备上,如果用户明确允许访问某个试图读取它们的应用程序,该应用程序可能会使用它们,但您无法防止这种情况发生。对于加密,您必须要求用户每次都输入解密密码(因此无法实现缓存凭据的目的) ,或者将密钥保存到一个文件中,这样就会遇到同样的问题。

存储令牌而不是实际的用户名密码有一些好处:

  • 第三方应用程序不需要知道密码,用户可以确定他们只将密码发送到原始网站(Facebook、 Twitter、 Gmail 等)
  • 即使有人偷了一个令牌,他们也看不到密码(用户可能在其他网站上也使用这个密码)
  • 令牌通常有一个生命周期,并在一定时间后过期
  • 如果您怀疑令牌已被泄露,则可以撤消令牌

你可以把它们存储在 会计经理中,这是这些家伙认为的最佳实践。

enter image description here

以下是官方定义:

此类提供对用户的 用户输入凭据(用户名和密码) 每个帐户一次,允许应用程序访问联机资源 一键通过。

有关如何使用 AccountManager 的详细指南:

但是,AccountManager 最终只将令牌存储为纯文本。所以,我建议在存储到 AccountManager 之前先加密你的秘密。您可以利用各种加密库,如 超级密码AESCypto

另一种选择是使用 藏书室。它对 Facebook 来说足够安全,而且比 AccountManager 更容易使用。下面是使用 Conceal 保存秘密文件的代码片段。

byte[] cipherText = crypto.encrypt(plainText);
byte[] plainText = crypto.decrypt(cipherText);

不是本身是一个安全的位置。在有根设备上,我们可以轻松地读取和修改所有应用程序的 SharedPreferecesxml 的。因此令牌应该相对频繁地过期。但是,即使一个令牌每小时过期一次,仍然可以从 SharedPreferences 中窃取更新的令牌。Android KeyStore 应该用于长期存储和检索加密密钥,这些密钥将用于加密我们的令牌,以便将它们存储在 SharedPreferences 或数据库中。密钥不存储在应用程序的进程中,因此它们 更难将被破坏。

因此,比一个地方更重要的是它们如何能够自身安全,例如使用加密签名的短期 JWT,使用 Android KeyStore 对它们进行加密,并使用安全协议发送它们

正如这个问题的最新更新一样,您现在可以使用 加密的共享首选项安全地存储数据。除了您还需要生成 MasterKey 之外,该接口非常类似。

EncryptedSharedPreferences 的大多数文档都使用 MasterKeys.getOrCreate (MasterKeys.AES256 _ GCM _ SPEC,但是这种方法似乎不受欢迎,而倾向于使用 万能钥匙,建造者

private var masterKeyAlias = MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()


private val preferences = EncryptedSharedPreferences.create(
context,
"auth_token_secured",
masterKeyAlias,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)


var authToken: String?
get() = preferences.getString("auth_token", "")
set(value) = preferences.edit().putString("auth_token", value).apply()