简介:这份源码资源面向需要在Google Play上更新应用签名的Android开发者,尤其是遇到签名校验失败、密钥轮换或上架审核受阻等问题的技术人员。资源以Java源码为主体,包含TLS协议实现、证书路径校验、椭圆曲线运算、AES与Threefish加密引擎、GOST与DSTU哈希算法等底层安全组件,可用于理解签名验证链路与加密通信机制。压缩包共2000个文件,其中1999个为java源码文件,另有1个txt说明文件,整体约5.02MB,体量轻便,便于直接导入IDE阅读与调试。目前已有372人学习下载,适合具备一定Android与密码学基础、希望深入排查签名问题的开发者参考。通过研读这些源码,读者可掌握证书链校验、密钥交换与摘要算法的具体实现思路,为自定义签名方案或安全加固提供可复用的代码基础。
1. 从一次签名翻车说起:pepk 源码到底该怎么装
Google Play 的签名机制这两年改得勤,不少团队在更新应用时突然发现上传的包被拒,提示签名不匹配,回头一查才发现是 pepk 工具没配对版本。pepk 是 Google 官方提供的一个密钥导出加密工具,用来把已有的签名密钥加密后上传到 Play Console,配合 Play App Signing 完成签名轮换。听起来简单,但真到装的时候,Java 版本、密钥库格式、加密参数、输出编码,每一步都能卡住人。我见过最典型的一次翻车,是某开发者直接用系统自带的 JDK 8 跑 pepk,结果加密后的文件上传后 Play Console 死活解不开,折腾了一整天才发现是 JDK 版本和 pepk 的加密实现不兼容。这篇笔记就把 pepk 源码的获取、环境搭建、参数配置、验证跑通整个流程拆开讲,适合正在做签名迁移或第一次接触 Play App Signing 的开发者照着走一遍。
2. 环境准备:JDK 版本、依赖与 pepk 源码获取
2.1 为什么 JDK 版本是第一个坑
pepk 本身是一个 Java 工具,源码托管在 Google 的官方仓库里,编译和运行都依赖 JDK。但问题在于,不同版本的 pepk 对 JDK 的要求不一样。早期版本的 pepk 用 JDK 8 编译没问题,但如果你拿到的源码是较新的分支,里面用到了 JDK 11 才有的 API,用 JDK 8 编译直接报cannot find symbol。更隐蔽的是运行时的问题:即使编译过了,JDK 8 和 JDK 11 在加密算法实现上有细微差异,尤其是AES/GCM/NoPadding这种模式,填充方式和 IV 处理稍有不同,加密出来的文件在 Play Console 那边就解不开。
我一般会先确认源码的build.gradle或者pom.xml里声明的 Java 版本。如果是 Gradle 项目,看sourceCompatibility和targetCompatibility;如果是 Maven,看maven.compiler.source。没有明确声明的话,直接上 JDK 11 或 JDK 17 的 LTS 版本最稳。JDK 17 目前兼容性最好,pepk 的新老分支都能跑,而且长期支持,不用担心突然断更。
提示:不要用系统自带的 OpenJDK,很多 Linux 发行版默认装的是精简版 JDK,缺少
jce无限强度策略文件,加密时会抛InvalidKeyException。建议手动装 Oracle JDK 或者 Adoptium 的完整版。
2.2 获取 pepk 源码的两种方式
pepk 的源码可以从 Google 的官方仓库克隆,也可以直接下载 release 包。如果你只是要用,不打算改代码,直接下 release 包最省事。但如果你需要针对自己的密钥库格式做调整,或者想看清楚加密逻辑,那就得克隆源码自己编译。
克隆源码的命令如下:
# 从官方仓库克隆 pepk 源码 git clone https://github.com/google/pepk.git # 进入源码目录 cd pepk # 查看当前分支和最近的提交,确认版本 git log --oneline -5这里用git log看一眼最近的提交,是为了确认你拿到的是哪个时间点的代码。pepk 的更新不算频繁,但签名相关的逻辑偶尔会修,比如之前有个版本对 PKCS12 密钥库的支持有问题,后来打了补丁。如果你克隆下来发现是很老的提交,建议切到最新的 release tag。
如果你不想用 git,也可以直接下载 release 包。下载下来是一个 zip 或者 tar.gz,解压后里面通常有编译好的 jar 包和源码。但要注意,release 包里的 jar 不一定是最新的,有些是几个月前打的,用之前最好对一下版本号。
2.3 编译 pepk 源码:Gradle 和 Maven 的取舍
pepk 源码同时支持 Gradle 和 Maven 构建。Gradle 的构建脚本在根目录的build.gradle,Maven 的在pom.xml。我一般用 Gradle,因为它的依赖管理更清晰,而且 pepk 的官方文档也是以 Gradle 为主。
编译之前先确认 Gradle 版本。源码里的gradle/wrapper/gradle-wrapper.properties会指定 Gradle 版本,直接用./gradlew就会自动下载对应的 Gradle,不用自己装。命令如下:
# 赋予执行权限 chmod +x gradlew # 清理并编译,跳过测试加快速度 ./gradlew clean build -x test # 编译完成后,jar 包在 build/libs 目录下 ls -lh build/libs/clean是清理之前的构建产物,避免旧文件干扰;build是编译加打包;-x test是跳过单元测试,因为 pepk 的测试用例有些需要真实的密钥库文件,跑起来比较慢,第一次编译可以先跳过。编译成功后,build/libs目录下会有一个pepk.jar,这就是后面要用的工具包。
如果用 Maven,命令是mvn clean package -DskipTests,产物在target目录下。Maven 的好处是如果你公司内网有 Maven 私服,依赖下载会快很多;Gradle 的好处是构建脚本更灵活,改起来方便。两者选一个就行,不用纠结。
注意:编译过程中如果报
Could not resolve dependencies,大概率是网络问题,Gradle 默认从 Maven Central 拉依赖,国内访问可能慢。可以在build.gradle里加阿里云的镜像仓库,或者配置全局的init.gradle做仓库替换。
3. 配置 pepk:密钥库参数、加密选项与输出格式
3.1 密钥库的准备与格式选择
pepk 的核心作用是把你的签名密钥加密后导出,所以第一步是准备好密钥库文件。Android 的签名密钥库常见的有两种格式:JKS 和 PKCS12。JKS 是 Java 传统的密钥库格式,PKCS12 是行业标准格式,Android Studio 从 3.0 开始默认用 PKCS12。
pepk 对两种格式都支持,但参数写法略有不同。如果你用的是 JKS,需要显式指定--keystore-type JKS;如果是 PKCS12,可以省略,因为 pepk 默认按 PKCS12 处理。我一般建议统一用 PKCS12,因为它是标准格式,跨工具兼容性好,而且 JDK 9 以后 JKS 的默认实现有变化,容易出玄学问题。
先确认你的密钥库格式:
# 查看密钥库类型和别名 keytool -list -v -keystore my-release-key.jks -storepass 你的密码 # 输出里会显示 Keystore type: PKCS12 或 JKSkeytool是 JDK 自带的工具,-list是列出密钥库内容,-v是详细输出,-keystore指定密钥库文件路径,-storepass是密钥库密码。输出里会显示密钥库类型、别名、证书指纹等信息。确认格式后,后面 pepk 的参数就好写了。
3.2 pepk 的核心参数逐个拆解
pepk 的命令行参数不多,但每个都关键。完整的命令格式如下:
java -jar pepk.jar \ --keystore=my-release-key.jks \ --alias=my-key-alias \ --output=encrypted-key.zip \ --encryptionkey=eb10fe8f7c7c9df715022017b00c6471f8ba8170b13049a11e6c09ffe3056a104a3bbe4ac5a955f4ba4fe93fc8cef27558a3eb9d2a529a2092761fc0f95d650 \ --include-cert--keystore指定密钥库文件路径,相对路径和绝对路径都行,但建议用绝对路径,避免工作目录不对导致找不到文件。--alias是密钥别名,就是keytool -list输出里显示的那个别名。--output是加密后的输出文件,通常是一个 zip 包,里面包含加密的密钥和证书。--encryptionkey是 Google Play Console 提供的一长串十六进制字符串,这个值每个应用不一样,在 Play Console 的「应用签名」页面能找到。--include-cert表示把证书也打包进去,这个参数建议加上,否则 Play Console 那边可能缺少证书链信息。
--encryptionkey这个参数最容易出错。它是一串 128 个字符的十六进制字符串,对应 64 字节的密钥材料。复制的时候一定要完整,不能有空格或换行。我见过有人从网页复制的时候多带了一个换行符,结果 pepk 报Invalid encryption key length,排查了半天。
3.3 密码处理:交互输入还是参数传入
pepk 需要两个密码:密钥库密码和密钥密码。默认情况下,pepk 会交互式提示输入,但如果你在 CI/CD 环境里跑,交互式输入就不方便了。pepk 支持通过--storepass和--keypass参数直接传入密码,但这样密码会出现在命令历史里,有安全风险。
我一般用环境变量的方式:
# 从环境变量读取密码,避免明文出现在命令中 java -jar pepk.jar \ --keystore=/path/to/my-release-key.jks \ --alias=my-key-alias \ --output=/path/to/encrypted-key.zip \ --encryptionkey=你的加密密钥 \ --include-cert \ --storepass="$KEYSTORE_PASSWORD" \ --keypass="$KEY_PASSWORD"$KEYSTORE_PASSWORD和$KEY_PASSWORD是提前在 shell 里 export 的变量,这样命令历史里看不到明文。如果是在 Jenkins 或 GitHub Actions 里跑,用对应的 secrets 机制注入环境变量。注意,--storepass和--keypass如果密码相同,可以只传--storepass,pepk 会默认用同一个密码。
提示:如果密钥库是 JKS 格式,且密钥密码和密钥库密码不同,必须同时传
--storepass和--keypass,否则会报UnrecoverableKeyException。
4. 避坑与排查:pepk 安装配置中最容易翻车的五个点
4.1 报错java.security.NoSuchAlgorithmException: AES/GCM/NoPadding
现象:运行 pepk 时直接抛异常,提示找不到AES/GCM/NoPadding算法。
原因:JDK 版本过低,或者用的是精简版 JDK,缺少 JCE 无限强度策略文件。JDK 8 的早期版本默认不支持 256 位 AES,需要手动替换local_policy.jar和US_export_policy.jar。
解决:升级到 JDK 11 或 JDK 17。如果必须用 JDK 8,去 Oracle 官网下载 JCE Unlimited Strength Jurisdiction Policy Files,替换$JAVA_HOME/jre/lib/security下的两个 jar 文件。不过现在 JDK 8 已经很少用了,直接升级更省事。
4.2 报错Invalid encryption key length
现象:pepk 启动后报加密密钥长度不对。
原因:--encryptionkey参数复制不完整,或者多了空格、换行符。这个密钥是 128 个十六进制字符,少一个都不行。
解决:从 Play Console 重新复制,粘贴到文本编辑器里检查长度。可以用echo -n "你的密钥" | wc -c确认字符数是不是 128。如果是 129,说明末尾多了换行符,去掉即可。
4.3 报错Keystore was tampered with, or password was incorrect
现象:pepk 提示密钥库被篡改或密码错误。
原因:密码确实错了,或者密钥库文件损坏。还有一种可能是密钥库格式和 pepk 默认的不一致,比如实际是 JKS 但没指定--keystore-type。
解决:先用keytool -list确认密码能正常打开密钥库。如果keytool能打开但 pepk 打不开,检查是否漏了--keystore-type JKS。如果keytool也打不开,说明密码真的错了,或者文件在传输过程中损坏,需要从备份恢复。
4.4 上传后 Play Console 提示签名不匹配
现象:pepk 生成的加密文件上传到 Play Console 后,提示签名与现有应用不匹配。
原因:pepk 用的密钥库不是当初上传应用时用的那个,或者别名选错了。一个密钥库文件里可能有多个别名,每个别名对应不同的密钥。
解决:用keytool -list -v查看密钥库里的所有别名,确认哪个是当初签名用的。对比证书指纹,Play Console 的「应用签名」页面会显示当前签名证书的 SHA-1 和 SHA-256 指纹,和keytool输出里的指纹对一下,一致的那个别名才是对的。
4.5 编译时Could not find tools.jar
现象:用 JDK 编译 pepk 源码时,Gradle 报找不到tools.jar。
原因:系统装的是 JRE 而不是 JDK,JRE 里没有tools.jar。或者JAVA_HOME指向了 JRE 目录。
解决:确认JAVA_HOME指向 JDK 安装目录,而不是 JRE。用echo $JAVA_HOME查看,然后ls $JAVA_HOME/lib/tools.jar确认文件存在。如果不存在,重新安装完整版 JDK。
5. 验证跑通:用测试密钥库完整走一遍 pepk 流程
装完配完之后,别急着拿生产密钥库去跑。我一般会先用一个测试密钥库完整走一遍流程,确认 pepk 能正常生成加密文件,再换生产密钥库。这一步花不了几分钟,但能避免很多低级错误。
5.1 生成测试密钥库
# 生成一个测试用的 PKCS12 密钥库 keytool -genkeypair \ -alias test-key \ -keyalg RSA \ -keysize 2048 \ -validity 365 \ -keystore test-keystore.p12 \ -storetype PKCS12 \ -storepass test123456 \ -keypass test123456 \ -dname "CN=Test, OU=Dev, O=Demo, L=City, S=State, C=CN"-genkeypair是生成密钥对,-alias是别名,-keyalg是算法,-keysize是密钥长度,-validity是有效期天数,-keystore是输出文件,-storetype指定 PKCS12 格式,-storepass和-keypass是密码,-dname是证书主题信息。这个测试密钥库只用来验证流程,不用管主题信息填得对不对。
5.2 用测试密钥库跑 pepk
# 用测试密钥库跑一遍 pepk,加密密钥用占位符 java -jar build/libs/pepk.jar \ --keystore=test-keystore.p12 \ --alias=test-key \ --output=test-encrypted.zip \ --encryptionkey=eb10fe8f7c7c9df715022017b00c6471f8ba8170b13049a11e6c09ffe3056a104a3bbe4ac5a955f4ba4fe93fc8cef27558a3eb9d2a529a2092761fc0f95d650 \ --include-cert \ --storepass=test123456 \ --keypass=test123456这里的--encryptionkey用的是 Google 官方文档里的示例值,实际使用时必须换成 Play Console 给你的那个。跑完之后检查test-encrypted.zip是否生成,文件大小是否正常(通常几 KB 到几十 KB)。
5.3 验证加密文件内容
# 查看加密 zip 包里的文件列表 unzip -l test-encrypted.zip # 输出应该包含 encrypted_key 和 certificate.pem 两个文件unzip -l是列出 zip 包内容,不实际解压。正常的 pepk 输出应该包含加密后的密钥文件和证书文件。如果只有密钥没有证书,说明--include-cert没生效,检查参数拼写。如果 zip 包是空的,说明 pepk 执行过程中出错了,回头看控制台有没有异常堆栈。
5.4 生产环境的最终检查清单
在拿生产密钥库跑之前,我习惯过一遍这个清单:
| 检查项 | 确认内容 |
|---|---|
| JDK 版本 | 11 或 17,完整版,非精简版 |
| pepk 版本 | 从最新源码编译,或官方 release 包 |
| 密钥库格式 | PKCS12 优先,JKS 需显式指定类型 |
| 别名 | 与 Play Console 当前签名证书指纹一致 |
| 加密密钥 | 从 Play Console 复制,128 字符,无空格换行 |
| 输出文件 | 包含 encrypted_key 和 certificate.pem |
| 密码传递 | 环境变量注入,不落命令历史 |
这张表看着简单,但每一条我都见过有人栽在上面。尤其是别名和加密密钥这两项,一个字母不对就前功尽弃。
从那以后我每次做签名迁移,都强制自己先用测试密钥库跑一遍完整流程,确认 pepk 输出正常了,再换生产密钥库。这个习惯帮我省了至少三次深夜回滚的麻烦。希望帮到你。
本文还有配套的精品资源,点击获取