使用hutool工具包为项目更换报文加密方式

项目最初采用RSA报文加密方式,由于临时需求要将RSA改为国密算法,然后就是我的踩坑之路:

首先,国密算法会用到hutool-all-xxx.jar和bcprov-jdk15on-xxx.jar两个jar包;

这里需要注意:hutool工具包会存在和jdk版本兼容的问题,博主使用的hutool-all-4.6.3需要jdk1.7+的支持,5.x则需要jdk1.8+的支持.

需要了解其他详情可以访问hutool的官网:Hutool — 🍬A set of tools that keep Java sweet.

废话不多说上代码:

public class Sm4Util{
//otherPublickey    对手公匙
//otherPrivatekey   对手私匙
//ownPublickey      己方公匙
//ownPrivatekey     己方私匙

//在两个系统进行加密数据互传时,己方是不可能获取对方的私匙的,同样对方不可能获取己方私匙
//例如,我用对方公匙加密后的内容发送给对手系统时,对方可以用他的私匙解密

    //对传来的内容进行加签加密
    public static String deliver(String msg,String otherPublickey,String ownPublickey){
        return encryptAndSign(msg,otherPublickey,ownPublickey);
    }

    //对传来的内容进行解签解密
    public static String receive(String msg,String ownPrivatekey,String otherPublickey){
        return checkSigAndDecrypt(msg,ownPrivatekey,otherPublickey);
    }
    
     //验签和解密
    public static String checkSignAndDecrypt(String msg,String ownPrivatekey,String 
    otherPublickey) throws AlipayApiException {
        System.out.println("接收到的原始密文:"+msg);
        if(!isBlank(msg)){//判断非空
            Element e = XmlUtils.getRootElementFromString(msg);
            //String content = XmlUtils.getElementValue(e, "response");
            String corpCode = XmlUtils.getElementValue(e, "corpCode");
            String sign = XmlUtils.getElementValue(e, "sign");
            //先解外层非对称加密,用私钥
            SM2 sm21 = SmUtil.sm2(ownPrivatekey,null);
            String sm21decryptStr= sm21.decryptStr(sign, KeyType.PrivateKey);
            System.out.println("解除外层后"+sm21decryptStr);
            //再解内层对称加密,
            String sSM4Key11 = otherPublickey.substring(0,16);
            SymmetricCrypto sm41 = SmUtil.sm4(sSM4Key11.getBytes());
            String  contentDecryptstr = sm41.decryptStr(sm21decryptStr);

            System.out.println("解密解签后----"+contentDecryptstr);
            System.out.println(contentDecryptstr);
            return contentDecryptstr;

        }
        return null;

    }
    //加签加密 这里因为报文是xml格式,所以加上了xml的标签,对手才能成功接收,懒得删了,无视即可
    public static String encryptAndSign(String msg, String             
    otherPublickey,String ownPublickey) throws AlipayApiException {

        System.out.println("对称加密加签前数据:"+msg);
        StringBuilder sb = new StringBuilder();
        if(!isBlank(msg)){
            sb.append("<?xml version=\"1.0\" encoding=\"" + "UTF-8" + "\"?>");
            sb.append("<lziig>");
            //用我方公钥的前16位字符加密内层
            String sSM4Key = ownPublickey.substring(0,16);
            SymmetricCrypto sm4 = SmUtil.sm4(sSM4Key.getBytes());
            String sSM4encrypt = sm4.encryptHex(msg,"UTF-8");
            sb.append("<response></response>");
            sb.append("<encryption_type>SM4</encryption_type>");
            //通过对方公钥获取非对称加密外层
            SM2 sm2 = SmUtil.sm2(null,otherPublickey);
            //用完整的对方公钥加密数据
            String sendJson = sm2.encryptHex(sSM4encrypt, KeyType.PublicKey);
            sb.append("<sign>" + sendJson + "</sign>");
            sb.append("<sign_type>SM2</sign_type>");
            sb.append("</lziig>");
        }
        return sb.toString();
    }

    public static boolean isBlank(String str) {
        int strLen;
        if (str != null && (strLen = str.length()) != 0) {
            for(int i = 0; i < strLen; ++i) {
                if (!Character.isWhitespace(str.charAt(i))) {
                    return false;
                }
            }

            return true;
        } else {
            return true;
        }
    }
    
}

我将上面的代码在我项目中封装成了一个工具类,在需要用的地方直接调用对应方法。这里的类是为了模仿客户端,测试能否正常加密发送到服务端和从服务端接收解密报文.

还有一点,在用对方公匙加密,对方接收到后要用他自己的私匙加密,对方用我方公匙加密,我方接受时用自己的私匙解密即可,当然这是针对非对称加密,如果是对称加密则简单很多

如有纰漏,还请各位老师指出错误.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值