在微信开发时,消息接口时,涉及到消息加密,抛出了 java.security.InvalidKeyException: Illegal key size 的异常,异常堆栈如下:
按照网上的解决方案,都是要求替换JDK目录下两个jar包,
对于一些生产系统 这种方式就不是很方便了,经过探索,发现一种方案,通过反射机制来解决
查看JDK源码,Cihper.checkCryptoPermcheckCryptoPerm,代码如下
private void checkCryptoPerm(CipherSpi var1, Key var2) throws InvalidKeyException {
if (this.cryptoPerm != CryptoAllPermission.INSTANCE) {
AlgorithmParameterSpec var3;
try {
var3 = this.getAlgorithmParameterSpec(var1.engineGetParameters());
} catch (InvalidParameterSpecException var5) {
throw new InvalidKeyException("Unsupported default algorithm parameters");
}
if (!this.passCryptoPermCheck(var1, var2, var3)) {
throw new InvalidKeyException("Illegal key size or default parameters");
}
}
}
其中主要的就是 this.cryptoPerm != CryptoAllPermission.INSTANCE ,找到cryptoPerm初始化的位置,有一个方法
private void initCryptoPermission() throws NoSuchAlgorithmException {
if (!JceSecurity.isRestricted()) {
this.cryptoPerm = CryptoAllPermission.INSTANCE;
this.exmech = null;
} else {
this.cryptoPerm = getConfiguredPermission(this.transformation);
String var1 = this.cryptoPerm.getExemptionMechanism();
if (var1 != null) {
this.exmech = ExemptionMechanism.getInstance(var1);
}
}
}
意思是,如果 JceSecurity.isRestricted() 返回true,则使用CryptoAllPermission.INSTANCE实例 否则需要进行key的校验,因此修改这个方法就行了
isRestricted方法的内容如下:
final class JceSecurity {
private static final boolean isRestricted; //默认情况下为true
static boolean isRestricted() {
return isRestricted;
}
}
isRestricted这是一个private static final变量,可通过反射的方式修改
反射修改private field值的方法是
Field field = Class.forName("类名").getDeclaredField("属性名");
field.setAccessible(true);
field.set(null,值); // 如果是static,第一个参数填null,否则填实例对象
由于这个属性的final的,需要对Field.class再反射一次,从modifiers中去掉final属性:
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
完整的代码:
//解决微信开发时,InvalidKeyException:illegal Key Size的问题//反射获取isRestrictedfieldField field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted");//这个field是 private static final的,需要找到这个field的modifiers,将final去掉,才能修改Field modifiersField = Field.class.getDeclaredField("modifiers");modifiersField.setAccessible(true);modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);//修改fieldfield.setAccessible(true);field.set(null,false);
执行完整的代码后,加密/解密正常,用微信企业号默认的SDK,测试加密通过
import com.yomahub.liteflow.example.utils.WXBizMsgCrypt;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Test {
public static void main(String[] args) throws Exception {
//解决微信开发时,InvalidKeyException:illegal Key Size的问题
//反射获取isRestrictedfield
Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted");
//这个field是 private static final的,需要找到这个field的modifiers,将final去掉,才能修改
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
//修改field
field.setAccessible(true);
field.set(null,false);
String sToken = "QDG6eK";
String sCorpID = "wx5823bf96d3bd56c7";
String sEncodingAESKey = "jWmYm7qr5nMoAUwZRjGtBxmz3KA1tkAj3ykkR6q2B2C";
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID);
String sRespData = "13488318601234567890123456128";
String sReqTimeStamp = "1409659813";
String sReqNonce = "1372623149";
String result = wxcpt.EncryptMsg(sRespData,sReqTimeStamp,sReqNonce);
System.out.println(result);
}
}
View Code
Original: https://www.cnblogs.com/xcr1234/p/15451907.html
Author:
Title: 反射解决微信开发加解密illegal key size,不需要修改JDK jar包
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/622026/
转载文章受原作者版权保护。转载请注明原作者出处!