mysql敏感数据加密-Java版

60 篇文章 0 订阅

MySQL敏感数据加密-Java实现方案

一、准备工作(环境要求)

1、版本要求

​ mysql必须是mysql5.6以上版本,通过以下命令查看是否版本支持

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.24    |
+-----------+

2、字段类型要求

​ 数据表字段类型必须是以下类型中的其中一个

 varbinary、binary、blob

二、数据库演示

1、创建演示表

mysql> CREATE TABLE `user` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(20) DEFAULT NULL,
  `mobile` varbinary(50) NOT NULL,
  `id_card` varbinary(155) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

注意: mobile(手机号) 和 id_card(身份证号) 的字段类型为varbinary,我们将对这两个字段进行加密存储。

2、插入加密数据

mysql> insert into user(username, mobile, id_card) 
	values('Tom', aes_encrypt('15101123333', 'test_key'), aes_encrypt('372522195710100019','test_key'));
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0

mysql> insert into user(username, mobile, id_card) values('Mary', aes_encrypt('15101123333', 'key'), aes_encrypt('372522195710100019','key'));
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0

注意:这里在使用insert 插入时,将需要加密的字段使用aes_encrypt函数并指定秘钥key。

3、查看插入数据

mysql> select * from user;

-----------++----+----------+------------------------------------+---------------------------------------------------------
| id | username | mobile                             | id_card                                                            |
+----+----------+------------------------------------+--------------------------------------------------------------------+
|  1 | Tom      | 0x28E415A075D38ECFEE0AFB86027231BD | 0x45397D31A49C50EEFE669D2145110F134A90D6E834084FBA38E4B5098F2EDAED |
|  2 | Mary     | 0xC932282B9EBC4FC82A225A56FB12BB63 | 0xF748DFDB3C0994DB9C06F4FB863AAAE5DC1685EA49D8AAA5C28952D5BFDD8A35 |
+----+----------+------------------------------------+--------------------------------------------------------------------+

**提示:**此处是直接查询,返回的是加密后的值,神仙也看不出是啥,如果猜测的话首先要猜出加密方式,其次是秘钥。

4、解密数据

mysql> select id, username, cast(aes_decrypt(mobile, 'test_key') as char charset utf8 ) as mobile from user where id = 1;
+----+----------+-------------+
| id | username | mobile      |
+----+----------+-------------+
|  1 | Tom      | 15101123174 |
+----+----------+-------------+

mysql> select id, username, cast(aes_decrypt(id_card, 'key') as char charset utf8 ) as id_card from user where id = 2;
+----+----------+--------------------+
| id | username | id_card            |
+----+----------+--------------------+
|  2 | Mary     | 372522195710100019 |
+----+----------+--------------------+

注意:

​ 1)、id为1的那条数据的加密密钥为key 为 test_key,

​ id 为2的加密密钥为key 为 key 。 解密时如果密钥不对将查询结果为null

​ 2)、解密函数aes_decrypt 外层需要使用cast 进行处理,否则将返回二进制值而不是解密后的值。

三、Java + mybatis 实现加解密

1、Java代码中什么都不需要动

提示: 此处java使用的是mybatis持久化数据,如果使用hibernatemybatis-plus等框架,请自行研究,理论上通用但需要变通一下

2、mybatis中插入和更新用法

