Android 稀奇古怪系列:新版本签名问题-Algorithm HmacPBESHA256 not available

🧩 Android 稀奇古怪系列:Algorithm HmacPBESHA256 not available

做 Android 开发久了,总会遇到些"不按常理出牌"的 BUG。

它们不是语法错误,而是藏在系统兼容、JDK 差异、Gradle 工具链甚至 IDE 默认行为里的暗坑。

这一回的坑,是由 Android Studio 自带签名工具的"安全性提升" 引发的兼容灾难。


🚨 异常概述

报错信息:

vbnet 复制代码
com.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 的签名工具帮我们"提升了安全性",

也顺便帮我们"挖了个坑"。

相关推荐
阿巴斯甜20 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker21 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95271 天前
Andorid Google 登录接入文档
android
黄林晴1 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_2 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android