🧩 Android 稀奇古怪系列:Algorithm HmacPBESHA256 not available
做 Android 开发久了,总会遇到些"不按常理出牌"的 BUG。
它们不是语法错误,而是藏在系统兼容、JDK 差异、Gradle 工具链甚至 IDE 默认行为里的暗坑。
这一回的坑,是由 Android Studio 自带签名工具的"安全性提升" 引发的兼容灾难。

🚨 异常概述
报错信息:
vbnetcom.android.ide.common.signing.KeytoolException: Failed to read key Key0 from store "C:\work\Android\xxx\app\test.jks": Integrity check failed: java.security.NoSuchAlgorithmException: Algorithm HmacPBESHA256 not available
场景非常常见:
- 在 新版本 Android Studio(内置 JDK 21) 中使用
「Generate Signed Bundle / APK」生成签名; - 拿这个签名文件放到老项目(JDK 11 环境)编译;
- 构建直接报错。
🧱 环境信息
项目 | 版本 |
---|---|
Android Studio | Meerkat Feature Drop · 2024.3.2 |
内置 JDK | 21 |
本地构建 JDK | 11 |
Gradle 版本 | 7.3.1 |

🔍 BUG 原因分析
1. 什么是 HmacPBESHA256?
HmacPBESHA256
是一种 keystore 加密算法,
全称是 HMAC-based Password-Based Encryption with SHA-256。
它结合了:
- HMAC-SHA256:基于 SHA-256 的消息认证;
- PBKDF2:通过多次哈希迭代生成强密钥。
作用是将用户输入的密码转化为高强度密钥,用来保护 .jks
/ .p12
文件内部的私钥内容。
2. 真正的问题不是 JDK,而是 Android Studio 的签名向导
许多人以为"JDK 21 生成的签名不兼容",其实不准确。
高版本 JDK 完全可以生成兼容签名。
问题的根源在于------Android Studio 自带的签名向导使用了新的默认算法。
区别如下:
生成方式 | 使用算法 | 是否兼容旧版 JDK |
---|---|---|
Android Studio 签名向导(JDK 21 内置 keytool) | HmacPBESHA256 |
❌ 否 |
命令行 keytool(即使是 JDK 21) | PBEWithMD5AndDES |
✅ 是 |
旧版 keystore 文件 | 旧算法 | ✅ 是 |
也就是说:
坑不在 JDK 版本,而在 Android Studio 的签名工具默认启用了新算法。
3. 异常流程复盘
markdown
Android Studio 2024.3.2(内置 JDK 21)
↓
Generate Signed Bundle / APK
↓
生成 keystore(HmacPBESHA256)
↓
旧项目使用 JDK 11 读取
↓
JDK 11 不识别该算法
↓
java.security.NoSuchAlgorithmException
🧩 解决方案
✅ 方案一:统一升级构建环境(推荐)
将项目构建使用的 JDK 升级到 14 及以上版本 。
因为从 JDK 14 起,HmacPBESHA256
算法已被原生支持。
检查版本
java -version
在 Gradle 中指定 JDK
在 gradle.properties
添加:
ini
org.gradle.java.home=C:\Program Files\Java\jdk-17
或直接在 Android Studio 里:
File > Settings > Build, Execution, Deployment > Build Tools > Gradle > Gradle JDK
中统一设置。
确保 IDE、Gradle、命令行、CI/CD 环境的 JDK 全部一致。
✅ 方案二:使用命令行生成签名(避免新算法)
如果暂时不能升级 JDK,可以直接用命令行生成签名文件。
命令行的 keytool
即使在 JDK 21 下,也不会自动启用 HmacPBESHA256
。
示例命令:
bash
keytool -genkeypair -alias testKey \
-keyalg RSA -keysize 2048 -validity 36500 \
-keystore test_compatible.jks \
-storetype JKS \
-storepass 123456 \
-keypass 123456 \
-dname "CN=Test, OU=Dev, O=Company, L=City, S=State, C=CN"
这样生成的 keystore 使用传统算法(PBEWithMD5AndDES
),
兼容所有 JDK 版本和老项目环境。
💡 延伸思考
Android Studio 自带的 JetBrains Runtime (JBR) 与系统 JDK 是两套独立环境。
自从 Arctic Fox 之后,AS 默认启用了自己的内置 JDK。
结果就是:
- 签名时走了 JBR 的 keytool;
- 编译时走了本地的 JDK;
- 两者算法不一致,冲突爆发。
🧭 总结
问题点 | 结论 |
---|---|
错误原因 | Android Studio 签名向导默认使用新算法 HmacPBESHA256 |
根本原因 | 低版本 JDK(≤11)不支持该算法 |
解决方案 1 | 升级项目 JDK ≥14 |
解决方案 2 | 用命令行 keytool 生成签名 |
建议 | 统一 IDE 与构建环境 JDK 版本,避免混用 |
有时候,坑并不是因为"版本太高",
而是因为"工具太聪明"。
Android Studio 的签名工具帮我们"提升了安全性",
也顺便帮我们"挖了个坑"。