<!-- 插入 -->
<insert id="saveCertificate" parameterType="com.test.candidate.bean.Certificate">
        insert into certificate (
            oa_serial,
            begin_date,
            end_date,
            certificate_type,
            certificate_code,
            certificate_code_again,
            address,
            country,
            created_at,
            updated_at
        ) values (
            #{oaSerial},
            #{beginDate},
            #{endDate},
            #{certificateType},
            AES_ENCRYPT(#{certificateCode,jdbcType=VARCHAR},'perinfo'),
            AES_ENCRYPT(#{certificateCodeAgain,jdbcType=VARCHAR},'perinfo'),
            #{address},
            #{country},
            #{createdAt},
            #{updatedAt}
        );
    </insert>
    
    <!-- 更新 -->
     <update id="updateCertificate" parameterType="com.test.candidate.bean.Certificate">
        update certificate set
            begin_date = #{beginDate},
            end_date = #{endDate},
            certificate_type = #{certificateType},
            certificate_code = AES_ENCRYPT(#{certificateCode,jdbcType=VARCHAR},'perinfo'),
            certificate_code_again = AES_ENCRYPT(#{certificateCodeAgain,jdbcType=VARCHAR},'perinfo'),
            address = #{address},
            country = #{country},
            updated_at = #{updatedAt}
        where oa_serial = #{oaSerial} and id = #{id}
    </update>

**注意:**插入和更新是加密:AES_ENCRYPT(#{certificateCode,jdbcType=VARCHAR},‘perinfo’),

3、mybatis中查询用法

<!-- 查询 -->
<select id="findList" resultMap="PartCertificateMap">
        SELECT
            begin_date,
            end_date,
            certificate_type,
            cast(AES_DECRYPT(certificate_code,'perinfo') as char charset utf8) certificate_code,
            cast(AES_DECRYPT(certificate_code_again,'perinfo') as char charset utf8) certificate_code_again,
            address,
            country
         FROM certificate
        where
         oa_serial = #{oaSerial}
    </select>

**注意:**查询时解密:cast(AES_DECRYPT(certificate_code,‘perinfo’) as char charset utf8) certificate_code,

四、其他说明

网上有人说无需更改数据类型,直接将加密数据存储到carchar类型的字段中,然后将字符集改成latin1, 虽然此种方式确实也能实现加解密,但是mysql中insert 时,会报warning, 并且可能会带来隐患,使用以下命令查看警告信息

mysql> show warnings();

并不推荐此种方式:

mysql> CREATE TABLE t_passwd_3(pass varchar(32)) CHARSET latin1;
Query OK, 0 rows affected (0.00 sec)
 
mysql> INSERT INTO t_passwd_3 SELECT AES_ENCRYPT('text', 'key3');
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
 
mysql> SELECT AES_DECRYPT(pass, 'key3') FROM t_passwd_3;
+---------------------------+
| AES_DECRYPT(pass, 'key3') |
+---------------------------+
| text   |
+---------------------------+
1 row in set (0.00 sec)

MySQL官方给出的描述信息如下:

Many encryption and compression functions return strings for which the result might contain arbitrary byte values. If you want to store these results, use a column with a VARBINARY or BLOB binary string data type. This will avoid potential problems with trailing space removal or character set conversion that would change data values, such as may occur if you use a nonbinary string data type (CHAR, VARCHAR, TEXT).

大意是,如果用此方法,直接将加密后的串存入char/varchar/text类型中,在做字符转换的时或空格被删除时,可能会带来潜在的影响。

  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MySQL数据库中,实现敏感数据加密和解密有多种方式: 1. 使用数据库函数:可以使用MySQL提供的函数,如AES_ENCRYPT和AES_DECRYPT进行加密和解密。这些函数可以通过指定密钥和明文数据来进行加密,同时也可以使用相同的密钥和密文数据来进行解密。 2. 使用存储过程和触发器:可以在数据库中创建存储过程和触发器来自动加密和解密敏感数据。例如,可以创建一个存储过程,在插入或更新数据时先进行加密,而在读取数据时进行解密。 3. 使用数据库代理或中间件:可以使用第三方的数据库代理或中间件,如Transparent Data Encryption (TDE)或数据库防火墙来加密和解密数据。这些工具会自动在数据传输过程中进行加密和解密操作,对应用程序透明。 4. 使用应用程序层加解密:可以在应用程序中实现数据加密和解密的逻辑。在将数据存储到数据库之前,先使用加密算法对数据进行加密,在读取数据时再进行解密。这种方式可以灵活控制加密算法和密钥。 无论采用哪种方式,都需要注意以下几点: - 密钥管理:确保密钥的安全性,比如使用专门的密钥管理工具来管理和保护密钥。 - 性能影响:加解密操作可能会影响数据库的性能,需要评估加解密操作对数据库性能的影响,并进行必要的优化和调整。 - 数据完整性:加密和解密操作可能会引入数据不一致的问题,需要保证数据加密和解密过程中的数据完整性。 总结而言,MySQL数据库对敏感数据加密和解密的实现方式有多种选择,可以根据实际情况选择最合适的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵然间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值