打包 Android 应用时遇到过:

Keystore was tampered with, or password was incorrect

当时一直认为记住的密码没有错,搜索很久后才回到项目的 build.gradle 检查。发现签名配置中的密码字段与预期不一致,修正配置后恢复了构建。

这个错误提示应先沿“实际读取了哪个文件、用了哪个密码”排查,而不是立即认定密钥文件已经损坏。

四个签名字段分别是什么

字段用途
storeFile要打开的密钥库文件
storePassword打开或校验密钥库所用的密码
keyAlias选择密钥库中的具体条目
keyPassword使用该私钥条目的密码

两种密码是否相同,取决于实际密钥库和创建方式,不能为了让构建通过而随意把它们改成同一个值。alias 填错或读取了另一个文件,也会把排查引向错误方向。Android 应用签名说明

回到实际生效的 Gradle 配置

以下是 Groovy 结构示例,假设四个环境变量均已在本地或 CI 的凭据配置中正确设置:

android {
    signingConfigs {
        release {
            storeFile file(System.getenv("ANDROID_KEYSTORE_PATH"))
            storePassword System.getenv("ANDROID_KEYSTORE_PASSWORD")
            keyAlias System.getenv("ANDROID_KEY_ALIAS")
            keyPassword System.getenv("ANDROID_KEY_PASSWORD")
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

示例不包含真实路径或密码。使用前应检查变量是否缺失;不要在日志中打印它们,也不要把密码放在命令行参数、截图或提交记录里。

建议的检查顺序

先确认当前 build variant 使用哪个 signingConfig,再检查 storeFile 的实际解析位置,尤其是相对路径和 CI 工作目录。随后核对文件类型、alias 和两个密码各自的用途。

本地可以成功、CI 失败时,重点比较配置来源:CI 是否用了另一份密钥库,环境变量是否缺失,是否覆盖了项目属性。不要只比较编辑器里看到的那段配置。

对已经发布的应用,原签名材料关系到后续更新身份。不要通过新建密钥库来掩盖密码问题,也不要覆盖唯一的密钥备份;先按既有签名和平台支持的恢复机制处理。