Keystore 是一个受保护的加密存储库,用于在 Android 开发中存储私钥和应用签名证书。根据 Android Developers Documentation, 2026,每个 APK 或 App Bundle 在 Google Play 发布之前必须使用 Keystore 中的数字签名进行签名。我们将介绍 Keystore 格式、创建和项目中使用。
要点
Keystore(KeyStore)— 是 Java 加密架构(JCA)的标准机制,用于存储加密密钥、证书和可信条目。在 Android 开发中,Keystore 用于存储应用发布前进行签名的私钥。签名保证应用确实由指定的开发者发布,并且其代码在发布后未被修改。每次应用更新必须使用相同的密钥签名,否则 Google Play 将拒绝 APK 或 App Bundle。
Keystore 可以包含多个条目(别名),每个条目代表一个带证书的密钥对(私钥和公钥)。别名 — 应用在签名时访问密钥的唯一条目名称。在典型的 Android 项目中,Keystore 包含一个用于签名发布版本的条目,还可以包含用于签名调试版本的附加条目。Google Play Console 为每个上传的应用显示证书的 SHA-1 和 SHA-256 指纹。
Android Studio 通过 Build → Generate Signed Bundle / APK 菜单包含对 Keystore 的内置支持。签名向导允许创建新的 Keystore 或选择现有的,指定别名、Keystore 和密钥密码,以及认证数据(组织名称、城市、国家)。这些数据嵌入到证书中,用户在验证 APK 签名时可见。Google Play 要求证书有效期至少为 25 年 — Android 在安装应用时检查到期日期。
应用更新在 Google Play 中只能使用与第一个版本相同的密钥。如果 Keystore 丢失,则无法发布更新 — 应用必须使用新的包名称重新发布。根据 Google Play Console Help (2026),应用签名密钥只能通过 Google Play App Signing 恢复 — 该服务将密钥存储在 Google 端。如果开发者使用了此选项,则本地 Keystore 的丢失并不严重。
Android 应用的签名过程包括创建 APK 内容的摘要(哈希)并使用 Keystore 中的私钥对其进行加密。Android SDK Build Tools 包含 apksigner 工具,它以 APK Signature Scheme v2(或 Android 9+ 的 v3)格式执行签名。在安装应用时,Android 验证签名:使用证书的公钥解密签名,将 APK 的哈希与原始哈希进行比较 — 如果哈希不匹配,则拒绝安装。
Android 支持多种签名方案:v1(JAR 签名)、v2(APK Signature Scheme)、v3(支持密钥轮换的 APK Signature Scheme)和 v4(Android 11+ 增量安装)。Google Play 要求新应用使用 v2 或 v3。如果密钥支持相应的算法,apksigner 会在签名时自动添加所有必要的方案。Android 11+ 支持带有 v4 签名的 ADB 安装,这加速了大型 APK 文件增量加载到设备的速度。
算法:Android 建议使用 RSA-2048 或 ECDSA P-256 作为签名密钥。证书应为 X.509 v3。Android 在安装时检查证书是否有效 — 如果已过期,则安装被阻止。这就是 Google 建议将证书有效期设置为至少 25 年的原因。Google Play App Signing 使用两个密钥:应用签名密钥(app signing key)和上传密钥(upload key)— 上传密钥由开发者用于将 APK 上传到 Console,Google 使用主密钥为用户签名应用。
Java 支持两种主要的 Keystore 格式:JKS(Java KeyStore)— Oracle 专有格式,自 JDK 1.2 以来存在,和 PKCS12 — RSA Laboratories 的标准化公钥密码标准 #12 格式。JKS 使用自己的数据存储格式,仅在 Java 生态系统中受支持。PKCS12 是一个开放标准,受 Java、.NET、OpenSSL、Python(cryptography)和大多数其他加密库支持。
Google Play 推荐 PKCS12 作为 2021 年后创建的新 Keystore 的首选格式。JDK 9 及更新版本默认以 PKCS12 格式创建 Keystore(以前默认是 JKS)。PKCS12 的主要优势是兼容性:.p12 文件可以在任何不依赖于 Java 的环境中打开。OpenSSL 可以从 PKCS12 中提取证书并将其转换为 PEM 格式。JKS 文件需要 JDK 工具来读取,并且无法由 OpenSSL 处理。
格式之间的转换使用 JDK 的 keytool 工具完成。在从 JKS 迁移到 PKCS12 时,必须确保所有别名和密码已正确转移。keytool -importkeystore 命令允许将一个 Keystore 的内容导入到另一个,无论格式如何。转换后,最好删除旧的 JKS 文件,以避免密钥版本混淆。Android Studio 在生成签名构建时支持两种格式。
| 特性 | JKS | PKCS12 |
|---|---|---|
| 标准 | 专有(Oracle) | 开放(RSA Labs) |
| 扩展名 | .jks / .keystore | .p12 / .pfx |
| 支持 | 仅 Java | Java、OpenSSL、.NET、Python |
| 默认 | JDK 8 及之前 | JDK 9+ |
| Google 推荐 | 已过时 | 首选 |
keytool 工具是 JDK(Java Development Kit)的一部分,提供了一套完整的命令来创建、查看和管理 Keystore。要创建一个带有一个密钥对的新 Keystore,使用 keytool -genkeypair 命令,并指定 PKCS12 格式、RSA 算法、密钥大小和证书有效期。Google Play 要求证书有效期至少为 25 年(9125 天)— 建议在 -validity 参数中指定此值。
为 Android 项目生成 PKCS12 格式的 Keystore 示例。-dname 参数包含证书的 X.500 Distinguished Name。-ext 参数将在需要时启用 Subject Alternative Name — 对于 Android,Basic Constraints 就足够了:
# 为 Android 创建 PKCS12 Keystore
keytool -genkeypair -alias "upload_key" \
-keyalg RSA -keysize 2048 -validity 9125 \
-keystore "release-keystore.p12" \
-storetype PKCS12 \
-dname "CN=Developer,O=Company,C=RU"
Keytool 将提示输入 Keystore 密码和密钥密码(可以相同)。-storetype PKCS12 参数以现代格式创建文件。-keysize 2048 符合 Google 对最小 RSA 密钥大小的要求。-validity 9125(25 年)确保在应用的整个预期生命周期内兼容。创建 Keystore 后,建议使用 keytool -list -v -keystore release-keystore.p12 命令检查其内容。
要检查 Keystore 的条目,使用带 -list 标志的命令。输出包括别名、创建和到期日期、条目类型和 SHA-256 指纹。Android Studio 在选择现有 Keystore 时,在 Generate Signed Bundle / APK 对话框中显示相同的信息:
# 查看 Keystore 条目
keytool -list -v -keystore "release-keystore.p12" \
-storetype PKCS12
在 CI/CD 管道中,Keystore 必须安全存储并传输到构建代理,而不会有泄露风险。GitHub Actions 提供 Secrets 用于以 base64 格式存储二进制文件。Keystore 使用 base64 命令编码,结果字符串存储在仓库机密中,在构建阶段解码回文件。GitLab CI 通过 File 类型的 Variables 使用类似的机制。
在 GitHub Actions 中使用 Keystore 配置 CI 构建的示例包括从机密解码 Keystore、配置 Gradle 属性和执行签名构建。Gradle Android 插件从 keystore.properties 文件(为本地开发从 .gitignore 中排除)或 CI 系统的环境变量中读取 Keystore 路径和密码:
// build.gradle (app) — 签名配置
@Override
android {
signingConfigs {
release {
storeFile file("release-keystore.p12")
storePassword System.getenv("STORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
Gradle 读取 CI 系统设置的环境变量。Keystore 文件应位于应用模块的根目录中,如 storeFile 中指定。为了安全起见,切勿将密码存储在仓库中 — 使用 CI 系统的 Secrets。Fastlane for Android 提供了与 Google Play Console 配合使用的 supply 插件,但 APK 签名仍然需要代理上的本地 Keystore。
替代方案是 Google Play App Signing。使用此选项时,开发者只将上传密钥(upload key)上传到 Google Play,Google 用自己的密钥签署最终的 APK。在这种情况下,Keystore 仅用于创建上传密钥,其丢失不会阻止更新 — 可以生成新的上传密钥并在 Console 中注册。从 2021 年 8 月起,新应用必须使用 Google Play App Signing。
Keystore 丢失是 Android 开发中最关键的问题之一。没有备份,无法发布现有应用的更新 — Google Play 拒绝使用不同密钥签名的 APK。建议至少在不同物理或云存储中保留两个 Keystore 备份:例如,团队云存储中的加密文件和组织保险柜中的物理介质。Keystore 和密钥密码与文件分开存储,例如在具有访问控制的密码管理器中。
Android Studio 在 Generate Signed Bundle / APK 对话框中创建新 Keystore 时,会提示记住未来构建的路径。然而,开发环境本身不会创建备份 — 这是开发者的责任。对于团队开发,建议使用 Google Play App Signing,并通过安全通道将上传密钥传递给所有团队成员。Gradle 允许使用自动生成的 debug.keystore 签名调试构建,该密钥库不需要备份 — 它对所有 Android Studio 安装都是相同的。
Keystore 传输时的安全性:.p12 或 .jks 文件只能通过加密通道(SFTP、HTTPS、加密电子邮件附件)传输。切勿将 Keystore 包含在源代码仓库中 — 即使是私有的。GitGuardian 或 GitHub secret scanning 会自动检测凭据的发布,但将 Keystore 存储在仓库中仍然违反安全规定。对于 CI/CD,使用平台机密机制(GitHub Actions Secrets、GitLab CI Variables、Jenkins Credentials)进行基础设施级别加密。
常见问题解答
如果您使用 Google Play App Signing,只是上传密钥丢失了 — 您可以生成一个新的并在 Google Play Console 中注册。如果未启用 App Signing,Keystore 丢失意味着无法更新应用 — 您需要使用不同的 package name 发布新应用。
是的,一个 Keystore 可以包含多个别名(条目),为不同的应用提供不同的密钥。对于每个应用,建议在同一个 Keystore 中使用单独的别名。Google Play 支持不同应用使用不同密钥 — 一个 Keystore 用于多个项目没有限制。
Android 支持两种算法,但 ECDSA P-256 更优:它以更小的签名大小和更快的验证提供等效于 RSA-2048 的安全性。但如果需要与 Android 4.4 及更低版本兼容,请选择 RSA — ECDSA 仅从 Android 4.3+ 开始支持。
Android 在安装应用时检查证书的有效期。如果证书已过期,安装将被阻止 — 即使是对现有应用的更新。25 年是 Google 建议的最短期限,以覆盖移动应用的整个预期生命周期,而无需颁发新证书。
Debug.keystore 由 Android SDK 自动创建,用于签名调试构建。它对所有 Android Studio 安装都是相同的(标准密码 android)。发布版 Keystore 由开发者创建,用于签名在 Google Play 上发布的版本,必须安全保管 — 其丢失是严重的。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。