注解形式优雅实现用SM4对称算法实现加解密

项目场景:

需要将数据入库时进行加密,查询时对数据进行解密,这里算法使用SM4国密对称算法;
为了使用起来更加优雅,这里使用自定义类型转换器,在实体的属性上注解上指定自定义的类型转换器,便可以自动实现数据的加密解密

代码实现

@Slf4j
@MappedTypes(String.class)
public class EncrpTypeHandler extends BaseTypeHandler<String> {

    private static SymmetricCrypto SM4;

    /**
     * 初始化加密类
     *
     * @param key 密钥key
     * @param iv  加密偏移量
     */
    public synchronized static void initEncrypt(String key, String iv) {

        if (SM4 == null) {
            SM4 = new SM4(CBC, ZeroPadding, key.getBytes(CharsetUtil.CHARSET_UTF_8), iv.getBytes(CharsetUtil.CHARSET_UTF_8));
        } else {
            throw new IllegalStateException("加密类已经初始化,不允许二次初始化!");
        }
    }

    /**
     * 非空字段加密
     *
     * @param preparedStatement
     * @param i
     * @param parameter
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, String parameter, JdbcType jdbcType) {
        try {
            if (StrUtil.isBlank(parameter)) {
                return;
            }
            String encrypt = encrypt(parameter);
            preparedStatement.setString(i, encrypt);
        } catch (Exception e) {
            log.error("typeHandler加密异常:{}", e.getMessage());
        }
    }

    /**
     * 非空字段解密  使用列名
     *
     * @param resultSet
     * @param columnName
     * @return
     * @throws SQLException
     */
    @Override
    public String getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        String col = resultSet.getString(columnName);
        try {
            if (StrUtil.isBlank(col)) {
                return col;
            }
            return decrypt(col);
        } catch (Exception e) {
            log.error("typeHandler解密异常:{}", e.getMessage());
        }
        return col;
    }

    /**
     * 可空字段解密 使用下标
     *
     * @param resultSet
     * @param columnIndex
     * @return
     * @throws SQLException
     */
    @Override
    public String getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        String col = resultSet.getString(columnIndex);
        try {
            if (StrUtil.isBlank(col)) {
                return col;
            }
            return decrypt(col);
        } catch (Exception e) {
            log.error("typeHandler解密异常:{}", e.getMessage());
        }
        return col;
    }

    /**
     * 可空字段解密 存储过程专用
     *
     * @param callableStatement
     * @param columnIndex
     * @return
     * @throws SQLException
     */
    @Override
    public String getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        String col = callableStatement.getString(columnIndex);
        try {
            if (StrUtil.isBlank(col)) {
                return col;
            }
            return decrypt(col);
        } catch (Exception e) {
            log.error("typeHandler解密异常:{}", e.getMessage());
        }
        return col;
    }

    /**
     * sm4加密算法
     *
     * @param plainTxt
     * @return
     */
    public String encrypt(String plainTxt) {

        if (SM4 == null) {
            throw new IllegalStateException("加密类未设置密钥!");
        }
        if (StringUtils.isEmpty(plainTxt)) {
            return plainTxt;
        }
        byte[] encrypHex = SM4.encrypt(plainTxt);
        String cipherTxt = Base64.encode(encrypHex);
        return cipherTxt;
    }

    /**
     * sm4解密算法
     *
     * @param cipherTxt
     * @return
     */
    public String decrypt(String cipherTxt) {

        if (SM4 == null) {
            throw new IllegalStateException("加密类未设置密钥!");
        }
        if (StringUtils.isEmpty(cipherTxt)) {
            return cipherTxt;
        }
        byte[] cipherHex = Base64.decode(cipherTxt);
        String plainTxt = SM4.decryptStr(cipherHex, CharsetUtil.CHARSET_UTF_8);
        return plainTxt;
    }
}
@TableField(typeHandler = EncrpTypeHandler.class)
private String password;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是用JavaScript实现AES算法的CBC模式加解密算法的示例代码: ```javascript // 定义AES加解密算法函数 function aesCBC(operation, key, iv, data) { var aesAlgorithm = "AES-CBC"; var blockSize = 16; var keyObj = CryptoJS.enc.Hex.parse(key); var ivObj = CryptoJS.enc.Hex.parse(iv); var dataObj = CryptoJS.enc.Hex.parse(data); var encryptedDataObj; // 根据操作类型选择加密或解密算法 if (operation === "encrypt") { encryptedDataObj = CryptoJS.AES.encrypt(dataObj, keyObj, { iv: ivObj, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, }); } else if (operation === "decrypt") { encryptedDataObj = CryptoJS.AES.decrypt(dataObj, keyObj, { iv: ivObj, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, }); } // 返回加解密结果 return encryptedDataObj.toString(CryptoJS.enc.Hex); } // 示例使用:加密 var key = "0123456789abcdef0123456789abcdef"; var iv = "0123456789abcdef0123456789abcdef"; var data = "0123456789abcdef0123456789abcdef"; var encryptedData = aesCBC("encrypt", key, iv, data); console.log("加密后的数据:" + encryptedData); // 示例使用:解密 var decryptedData = aesCBC("decrypt", key, iv, encryptedData); console.log("解密后的数据:" + decryptedData); ``` 这里使用了CryptoJS这个JavaScript库来实现AES算法的CBC模式加解密。其中,`aesCBC`函数接受四个参数: - `operation`:操作类型,可以是`encrypt`(加密)或`decrypt`(解密)。 - `key`:密钥,使用16进制字符串表示。 - `iv`:初始化向量,使用16进制字符串表示。 - `data`:待加密或解密的数据,使用16进制字符串表示。 函数中使用`CryptoJS.AES.encrypt`和`CryptoJS.AES.decrypt`分别进行加密和解密操作,其中`iv`参数表示CBC模式中的初始化向量,`mode`参数表示加密模式,`padding`参数表示填充模式。 示例中使用`console.log`打印加解密结果。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值