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 的签名工具帮我们"提升了安全性",

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

相关推荐
小妖怪的夏天8 小时前
react native android设置邮箱,进行邮件发送
android·spring boot·react native
东风西巷8 小时前
Avast Cleanup安卓版(手机清理优化) 修改版
android·学习·智能手机·软件需求
用户2018792831678 小时前
Android断点续传原理:小明的"读书笔记"故事
android
用户2018792831679 小时前
ART 内存模型:用 “手机 APP 小镇” 讲明白底层原理
android
liulangrenaaa9 小时前
Android NDK 命令规范
android
用户2018792831679 小时前
Android中的StackOverflowError与OOM:一场内存王国的冒险
android
用户20187928316710 小时前
类的回收大冒险:一场Android王国的"断舍离"故事
android
用户20187928316710 小时前
Android Class 回收原理及代码演示
android
前端 贾公子11 小时前
《Vuejs设计与实现》第 18 章(同构渲染)(上)
android·flutter