Android端AES加密生成Hex格式数据报错NoSuchMethodError排查(适配Node.js Forge服务端场景)
这个报错的核心原因很明确:你调用的Hex.encodeHexString([BZ)方法在Android系统自带的org.apache.commons.codec.binary.Hex类中不存在。
为什么会出现这个错误?
Android系统内置了一个旧版本的Apache Commons Codec库(打包在org.apache.http.legacy.jar里),这个旧版本的Hex类只提供了encodeHex(byte[])方法(返回char[]类型),而你代码里用到的encodeHexString(byte[], boolean)是Commons Codec 1.10及以上版本才新增的静态方法,系统自带的旧版本根本没有这个方法,所以抛出了NoSuchMethodError。
三种可行的解决方法
方法1:改用系统自带Hex类支持的API
不用引入额外依赖,直接用旧版本Hex类的encodeHex方法,把返回的char[]转换成String,同时处理大小写需求:
val KEY_AES= "************" val IV_AES= "************" fun encrypat(value: String): String? { try { val key: ByteArray = KEY_AES.toByteArray() val ivs: ByteArray = IV_AES.toByteArray() val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding") val secretKeySpec = SecretKeySpec(key, "AES") val paramSpec: AlgorithmParameterSpec = IvParameterSpec(ivs) cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, paramSpec) val encryptedBytes = cipher.doFinal(value.toByteArray(charset("UTF-8"))) // 转换为char数组后转成字符串,再转小写匹配原代码需求 val hexChars = org.apache.commons.codec.binary.Hex.encodeHex(encryptedBytes) return String(hexChars).toLowerCase() } catch (e: Exception) { e.printStackTrace() } return null }
方法2:改用Android原生的android.util.Hex类(最推荐)
Android系统本身提供了android.util.Hex工具类,完全可以替代第三方的Hex转换,彻底避免版本冲突问题:
val KEY_AES= "************" val IV_AES= "************" fun encrypat(value: String): String? { try { val key: ByteArray = KEY_AES.toByteArray() val ivs: ByteArray = IV_AES.toByteArray() val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding") val secretKeySpec = SecretKeySpec(key, "AES") val paramSpec: AlgorithmParameterSpec = IvParameterSpec(ivs) cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, paramSpec) val encryptedBytes = cipher.doFinal(value.toByteArray(charset("UTF-8"))) // 原生API默认返回大写,转小写匹配原代码需求 return android.util.Hex.encodeToString(encryptedBytes).toLowerCase() } catch (e: Exception) { e.printStackTrace() } return null }
方法3:引入最新版的Commons Codec库并强制使用
如果你一定要用Apache Commons Codec的encodeHexString方法,可以在项目中引入最新版的库,并配置Gradle强制使用这个版本,忽略系统自带的旧版本:
- 在
app/build.gradle的dependencies块中添加依赖:
implementation 'commons-codec:commons-codec:1.15'
- 在
android块中添加配置,强制使用引入的版本:
android { // ...其他已有配置 configurations.all { resolutionStrategy.force 'commons-codec:commons-codec:1.15' } }
配置完成后,你的原有代码就能正常运行了。
额外提醒:AES密钥长度必须是16、24或32字节(对应AES-128、AES-192、AES-256),IV必须是16字节,否则初始化Cipher时也会抛出异常,记得检查你的KEY_AES和IV_AES是否符合要求哦。
内容的提问来源于stack exchange,提问作者LumbusterTick

