MySQL利用AES_ENCRYPT()与AES_DECRYPT()加解密的正确方法示例

2023-11-05

前言

最近在工作中遇到一个需求是这样的:需要在使用AES_ENCRYPT()函数将明文加密,存储在MySQL中,但是遇到了一些问题……下面就来详细介绍下。

说将加密后的密文,解密取出来是NULL。

看了一下,她发过来的表结构:

再看了她通过AES_DECRYPT()函数加密了一个字符串,然后insert进去了,执行成功后,显示了一个warning:
Query OK, 1 row affected, 1 warning (0.00 sec)

(没有报错而是warning,大概是sql_mode的缘故)

此时她忽略了这个warning,再通过AES_DECRYPT()解密后,发现取出来的明文为NULL。

再回看表结构,发现其字段属性为“varchar” && 字符集是ut8,检查warning为下:

?

1

2

3

4

5

6

7

mysql> show warnings;

+---------+------+------------------------------------------------------------------------+

| Level | Code | Message        |

+---------+------+------------------------------------------------------------------------+

| Warning | 1366 | Incorrect string value: '\xE3f767\x12...' for column 'passwd' at row 1 |

+---------+------+------------------------------------------------------------------------+

1 row in set (0.00 sec)

查了一下文档,看一下这两个函数的使用:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

-- 将'hello world'加密,密钥为'key',加密后的串存在@pass中

mysql> SET @pass=AES_ENCRYPT('hello world', 'key');

Query OK, 0 rows affected (0.00 sec)

 

-- 看一下加密后串的长度(都为2的整数次方)

mysql> SELECT CHAR_LENGTH(@pass);

+--------------------+

| CHAR_LENGTH(@pass) |

+--------------------+

| 16   |

+--------------------+

1 row in set (0.00 sec)

 

-- 使用AES_DECRYPT()解密

mysql> SELECT AES_DECRYPT(@pass, 'key');

+---------------------------+

| AES_DECRYPT(@pass, 'key') |

+---------------------------+

| hello world  |

+---------------------------+

1 row in set (0.00 sec)

那么到底该如何存呢?

方法①: 

将字段属性设置为varbinary/binary/四个blob类型,等二进制字段属性。

创建三个字段,属性分别为varbinary、binary、blob。

并将'明文1','text2','明文_text3'加密,密钥为key,存入表中。

最后取出。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

mysql> CREATE TABLE t_passwd (pass1 varbinary(16), pass2 binary(16), pass3 blob);

Query OK, 0 rows affected (0.00 sec)

 

mysql> INSERT INTO t_passwd VALUES (AES_ENCRYPT('明文1', 'key'), AES_ENCRYPT('text2', 'key'), AES_ENCRYPT('明文_text3', 'key'));

Query OK, 1 row affected (0.01 sec)

 

mysql> SELECT AES_DECRYPT(pass1, 'key'), AES_DECRYPT(pass2, 'key'), AES_DECRYPT(pass3, 'key') FROM t_passwd;

+---------------------------+---------------------------+---------------------------+

| AES_DECRYPT(pass1, 'key') | AES_DECRYPT(pass2, 'key') | AES_DECRYPT(pass3, 'key') |

+---------------------------+---------------------------+---------------------------+

| 明文1   | text2   | 明文_text3   |

+---------------------------+---------------------------+---------------------------+

1 row in set (0.00 sec)

当然,属性括号内的长度要取决于明文的长度,此处明文较短,故只给了16。

方法②:

将密文十六进制化,再存入varchar/char列。

此处需要用到HEX()来存入,用UNHEX()取出。

创建一个字符串属性的字段。

将'hello world'先用密钥'key2'进行AES加密,再将加密后的串通过HEX函数十六进制化。

最后先将加密后的串通过UNHEX取出,再通过AES据密钥'key2'解密:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

mysql> CREATE TABLE t_passwd_2(pass1 char(32));

Query OK, 0 rows affected (0.01 sec)

 

mysql> INSERT INTO t_passwd_2 VALUES (HEX(AES_ENCRYPT('hello world', 'key2')));

Query OK, 1 row affected (0.00 sec)

 

mysql> SELECT AES_DECRYPT(UNHEX(pass1), 'key2') FROM t_passwd_2;

+-----------------------------------+

| AES_DECRYPT(UNHEX(pass1), 'key2') |

+-----------------------------------+

| hello world   |

