濮阳杆衣贸易有限公司

主頁 > 知識庫 > MySQL利用AES_ENCRYPT()與AES_DECRYPT()加解密的正確方法示例

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

熱門標簽:百度地圖標注地方備注 地圖標注圖標素材入駐 電銷機器人價格多少錢一臺 好搜地圖標注 400電話申請什么好 電話機器人免費嗎 怎么辦理400電話呢 龍圖酒吧地圖標注 怎么申請400電話申請

前言

最近在工作中遇到一個需求是這樣的:需要在使用AES_ENCRYPT()函數(shù)將明文加密,存儲在MySQL中,但是遇到了一些問題……下面就來詳細介紹下。

說將加密后的密文,解密取出來是NULL。

看了一下,她發(fā)過來的表結構:

再看了她通過AES_DECRYPT()函數(shù)加密了一個字符串,然后insert進去了,執(zhí)行成功后,顯示了一個warning:
Query OK, 1 row affected, 1 warning (0.00 sec)

(沒有報錯而是warning,大概是sql_mode的緣故)

此時她忽略了這個warning,再通過AES_DECRYPT()解密后,發(fā)現(xiàn)取出來的明文為NULL。

再回看表結構,發(fā)現(xiàn)其字段屬性為“varchar” 字符集是ut8,檢查warning為下:

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)

查了一下文檔,看一下這兩個函數(shù)的使用:

-- 將'hello world'加密,密鑰為'key',加密后的串存在@pass中
mysql> SET @pass=AES_ENCRYPT('hello world', 'key'); 
Query OK, 0 rows affected (0.00 sec)

-- 看一下加密后串的長度(都為2的整數(shù)次方)
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類型,等二進制字段屬性。

創(chuàng)建三個字段,屬性分別為varbinary、binary、blob。

并將'明文1','text2','明文_text3'加密,密鑰為key,存入表中。

最后取出。

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()取出。

創(chuàng)建一個字符串屬性的字段。

將'hello world'先用密鑰'key2'進行AES加密,再將加密后的串通過HEX函數(shù)十六進制化。

最后先將加密后的串通過UNHEX取出,再通過AES據(jù)密鑰'key2'解密:

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)

同樣,根據(jù)明文的長度不同,AES_ENCRYPT加密后的串長度也會有所變化,所以HEX后的字符串長度也會有所變化。
實際使用時,需要據(jù)業(yè)務評估出一個合理值即可。

方法③:

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

回溯到問題的一開始,將加密后的串,存到utf8字符集并且屬性為varchar中,是不行的。

實際上,將字符集改成latin1就可以了:

在insert的時候也不會報warning了。

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中,那么還是參考方法②,十六進制化一下吧。

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

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

參考文檔:

Chapter 12 Functions and Operators - 12.13 Encryption and Compression Functions

您可能感興趣的文章:
  • The MySQL server is running with the --read-only option so it cannot execute this statement
  • mysql數(shù)據(jù)庫mysql: [ERROR] unknown option ''--skip-grant-tables''
  • mysql視圖之確保視圖的一致性(with check option)操作詳解
  • MySQL存儲表情時報錯:java.sql.SQLException: Incorrect string value:‘\xF0\x9F\x92\xA9\x0D\x0A...’的解決方法
  • Mysql中的NULL和Empty String
  • javascript連接mysql與php通過odbc連接任意數(shù)據(jù)庫的實例
  • ubuntu下apt-get安裝和徹底卸載mysql詳解
  • mysql server is running with the --skip-grant-tables option
  • 利用pt-heartbeat監(jiān)控MySQL的復制延遲詳解
  • MySQL pt-slave-restart工具的使用簡介

標簽:浙江 溫州 內江 撫順 汕尾 防疫工作 固原 廣西

巨人網絡通訊聲明:本文標題《MySQL利用AES_ENCRYPT()與AES_DECRYPT()加解密的正確方法示例》,本文關鍵詞  MySQL,利用,AES,ENCRYPT,與,DECRYPT,;如發(fā)現(xiàn)本文內容存在版權問題,煩請?zhí)峁┫嚓P信息告之我們,我們將及時溝通與處理。本站內容系統(tǒng)采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《MySQL利用AES_ENCRYPT()與AES_DECRYPT()加解密的正確方法示例》相關的同類信息!
  • 本頁收集關于MySQL利用AES_ENCRYPT()與AES_DECRYPT()加解密的正確方法示例的相關信息資訊供網民參考!
  • 推薦文章
    周宁县| 康乐县| 鲁甸县| 大石桥市| 长海县| 芮城县| 喜德县| 新泰市| 阿鲁科尔沁旗| 泰兴市| 南川市| 利津县| 同仁县| 进贤县| 金昌市| 乌兰察布市| 德阳市| 和政县| 徐水县| 休宁县| 罗江县| 桑日县| 陇南市| 玉树县| 阆中市| 新泰市| 金华市| 永丰县| 长宁区| 郴州市| 东台市| 文化| 麦盖提县| 佛坪县| 神农架林区| 寿光市| 荥经县| 吴旗县| 阿鲁科尔沁旗| 剑阁县| 西充县|