AndroidX DataStore 1.3.0-alpha07 新特性:给你的 DataStore 加上加密
背景
说到我的老朋友 EncryptedSharedPreferences,我都快忘了这号人物了😅
和大多数 Android 开发者一样,我和 EncryptedSharedPreferences 的纠葛可太复杂了:这个库刚出来的时候大家一片叫好,纷纷上手用,结果后来更新越来越少,官方也没个准信,慢慢就凉了,用的人一肚子火,更新完全停摆。
等了快一个世纪,最近的更新终于给了个准信——这个库正式废弃了。但这下更多开发者懵了:那这玩意儿之后用啥替代啊?总不能没得用吧?
🔗 延伸阅读:《守护未来:梳理 EncryptedSharedPreferences 废弃后的替代方案》
(原发布于 proandroiddev.com,讨论 EncryptedSharedPreferences 废弃对应用安全的影响)
这篇文章我们就来聊聊这个意料之外的新进展:AndroidX DataStore 1.3.0-alpha07 竟然加了官方加密支持!
新特性解析:怎么有种似曾相识的感觉?
按照 AndroidX 的常规发布节奏,DataStore 1.3.0-alpha07 于2026年4月11日发布,发布说明里有这么一条值得重点关注:
加密支持:新增 androidx.datastore:datastore-tink 构件,支持通过 Tink 加密库为 DataStore 提供加密能力
为了节省篇幅,我默认大家已经了解 DataStore 的基本用法,如果还不熟悉可以先去官方文档补补课。
新的 androidx.datastore:datastore-tink 依赖提供了 AeadSerializer 类,它是对现有负责读写操作的 Serializer 实例的一层封装:
- 写入数据时,
AeadSerializer 会先用 Tink 的 Aead (后面会详细讲)加密明文数据,再把加密后的密文字节传给原有 Serializer 处理。 - 读取数据时,
AeadSerializer 会用同一个 Aead 把从封装的 Serializer 读到的密文字节解密回原始明文。
下面的示例代码直接来自官方发布说明,是当前第一个alpha版本的最小使用示例¹:
val keysetHandle =
AndroidKeysetManager.Builder()
.withSharedPref(applicationContext, "keyset", "keyset_prefs")
.withKeyTemplate(KeyTemplate.createFrom(PredefinedAeadParameters.AES256_GCM))
.withMasterKeyUri("android-keystore://master_key")
.build()
.keysetHandle
val aeadSerializer = AeadSerializer(
aead =
keysetHandle.getPrimitive(
RegistryConfiguration.get(),
Aead::class.java,
),
wrappedSerializer = SomeExistingSerializer,
associatedData ="settings.json".encodeToByteArray(),
)
val dataStore = dataStore(
fileName ="settings.json",
serializer = aeadSerializer,
scope = scope,
)
那这套机制到底是怎么运行的?🧐 底层的加密能力是通过 Tink 的带关联数据的认证加密(Authenticated Encryption with Associated Data,简称AEAD)原语实现的,这是行业广泛采用的标准方案,能在一次操作中同时完成加密和完整性校验。
简单来说,这个方案非常适合这个场景:AEAD 不仅能保证数据的保密性,还能确保加密内容本身以及相关的未加密元数据(也就是我们说的「关联数据」)都没有被篡改。它会生成一个「认证标签」,这个标签和密文、关联数据都是密码学绑定的,解密前会先校验完整性,如果输入的任何部分被篡改过,校验就会失败,就会认为数据已经被篡改。
当然这里我做了非常多的简化²,EncryptedSharedPreferences 底层也是用的 Tink,包括 Aead,结果后来 Tink 版本更新几年都更不动,最后直接沦落成了无人维护的弃坑项目。
你肯定要问:那这次有啥不一样啊? 问得好!
为什么要做这个加密库?
首先要提醒大家,这只是这个功能的第一个alpha版本,所以现在还有很多悬而未决的问题,后续应该会慢慢明朗。
现在最核心的问题是:这个功能的官方定位到底是给什么场景用的?我之前在金融科技公司做开发的时候,用过 EncryptedSharedPreferences 来满足合规要求,我个人能想到的「合理」场景也就这么几类。我还挺好奇 AndroidX 团队觉得这个库适合用在什么地方的😎
还有个值得一提的事:在 Google 的问题跟踪器上,要求给 DataStore 加加密功能的需求帖拿了950个+1,是 DataStore 相关需求里得票最高的,而且甩开第二名一大截。不过转念一想,这个需求提了5年半才搞定,好像也就没那么厉害了🙃
那这个功能适合我吗?🫣
长话短说:大概率不适合。
从 Android 10 开始,系统层面就强制启用了文件级加密,而且 Android 的应用沙箱机制也保证了正常情况下,应用之间是没法互相访问对方的文件的,包括 DataStore、SharedPreferences 这些存储的内容。所以要想拿到这些文件,基本得靠极端手段:比如物理拿到设备、root 设备、或者设备里有恶意软件。这类攻击的难度非常高,除非你做的是高风险应用,对安全要求到了吹毛求疵的地步,不然给 DataStore 内容加密完全是小题大做,根本没必要。
当然,肯定有人会反驳说「这总能提升我应用的整体安全性吧」,乍一听好像挺有道理。
但就像当年的 EncryptedSharedPreferences 一样,我对这类加密持久化 API 最大的顾虑还是:它们的存在反而会误导那些对移动安全一知半解的开发者,让他们觉得「反正加密了,存敏感数据也没事」,而不是去想「这个数据到底该不该存在本地」。
求求你们,真的别再把敏感数据存在本地了 🙏
—— 我,逢人就说这句话
按理说大家都懂:只要有可能,绝对不要在本地存储敏感数据。所以推出这种让违反这个原则变得轻而易举的 API,(至少在我看来)是走了弯路。尤其是如果这些 API 配套的文档根本没告诉开发者存敏感数据有什么风险的话,问题就更严重了。
当年的 EncryptedSharedPreferences 就是这么干的,至于 androidx.datastore:datastore-tink 会不会重蹈覆辙,我们走着瞧😬
总结
虽然我对这个新 API 的态度看起来有点悲观,但我也知道现在还在早期阶段,后续完全有可能发生天翻地覆的变化。
对一部分开发者来说,这个新功能绝对是天大的好消息:EncryptedSharedPreferences 废弃后留下的空白,终于有官方维护的替代方案了。
但我也希望 AndroidX 团队能抓住这个机会:不仅要给那少数确实需要加密 DataStore 数据的合法场景提供支持,更要花大力气写好文档,告诉绝大多数开发者什么时候不该用这个功能。
说到这里,我想起一句名言,刚好能完美概括我现在的想法:
忘记历史的人注定要重蹈覆辙
—— 乔治·桑塔亚纳,《理性的生活》,1905
相信这次会是个好的改变,大家也肯定从 EncryptedSharedPreferences 的坑里吸取了教训。不过说归说,到底怎么样,还是得时间来证明🤞
你们打算用 androidx.datastore:datastore-tink 做什么?欢迎留言分享~
脚注
[1] 此API仍处于早期阶段,可能发生重大变更,请查阅官方发布说明获取最新文档。
[2] 想要深入了解AEAD,可以看 Adolfo Ochagavía 写的这篇很棒的博客 ✨
原文链接:https://sp4ghetticode.medium.com/whats-new-in-androidx-datastore-1-3-0-alpha07-encrypt-your-datastore-25ca02b0b0e7