MySQL敏感数据加密的实现方案

 更新时间:2024年02月26日 09:12:08   作者:纵然间  
这篇文章主要介绍了MySQL敏感数据加密的实现方案,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值 ,需要的朋友可以参考下

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

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('15101123111', 'test_key'), aes_encrypt('372522195710100019','test_key'));
	
mysql> insert into user(username, mobile, id_card) values('Mary', aes_encrypt('15101123111', 'key'), aes_encrypt('372522195710100019','key'));

注意:这里在使用**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      | 15101123111 |
+----+----------+-------------+

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类型中,在做字符转换的时或空格被删除时,可能会带来潜在的影响。

以上就是MySQL敏感数据加密的实现方案的详细内容,更多关于MySQL敏感数据加密的资料请关注脚本之家其它相关文章!

相关文章

  • Mysql中实现修改主键自增值

    Mysql中实现修改主键自增值

    这篇文章主要介绍了Mysql中实现修改主键自增值方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • MySQL 字符类型大小写敏感

    MySQL 字符类型大小写敏感

    这篇文章主要介绍了MySQL 字符类型大小写敏感的相关资料,帮助大家更好的理解和使用MySQL数据库,感兴趣的朋友可以了解下
    2020-12-12
  • linux mysql 安装与操作

    linux mysql 安装与操作

    mysql是linux平台下最流行的数据库系统,今天介绍的是mysql的安装及简单的操作方法!
    2009-06-06
  • 使用SQL查询所有数据库名和表名问题

    使用SQL查询所有数据库名和表名问题

    这篇文章主要介绍了使用SQL查询所有数据库名和表名问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • mysql导入导出数据的示例详解

    mysql导入导出数据的示例详解

    本文主要介绍了MySQL 导出和导入数据的几种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05
  • mysql 5.7.17 winx64免安装版配置方法图文教程

    mysql 5.7.17 winx64免安装版配置方法图文教程

    这篇文章主要为大家详细介绍了mysql 5.7.17 winx64免安装版配置方法图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • 在centOS 7安装mysql 5.7的详细教程

    在centOS 7安装mysql 5.7的详细教程

    这篇文章主要介绍了在centOS 7安装mysql 5.7的详细教程,非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2016-12-12
  • Mysql事物阻塞的实现

    Mysql事物阻塞的实现

    本文主要介绍了Mysql事物阻塞的实现,阻塞并不是一件坏事,其是为了确保事务可以并发且正常地运行,具有一定的参考价值,感兴趣的可以了解一下
    2024-04-04
  • Mysql 错误问题汇总(不断更新中)

    Mysql 错误问题汇总(不断更新中)

    Mysql 错误问题汇总,我们在开发过程中经常看到mysql的一些错误,这里整理下,方便需要的朋友
    2012-07-07
  • mysql容器之间的replication配置实例详解

    mysql容器之间的replication配置实例详解

    这篇文章主要给大家介绍了关于mysql容器之间replication配置的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01

最新评论