自定义接口aop,实现自动加解密

1、创建切面

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface AutoSmUtil {
}

2、实现切面功能

@Aspect
@Component
public class AutoSmUtilImpl {

    @Value("${sm2.publicKey}")
    String publicKey_a;
    String publicKey_b="jHNE9tDymZU0BgZCX4slK7+SBOencVLnI3GvHiczb1Oy1Qb6rGoi/uL/nbJaSPfzTXA==";
    @Value("${sm2.privateKey}")
    String privateKey_a;
    String privateKey_b="UBgi2hRANCAASv8TQMEMH7gRmS+epXm2Mc0T20PKZlTQGBkJfiyUrv5IE56dxUucjca8eJzNvU7LVBvqsaiL+4v+dslpI9/NNc";


    @Around("@annotation(com.sgcc.payment.allinpay.annotation.AutoSmUtil)")
    public Object autoSmUtilImpl(ProceedingJoinPoint joinPoint) throws Throwable {
        //base64转密钥
        byte[] publicKeyByte =SecureUtil.decode(publicKey_a+publicKey_b);
        byte[] privateKeyByte = SecureUtil.decode(privateKey_a+privateKey_b);
        SM2 sm2 = SmUtil.sm2(privateKeyByte, publicKeyByte);
        Object[] args = joinPoint.getArgs();
        // 在这里对参数进行修改
        String prams1 = decrypt(sm2, JSONObject.parseObject(JSONObject.toJSONString(args[0])).getString("prams"));
//        Log.info("请求",prams1);
        args[0] = JSONObject.parseObject(prams1);
        // 修改完成后,可以继续调用原方法并传入修改后的参数
        String result = JSONObject.toJSONString(joinPoint.proceed(args));
//        Log.info("响应" ,result);
        //加密 先转json在转string
        result = encrypt(sm2,result);
        R r = new R();
        r.setData(result);
        r.setCode(200);
        r.setMsg("成功");
        return r;
    }
    //解密
    private String decrypt(SM2 sm2,String encryptedPassword) {
        byte[] decode = Base64.decode(encryptedPassword);
        //密文
//        System.out.println("密文:" + encryptedPassword);

        //解密
        String decryptStr = StrUtil.utf8Str(sm2.decrypt(decode, KeyType.PrivateKey));
//        System.out.println("解密后的原文:" + decryptStr);
        //sm2(sm3+原文)
        //截取头部的sm3和原文校验
        String sm3 = decryptStr.substring(0, 64);
        String returnValue = decryptStr.substring(64);
        //sm3校验
        if (!sm3.equals(SmUtil.sm3(returnValue))) {
            throw new RuntimeException("sm3校验失败");
        }

        return returnValue;
    }
    //加密
    private String encrypt(SM2 sm2,String returnValue) {
        //sm2(sm3+原文)
//        System.out.println("sm3加密后的原文:"+SmUtil.sm3(returnValue)+returnValue);
        return Base64.encode(sm2.encrypt(SmUtil.sm3(returnValue)+returnValue, KeyType.PublicKey));
    }

    public static void main(String[] args) {
        //需要加密的明文
        String text = "我是一段测试aaaa";
        //创建sm2 对象
        SM2 sm2 = SmUtil.sm2();
        //这里会自动生成对应的随机秘钥对 , 注意! 这里一定要强转,才能得到对应有效的秘钥信息
        byte[] privateKey = BCUtil.encodeECPrivateKey(sm2.getPrivateKey());
        //这里公钥不压缩  公钥的第一个字节用于表示是否压缩  不压缩才是65的长度
        byte[] publicKey = ((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false);
        //原始公私秘钥
         byte[] oldprivateKey = BCUtil.encodeECPrivateKey(sm2.getPrivateKey());
         byte[] oldpublicKey = BCUtil.encodeECPublicKey(sm2.getPublicKey());
        System.out.println("原始私钥: " + HexUtil.encodeHexStr(oldprivateKey));
        System.out.println("原始公钥: " + HexUtil.encodeHexStr(oldpublicKey));
        //这里得到的 压缩后的公钥   ((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(true);
        // byte[] publicKeyEc = BCUtil.encodeECPublicKey(sm2.getPublicKey());
        //打印当前的公私秘钥
        System.out.println("变换私钥: " + HexUtil.encodeHexStr(privateKey));
        System.out.println("变换公钥: " + HexUtil.encodeHexStr(publicKey));
        //还原公私秘钥
        //将密钥还原回sm2对象
        PrivateKey privateKey1 = sm2.getPrivateKey();
        PublicKey publicKey1 = sm2.getPublicKey();
        SM2 huanyuan = SmUtil.sm2(privateKey1,publicKey1);
        //打印还原后的公私秘钥
        System.out.println("还原私钥: " + HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(huanyuan.getPrivateKey())));
        System.out.println("还原公钥: " + HexUtil.encodeHexStr(BCUtil.encodeECPublicKey(huanyuan.getPublicKey())));


        //sm3计算
        String s1 = SmUtil.sm3(text);
        //得到明文对应的字节数组
        byte[] dateBytes = (s1+text).getBytes();
        System.out.println("数据: " + HexUtil.encodeHexStr(dateBytes));

        //sm2计算
        String s = HexUtil.encodeHexStr(sm2.encrypt(dateBytes));
        System.out.println("加密后: " +s);

        //sm2解密
        String s2 = new String(sm2.decrypt(HexUtil.decodeHex(s)));
        System.out.println("解密后: " + s2);

        //这里需要手动设置,sm2 对象的默认值与我们期望的不一致
        sm2.setMode(SM2Engine.Mode.C1C2C3);
        sm2.setEncoding(new PlainDSAEncoding());

        //sm2计算签名
        byte[] sign = sm2.sign(dateBytes, null);
        System.out.println("签名: " + HexUtil.encodeHexStr(sign));
        //sm2 校验  验签
        boolean verify = sm2.verify(dateBytes, sign);
        //sm3 检验
        boolean verify1 = SmUtil.sm3(s2.substring(64)).equals(s2.substring(0,64));

         System.out.println("Sm2验签"+verify);
        System.out.println("Sm3验签"+verify1);
    }
}

3、使用

直接在接口上@AutoSmUtil

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值