+-----------------------------------+

1 row in set (0.00 sec)

同样,根据明文的长度不同,AES_ENCRYPT加密后的串长度也会有所变化,所以HEX后的字符串长度也会有所变化。
实际使用时,需要据业务评估出一个合理值即可。

方法③:

直接存入varchar中,不做十六进制化。

回溯到问题的一开始,将加密后的串,存到utf8字符集并且属性为varchar中,是不行的。

实际上,将字符集改成latin1就可以了:

在insert的时候也不会报warning了。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

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)

这样的方法虽然美,只需将字段字符集设置为latin1就可以了,但可能会带来隐患:

文档上写了这样的一句:

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

所以如果一定要存在char/varchar/text中,那么还是参考方法②,十六进制化一下吧。

或者如同方法①,直接存在二进制字段中。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL利用AES_ENCRYPT()与AES_DECRYPT()加解密的正确方法示例 的相关文章

  • php 连接池 mysql [重复]

    这个问题在这里已经有答案了 我打算使用MYSQL 有可用的连接池扩展吗 或者说连接的正常做法是什么 是不是到处都用这个啊 mysqli connect localhost xxx xxx test 人们正常使用吗mysql connect
  • 将所有 PHP 错误输出到数据库而不是 error_log

    是否可以将所有 PHP 错误写入 MySQL 而不是标准的 error log 文件 我想如果我从头开始编写自己的错误处理程序 这是可能的 但我有很多遗留代码 理想情况下我只需进行 1 个全局更改即可 这可以做到吗 我认为如果不构建自己的错
  • 无法在 Windows 中安装 mysql-python(较新版本)

    I have mysql pythonv1 2 4 在我的机器 Windows 8 上安装得很好 我正在使用Python 2 7 每次尝试升级到 v1 2 5 时 我总是遇到以下错误 从 v1 3 7 开始仍然发生 C Users User
  • 如何使用 mysqli 设置排序规则?

    我的数据库使用 utf8 czech ci 排序规则 我也想将其设置为我的数据库连接 如果我不想要默认的 utf8 general ci Mysqli set charset 不会让我设置排序规则 Here https bugs php n
  • 检查行是否存在,Laravel

    我有以下数据库结构 items id name user id users table id name user favorites table id user id item id 在我的项目永久链接页面上 我有一个 添加到收藏夹 按钮
  • Sql查询增加多个项目的项目价值价格

    我想编写 Sql 查询来按百分比增加商品价格 场景是 在表中 我有 3 列 ID 商品名称 价格 Example If item Name is T shirt Increase price by 10 item Name is Jins
  • 在 WHERE 子句中使用 mysql SUM()

    假设我有这张桌子 id cash 1 200 2 301 3 101 4 700 我想返回第一行 其中之前所有现金的总和大于某个值 例如 如果我想返回第一行 其中之前所有现金的总和大于 500 则应该返回到第 3 行 如何使用 mysql
  • 如何查询两个日期之间的“日期”字段是字符串?

    我在 MySQL 数据库中有一个表 其中有一个名为 日期 的字段 问题是日期的格式为 DD MM YYYY 因此我无法将其作为 DATE 类型字段上传到 MySQL 相反 字段类型是字符串 考虑到这一点 我如何编写能够产生这种效果的查询 S
  • 致命错误:在非对象上调用成员函数 FetchRow()

    这是我的错误消息致命错误 Call to a member function FetchRow on a non object in C AppServ www hfix include care api classes class min
  • 通过sql视图向多个表插入数据

    mysql 有没有办法通过视图向多个表插入数据 MySQL 参考手册对于可更新视图是这样说的 一些视图是可更新的 也就是说 您可以在诸如以下的语句中使用它们UPDATE DELETE or INSERT更新基础表的内容 为了使视图可更新 必
  • MySQL 选择 table01 中不存在于 table02 的行[重复]

    这个问题在这里已经有答案了 我有两个表 table03 有 10 行 table01 有 21 行 现在我想从 table03 中获取 table01 中不存在的行 到目前为止我编写了这个查询 但它显示了 table03 的所有行 即使有些
  • PHP - 简单嵌套无序列表 (UL) 数组

    我在 stackoverflow 上看到了这个嵌套 UL 数组问题的一些变体 但我认为我的比其他问题更简单 我正在寻找一个简单的数组循环 它允许无限量的主题 父项 和无限量的项目 子项 例如 ul li Topic li ul li Ite
  • 将 mysql 连接传递给 python 线程时管道损坏

    我正在尝试将 mysql 连接传递给 python 中的线程 如果我在工作类中进行 mysql 的初始化 则不会出现错误 但是 连接的成本可能很高 因此我尝试仅从调用者函数传递 mysql 连接 请参见下面的代码 但这一直抛出这个错误 20
  • mysql数据库的“零知识”加密

    我一直在研究 Web 应用程序数据库层的加密 它使用MySQL 5 1 或更高版本 我记不清了 该应用程序由我的组织管理 为公共客户存储数据 最简单的选择是 AES ENCRYPT AES DECRYPT 如果坏人以某种方式访问 我的数据库
  • 如何将mysql的默认端口从3306更改为3360

    我想更改MySQL服务器的默认端口号 目前它是3306 我想将其更改为3360 我努力了 port 3360 但事情对我不起作用 请提供更改端口的查询 而不是任何配置 我使用的是 Windows 8 64 位 您需要编辑您的my cnf文件
  • SQL仅选择列上具有最大值的行[重复]

    想要改进这篇文章吗 提供此问题的详细答案 包括引用和解释为什么你的答案是正确的 不够详细的答案可能会被编辑或删除 这个问题在这里已经有答案了 我有这个文件表 这里是简化版本 id rev content 1 1 2 1 1 2 1 3 如何
  • 按日期和时间降序排序?

    全部 我想显示特定 id 最后输入的 5 条数据 我的sql查询是 SELECT id name form id DATE updated at as date FROM wp frm items WHERE user id 11 form
  • SELECT MySQL 字段包含子字符串[重复]

    这个问题在这里已经有答案了 使用 LIKE 在 MySQL 中非常常见 我们这样使用它 WHERE field LIKE substring 我们有一个子字符串 并且字段有完整的字符串 但我需要的是相反的东西 我在字段中有子字符串 所以 我
  • MySQL:进行基本搜索

    我的数据库中有一个名称表 我希望对其进行模糊搜索 例如我的数据库包含 Name ID John Smith 1 Edward Smith 2 Gabriel Gray 3 Paul Roberts 4 目前 当我通过 python 搜索数据
  • 错误 1366 (HY000):整数值不正确:第 1 行的列“id”的“”[已关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 My code sql INSERT INTO static table name sql join array key

随机推荐

  • unity3d-血条的设计

    任务目标 完成血条的预制设计 任务要求 分别使用 IMGUI 和 UGUI 实现 使用 UGUI 血条是游戏对象的一个子元素 任何时候需要面对主摄像机 分析两种实现的优缺点 给出预制的使用方法 实现过程 使用IMGUI实现 创建一个空对象
  • linux系统下常用的激活命令总结

    linux系统下常用的激活命令总结 作为一个刚入门linux的小白 很多的命令用了之后又会忘记 所以记录一下 方便后面回头查询 1 退出base环境 在terminal或者 bashrc文件中把conda自动启动设置为 false cond
  • Redis可视化客户端

    Redis是一个超精简的基于内存的键值对数据库 key value 一般对并发有一定要求的应用都用其储存session 乃至整个数据库 redis的可视化客户端目前较流行的有三个 Redis Client Redis Desktop Man
  • Vue 3 中的 Suspense 是什么?如何使用它

    Vue 3 中的 Suspense 是什么 如何使用它 介绍 Vue 3 是 Vue js 的最新版本 引入了一些令人兴奋的新功能和改进 其中之一是 Suspense 中文翻译为 暂停 机制 Suspense 是一种用于处理异步组件和延迟加
  • 教你App如何上架应用宝----腾讯开放开发平台

    上架app视频 http v youku com v show id XMTU0NTM1MTczNg html from y1 7 1 2 paction app在腾讯的 应用宝 市场 输入 czg学习演示 可以下载 注意 上架app视频的
  • 冒泡排序算法的Python实现(头歌实践教学平台)

    第1关 冒泡排序的实现 任务描述 本关任务 编写代码实现冒泡排序 相关知识 为了完成本关任务 你需要掌握 1 如何实现冒泡排序 2 冒泡排序的算法分析 冒泡排序 冒泡排序又称起泡排序 它的算法思路在于对无序表进行多趟比较交换 每趟都包括了多
  • ERROR: cannot launch node of type [turtlesim/turtlesim_node]

    这个之前路径是正确的 没有文档里说的那个BUG 为什么后续运行roslaunch rename01 node start turtle launch 的时候还是会报错呢 还是会出现 ERROR cannot launch node of t
  • 继承的详细介绍与理解,看了就懂

    继承的介绍 继承的概念及定义 定义格式 继承基类成员访问方式的变化 基类和派生类对象赋值转换 继承中的作用域 派生类的默认成员函数 继承与友元 继承与静态成员 复杂的菱形继承及菱形虚拟继承 总结 继承的概念及定义 继承也是面向对象的三大特性
  • ASM学习——开端

    什么是ASM ASM是一个操作java字节码的类库 ASM的操作对象 字节码 bytecode 数据 一个java文件经过java编译器javac编译之后会生成 class文件 在 class文件中 存储的就是字节码数据 ASM的操作对象就
  • XSL-FO 高级技术4

    概述 第 1 页 共7 页 既然您已经了解了定义打印页面外观的基本元素 现在让我们研究其它 XSL FO 元素 这些元素可以使 PDF 文档看上去更专业 本章将讨论下列主题 定义多页布局 添加页眉和页脚 对页面编号 用 Page x of
  • verilog/systemverilog的随机数生成问题

    Verilog SystemVerilog 里面的随机函数 Verilog系统自带一些随机数发生函数 最常用的有random 语法如下 random seed 指定概率分布 如果希望生成的随机数具有一定的概率分布 还有一些系统函数可以选用
  • webview页面有很多图片加载慢的处理方式

    dangwebview加载有很多图片的网页时会很慢 此时可以用webview的setBlockNetworkImage方法 在开始加载的时候使用 webview getSettings setBlockNetworkImage true 在
  • 云计算运营—01华为云计算解决方案介绍

    华为云计算解决方案介绍 文章目录 华为云计算解决方案介绍 一 FusionSphere虚拟化解决方案介绍 云操作系统架构 FusionCompute组成 FusionManager FusionStorage FS相比传统存储的优势 应用场
  • matplotlib 自带绘图样式效果展示速查(28种,全)

    matplotlib 自带绘图样式效果展示速查 28种 全 目 录 一 matplotlib 自带所有绘图样式效果展示 0 没有加style时的绘图风格 1 加 bmh style时的绘图风格 2 加 classic style时的绘图风格
  • 详解浏览器渲染原理及流程

    今天来分享一下浏览器的渲染原理及流程 前言 先来看看 Chrome 浏览器的多进程架构 通常 我们打包出来的 HTML CSS JavaScript 等文件 经过浏览器运行之后就会显示出页面 这个过程就是浏览器的渲染进程来操作实现的 渲染进
  • 网络通信设备之网络路由技术详解

    一 路由器简介 路由器是构成IP网络的核心 其最基本的作用就是连接不同类型的网络 智能选择最佳的信息传送线路 除此以外 路由器还具有访问控制功能 路由器也可以算作是一台专用计算机 可以听懂并翻译各种网络协议 就像一个会讲各种语言的人一样 1
  • 50个查询系列-第三个查询:查询所有同学的学号、姓名、选课数、总成绩;

    查询最主要的就是确定查询的主表 和辅助表 这个的话我们可以确认是用子查询 主表就是我们的学生表 tblstudent可以查到学生的学号 姓名 辅助表就是成绩表 tblscore 自己写的语句如下 SELECT tblstudent StuI
  • 在虚拟机中安装Windows Server2016

    先介绍一些比较有用的文章 但可能与本文没有直接关系 将windows server 2016改造为像windows 10一样适合个人使用的系统 Windows Server 2016 配置指南 事先说明 千万不要提前分区 没有意义 什么都不
  • 十一、Node.js

    一 Node js是什么 在了解Node js之前 我们先去了解一下什么叫v8引擎 这里参考一下其他博主的资料 聊聊V8引擎 努力学习前端的77的博客 CSDN博客 这个时候我们再去看下Node js的定义 官方对Node js的定义 No
  • MySQL利用AES_ENCRYPT()与AES_DECRYPT()加解密的正确方法示例

    前言 最近在工作中遇到一个需求是这样的 需要在使用AES ENCRYPT 函数将明文加密 存储在MySQL中 但是遇到了一些问题 下面就来详细介绍下 说将加密后的密文 解密取出来是NULL 看了一下 她发过来的表结构 再看了她通过AES D