博客
如何创建 Android Keystore(分步指南)
发布日期: 更新日期: 阅读约 7 分钟
什么是 Android keystore?为什么需要它?
Keystore 是一个加密文件,保存着用于签署应用的公私钥对。Google Play 要求你上传的每个 AAB 都携带有效签名;未签名或签名错误的软件包会在上传时被 Play Console 拒绝。
Flutter 和 Android Studio 会为本地开发自动生成一个"debug keystore";它使用固定密码,仅用于在你自己的设备上测试,任何应用商店都不接受它。你上传到商店的软件包必须使用你自己生成的"release"或"upload" keystore 签名。
同一应用的每一次后续更新都必须使用相同的密钥(或 Google 认可的签名链)签名;否则 Play Console 会以"签名证书不同"为由拒绝更新,迫使用户卸载后重新安装。这使得你的 keystore 文件成为应用身份中永久不可分割的一部分。
使用 keytool 生成 keystore
keytool 是随 Java Development Kit(JDK)一同提供的命令行工具;由于你的 Flutter 或 Android Studio 安装已经自带 JDK,通常无需单独安装。Flutter 官方文档推荐的标准命令是:keytool -genkey -v -keystore upload-keystore.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias upload。这里的 -storetype JKS 参数很重要:自 Java 9 起,keytool 的默认存储类型是 PKCS12,如果不加这个参数,生成的文件虽然扩展名是 .jks,实际内容却是 PKCS12 格式。
-keyalg RSA -keysize 2048 用于设置密钥算法与长度,-validity 10000 使密钥保持约 27 年有效期,-alias upload 则是你为密钥指定的简短名称,后续会在 key.properties 中复用。运行该命令时,系统会依次提示输入 store 密码、key 密码以及你的姓名/组织信息。
在 macOS 和 Linux 上,只要 JDK 已加入 PATH,keytool 就可以直接从终端运行。在 Windows 上,请先运行 flutter doctor -v,查看输出中的"Java binary at:"这一行,确认具体使用的是哪个 JDK;keytool 就位于该目录的 bin 文件夹中(如果没有设置 JAVA_HOME,或安装了多个 JDK,直接假设路径是"%JAVA_HOME%\bin\keytool"可能会指向错误的 JDK)。请将 -keystore 参数中的文件路径调整为你自己的用户目录,并记下运行该命令时所在的目录——下一步还会用到这个路径。
接入 key.properties 与 Gradle
在 android/ 目录下创建一个名为 key.properties 的文件,并添加 storePassword、keyPassword、keyAlias 和 storeFile(你的 keystore 文件完整路径)这几行。该文件是明文,直接暴露你的密码,因此绝不能纳入版本控制——第一步就应把 key.properties 这一行加入 .gitignore。
在 android/app/build.gradle.kts(当前的 Kotlin DSL)中读取该文件,并定义一个 signingConfigs.release 代码块,其中 keyAlias、keyPassword、storeFile 和 storePassword 均取自 key.properties。随后在 release 构建类型上赋值 signingConfig = signingConfigs.getByName("release"),这样每个生成的 release 包都会用这个密钥签名。
如果开启了 R8/ProGuard 代码压缩(isMinifyEnabled=true),在上传到商店之前请先在真机上测试已签名的 release 包;一些依赖反射的库会受到压缩影响,只在 release 构建中崩溃。这与签名本身无关,但却是这一步中常被忽略的问题。
Play App Signing:upload key 与 app signing key 的区别
自 2021 年起,Google 要求新应用必须启用 Play App Signing,且不再提供退出选项。该模式下有两个不同的密钥:你用 keytool 生成、用来签署每个 AAB 的"upload key",以及 Google 保存在其自有安全基础设施中、用于对分发给用户的软件包做最终签名的"app signing key"。你本人永远不会看到或持有 app signing key。
如果你丢失了 upload key(文件本身或其密码),但已启用 Play App Signing,仍有解决办法:在 Play Console 中依次进入 Protected with Play > Play Store protection > Manage Play app signing,然后在"Upload Key Certificate"部分发起"Request upload key reset"请求。流程如下:先用 keytool 生成一个新的 upload keystore,再用 keytool -export -rfc -keystore upload-keystore.jks -alias upload -file upload_certificate.pem 命令将证书导出为 PEM 格式,然后把这个 PEM 文件连同说明重置原因的备注一起上传到 Play Console。Google 审核并批准请求后,新的 upload key 即生效;由于真正的签名密钥从未离开过 Google,你应用在商店中的身份、评论和安装量都不受影响。
如果你从未启用过 Play App Signing——这通常是该规定成为强制要求之前发布的旧应用——一旦丢失了你唯一的签名密钥,就再无回旋余地:你将永远无法为该应用上传新的更新。唯一的办法是使用新的 applicationId 重新开一个全新的应用列表,这意味着失去现有的评论、安装量和搜索排名。
安全存储实践
只把 keystore 文件保存在单一本地磁盘上是有风险的:磁盘故障、重新格式化或更换电脑都可能导致文件永久丢失。请至少保留一份加密备份(外置硬盘、加密云存储),并且绝不要把该文件加入项目代码仓库——和 key.properties 一样,keystore 文件也应写入 .gitignore。
将 store 密码和 key 密码保存在密码管理器中,同时记下 alias 名称;缺少这三者中的任何一个,文件本身就毫无用处。切勿通过邮件或聊天工具以明文形式分享密码;如果是团队协作,请只把访问权限开放给真正需要的人。
Vibeloy Keystore 保险库以端到端加密方式存储你的 keystore 文件和密码;你不必只把文件保存为本地单一副本,而是可以将它安全地保存在与账户关联、可从任何设备访问的保险库中。这是 Vibeloy 的高级(premium)功能。
常见问题
- 我丢失了 keystore 文件,该怎么办?
- 如果你已启用 Play App Signing,可以在 Play Console 的 Protected with Play > Play Store protection > Manage Play app signing 下的"Upload Key Certificate"部分发起 upload key 重置请求:生成一个新的 upload keystore,用 keytool -export -rfc 将证书导出为 PEM 格式,连同重置原因一起上传;Google 批准后新密钥即生效。如果未启用,损失将是永久性的——你将再也无法更新该应用。
- 什么是 key.properties?为什么需要它?
- 它是保存在 android/ 目录下的明文配置文件,记录着你的 keystore 文件路径和密码。Gradle 在签署 release 构建时会从中读取这些信息;该文件绝不能提交到 git。
- 我忘记了 keystore 密码,但文件还在——能找回吗?
- 不能——密码是让文件真正可用的加密组成部分,无法找回。对你的应用来说,这在实际后果上等同于彻底丢失文件:如果启用了 Play App Signing,就重置 upload key;如果没有启用,就只能用新的 applicationId 重新开始。
- debug keystore 和 release(upload)keystore 有什么区别?
- debug keystore 由 Flutter/Android Studio 自动生成,使用固定且公开已知的密码,仅用于本地测试,任何商店都不接受它。release(upload)keystore 则是你自己用 keytool 生成的,密码只有你知道,用于签署你上传到商店的软件包。
- 我应该把 keystore 文件加入项目代码仓库(git)吗?
- 不应该。keystore 文件和 key.properties 都应加入 .gitignore,绝不能提交;一旦泄露到公开仓库,任何获得该密钥的人都能尝试以你应用的身份签署软件包。