VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Java教程 >
  • 反射解决微信开发加解密illegal key size,不需要修改JDK jar包

 在微信开发时,消息接口时,涉及到消息加密,抛出了 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的问题

//反射获取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);
复制代码

 

执行完整的代码后,加密/解密正常,用微信企业号默认的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 = "<xml><ToUserName><![CDATA[mycreate]]></ToUserName><FromUserName><![CDATA[wx5823bf96d3bd56c7]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[this is a test]]></Content><MsgId>1234567890123456</MsgId><AgentID>128</AgentID></xml>";
        String sReqTimeStamp = "1409659813";

        String sReqNonce = "1372623149";
        String result = wxcpt.EncryptMsg(sRespData,sReqTimeStamp,sReqNonce);

        System.out.println(result);
    }
}
复制代码



来源:https://www.cnblogs.com/xcr1234/p/15451907.html


相关教程