第3章:原始应用签名密钥的生成与保管
本章聚焦Android应用签名的起点——使用JDK内置的keytool工具生成JKS格式密钥库,并建立从密钥创建、密码与别名记录到离线备份的完整保管流程。密钥是应用数字身份的根,一旦丢失或泄露,将导致无法更新已发布应用、无法通过Google Play Integrity验证,甚至被恶意篡改冒签。本章按SOP流程逐一拆解每个操作节点。
适用场景
- 新应用首次发布:为应用创建独立的原始签名身份,用于Google Play App Signing初始上传密钥。
- 密钥轮换或补签:需要为已有应用生成新的签名密钥,并替换Google Play控制台中的上传密钥。
- 企业级多应用隔离:每个应用或应用组使用独立JKS密钥库,防止单点泄露波及全系产品。
- 合规审计要求:金融、政务、医疗类应用需满足密钥生成和保管的可追溯、可恢复标准。
前置条件
| 条件项 | 要求 | 确认方式 |
|---|---|---|
| JDK 版本 | ≥ JDK 8(推荐 JDK 11 LTS 或 JDK 17 LTS) | java -version |
| keytool 可用 | 位于 $PATH 或 %JAVA_HOME%\bin\ | keytool -help |
| 操作系统 | macOS / Linux / Windows 均可,无特殊限制 | — |
| 离线存储介质 | ≥ 2 份独立物理介质(USB 加密盘 / 刻录光盘 / 硬件密码模块) | 物理检查 + 写入测试 |
| 密码管理工具 | 企业密码管理器(如 1Password、KeePass、Bitwarden)或纸质密封信封 | 记录完整性检查 |
操作步骤
Step 1:确认工作目录与环境变量
- 创建一个专用工作目录(例如
~/app-signing-keys/或D:\signing-keys\),该目录仅用于本次密钥生成,生成后清理。 - 打开终端(macOS/Linux)或命令提示符(Windows 以管理员身份运行)。
- 验证 keytool 可执行:
keytool -genkey -v -keystore my-release-key.jks \
-keyalg RSA -keysize 2048 -validity 10000 \
-alias my-app-key-alias
最佳实践:
-validity 建议 ≥ 10000 天(约 27 年),覆盖应用完整生命周期。Google Play 要求上传密钥的有效期超过应用预期寿命,避免中途过期导致签名验证失败。Step 2:交互式填写密钥信息
执行上述命令后,keytool 会依次提示以下字段。请逐项填写,所有字段必须真实、完整,不可使用占位符:
| 提示字段 | 填写指导 | 示例 |
|---|---|---|
| Keystore 密码 | ≥ 16 位,混合大小写 + 数字 + 特殊字符;立即记录 | Jks!P@ss2024#Sec |
| 密钥密码 | 建议与 Keystore 密码一致(回车确认),也可独立设置 | 同上或独立强密码 |
| 名字与姓氏 | 填写组织负责人或应用发布者真实姓名 | Zhang Wei |
| 组织单位 (OU) | 填写部门名称,如移动开发部 | Mobile Engineering |
| 组织 (O) | 填写公司法定全称 | Example Tech Co., Ltd. |
| 城市/地区 (L) | 填写注册城市 | Beijing |
| 州/省 (ST) | 填写注册省份 | Beijing |
| 国家代码 (C) | 两位 ISO 国家代码 | CN |
风险警示:密钥密码与别名是恢复签名的唯一凭证。密码丢失将导致整个密钥库不可用,应用永远无法发布更新。密码生成后必须立即使用密码管理器保存,并打印纸质副本密封存档。
Step 3:确认密钥库文件与指纹
- 生成完成后,当前目录出现
my-release-key.jks文件。 - 使用以下命令查看密钥指纹(SHA-256),并与 Google Play 控制台要求的指纹格式比对:
keytool -list -v -keystore my-release-key.jks -alias my-app-key-alias
输出中重点关注 SHA-256 和 有效期至 字段。示例输出片段:
Alias name: my-app-key-alias
Creation date: 2025-01-15
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Zhang Wei, OU=Mobile Engineering, O=Example Tech Co., Ltd., L=Beijing, ST=Beijing, C=CN
Issuer: CN=Zhang Wei, OU=Mobile Engineering, O=Example Tech Co., Ltd., L=Beijing, ST=Beijing, C=CN
Serial number: 1a2b3c4d
Valid from: Wed Jan 15 10:30:00 CST 2025 until: Sun Jun 02 10:30:00 CST 2052
Certificate fingerprints:
SHA-256: AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89
SHA-1: FE:DC:BA:98:76:54:32:10:FE:DC:BA:98:76:54:32:10
Step 4:记录密钥凭证与元数据
填写《密钥凭证记录表》(参见记录材料章节),必须包含以下信息:
- 密钥别名:
my-app-key-alias - Keystore 密码:记录在密码管理器 + 纸质密封信封
- 密钥密码:同上
- SHA-256 指纹:完整 64 位十六进制字符串
- 有效期截止日期:如 2052-06-02
- 生成时间与操作人:精确到分钟,记录执行者姓名
双重记录原则:电子记录(密码管理器)+ 纸质记录(防火防潮密封袋)分开存放,确保任何单一灾难不会同时摧毁两份记录。
Step 5:加密打包与离线备份
- 将
my-release-key.jks和《密钥凭证记录表》放入一个加密 ZIP 包:
# 使用 GPG 对称加密(推荐 AES-256)
gpg --symmetric --cipher-algo AES256 --output signing-key.gpg my-release-key.jks
# 或者使用 7-Zip 加密 ZIP(AES-256)
7z a -tzip -p"YourBackupPassword" -mem=AES256 signing-key-backup.zip my-release-key.jks record-sheet.pdf
- 将加密包写入 至少 2 份 物理介质:USB 加密盘 + 一次性写入光盘(DVD-R / BD-R)。
- 在介质表面粘贴标签(仅写项目编号和日期,不写“签名密钥”等敏感词)。
- 将介质存入不同的物理隔离位置:公司保险柜 + 银行保管箱 或 异地灾备中心。
安全红线:密钥库文件严禁以明文形式存储在 GitHub、GitLab、云盘、CI/CD 环境变量、Docker 镜像或任何联网位置。加密包也不应上传至云存储,除非使用企业级 HSM 或 KMS 服务配合访问审计。
Step 6:清理工作痕迹
- 确认备份介质写入成功并验证可读取后,立即删除工作目录下的
my-release-key.jks明文文件。 - 清空终端历史记录(macOS/Linux:
history -c;Windows:doskey /listsize=0)。 - 重启终端窗口,确保密码不残留在 shell 历史或环境变量中。
输入输出物
| 类别 | 输入物 | 输出物 | 保管要求 |
|---|---|---|---|
| 密钥文件 | — | my-release-key.jks(加密后归档) | 离线 + 加密 + 异址 |
| 凭证记录 | — | 《密钥凭证记录表》(电子+纸质) | 密码管理器 + 密封信封 |
| 备份介质 | 空白 USB / 空白光盘 | 写入加密包的物理介质 × 2+ | 双份异址物理隔离 |
| 指纹信息 | — | SHA-256 指纹摘要 | 存入 Google Play 控制台 + 本地记录 |
| 环境记录 | JDK 安装包 | 生成日志(脱敏后) | 审计归档 3 年 |
责任边界
- 开发工程师:执行 keytool 命令、填写交互信息、确认指纹正确性。不得私自留存密钥副本或密码。
- 安全官 / 密钥管理员:监督生成过程、审核凭证记录、执行加密打包并护送备份介质至离线存储位置。拥有密码纸质的唯一访问权。
- QA / 审计员:验证备份介质可恢复性(不接触明文密码)、检查清理痕迹、记录审计日志。
- CI/CD 管理员:仅在收到经安全官签发的加密密钥包后,方可将其导入构建系统的加密存储区(如 Jenkins Credential Binding 或 GitLab CI/CD Masked Variables)。
记录材料
以下记录表需在本章操作完成后 24 小时内填写完毕,由安全官签字归档:
| 记录项 | 内容 | 存放位置 |
|---|---|---|
| 《密钥生成操作记录表》 | 生成时间、操作人、环境信息、密钥参数、指纹摘要 | 内部审计系统 + 纸质归档 |
| 《密钥凭证记录表》 | 别名、Keystore 密码、密钥密码、有效期、SHA-256 | 密码管理器 + 纸质密封信封 |
| 《备份介质交接单》 | 介质编号、加密算法、存储位置、保管人、交接时间 | 安全部门档案柜 |
| 《恢复测试报告》 | 测试日期、测试人、是否成功还原、签名验证结果 | 归档至应用发布档案 |
异常处理
| 异常场景 | 处理措施 | 预防策略 |
|---|---|---|
keytool 命令未找到 | 检查 JAVA_HOME 环境变量,重新安装 JDK 或将 bin/ 目录加入 PATH | 生成前执行 keytool -help 验证 |
| 密码输入错误 / 忘记密码 | 立即中止操作,从密码管理器或纸质信封恢复密码;若无法恢复则重新生成密钥并更新 Google Play 上传密钥 | 生成时双人确认 + 立即记录 |
| 备份介质写入失败 | 更换介质品牌或类型(如 USB 写入失败改用光盘),重试加密写入步骤 | 准备 ≥ 3 份空白介质备用 |
| 指纹与预期不匹配 | 核对命令参数是否正确(别名、密码、算法),重新生成并对比两次指纹 | 生成后立即截图保存,双人复核 |
| 密钥文件在加密前被误删 | 若未备份则只能重新生成;若已部分备份则从备份中恢复并补全记录 | 加密前锁定文件只读权限 |
| 离线介质物理损坏 | 使用备用介质恢复;若无备用则从另一异址副本拷贝,重新写入新介质 | 坚持“2+1”策略:2份异址 + 1份本地临时副本(加密) |
验收标准
- 密钥完整性:从任意一份备份介质中完整还原
.jks文件,使用keytool -list -v查看指纹与原始记录表完全一致。 - 密码可恢复:从密码管理器或纸质密封信封中提取的密码可以成功打开密钥库,且别名匹配。
- 备份冗余:至少 2 份独立物理介质已存入不同物理位置(公司保险柜 + 银行保管箱或异地灾备中心),交接单签字完整。
- 痕迹清除:工作目录下无明文
.jks文件残留,终端历史记录已清空,无敏感信息泄露风险。 - 文档归档:所有记录表(操作记录、凭证记录、交接单、恢复测试报告)已填写并签字,电子版存入审计系统,纸质版存入档案柜。
- Google Play 关联:生成的 SHA-256 指纹已成功上传至 Google Play 控制台 > 应用签名 > 上传密钥证书(如适用),且状态为“已启用”。
验收通过标志:以上 6 项全部为“是”后,由安全官在《密钥生成操作记录表》中签署“验收通过”并加盖部门章,本章流程方可关闭。