>데이터 베이스 >MySQL 튜토리얼 >MySQL이 암호화 및 암호 해독을 위해 AES_ENCRYPT() 및 AES_DECRYPT()를 사용하는 방법의 예

MySQL이 암호화 및 암호 해독을 위해 AES_ENCRYPT() 및 AES_DECRYPT()를 사용하는 방법의 예

黄舟
黄舟원래의
2018-05-18 16:55:462896검색

MySQL의 AES_ENCRYPT('password', 'key') 함수는 필드 값을 암호화할 수 있고, AES_DECRYPT(테이블의 필드 이름, 'key') 함수는 값을 해독할 수 있습니다. 다음 글에서는 주로 필드 값의 사용법을 소개합니다. MySQL의 AES_ENCRYPT() 및 AES_DECRYPT() 암호화 및 암호 해독에 대한 자세한 샘플 코드가 제공되며 필요한 친구는 이를 참조할 수 있습니다.

머리말

최근 직장에서 요구 사항에 직면했습니다. 일반 텍스트를 암호화하고 MySQL에 저장하려면 AES_ENCRYPT() 함수를 사용해야 하는데 몇 가지 문제가 발생했습니다.. .…아래에서 자세히 소개하겠습니다. AES_ENCRYPT()函数将明文加密,存储在MySQL中,但是遇到了一些问题……下面就来详细介绍下。

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

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

再看了她通过AES_DECRYPT()函数加密了一个字符串,然后insert进去了,执行成功后,显示了一个warning:<br>

Query OK, 1 row affected, 1 warning (0.00 sec)

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

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

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

mysql> show warnings;
+---------+------+------------------------------------------------------------------------+
| Level | Code | Message        |
+---------+------+------------------------------------------------------------------------+
| Warning | 1366 | Incorrect string value: &#39;\xE3f767\x12...&#39; for column &#39;passwd&#39; at row 1 |
+---------+------+------------------------------------------------------------------------+
1 row in set (0.00 sec)

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

-- 将&#39;hello world&#39;加密,密钥为&#39;key&#39;,加密后的串存在@pass中
mysql> SET @pass=AES_ENCRYPT(&#39;hello world&#39;, &#39;key&#39;); 
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, &#39;key&#39;);
+---------------------------+
| AES_DECRYPT(@pass, &#39;key&#39;) |
+---------------------------+
| hello world  |
+---------------------------+
1 row in set (0.00 sec)

那么到底该如何存呢?

方法①:

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

创建三个字段,属性分别为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(&#39;明文1&#39;, &#39;key&#39;), AES_ENCRYPT(&#39;text2&#39;, &#39;key&#39;), AES_ENCRYPT(&#39;明文_text3&#39;, &#39;key&#39;)); 
Query OK, 1 row affected (0.01 sec)
mysql> SELECT AES_DECRYPT(pass1, &#39;key&#39;), AES_DECRYPT(pass2, &#39;key&#39;), AES_DECRYPT(pass3, &#39;key&#39;) FROM t_passwd;
+---------------------------+---------------------------+---------------------------+
| AES_DECRYPT(pass1, &#39;key&#39;) | AES_DECRYPT(pass2, &#39;key&#39;) | AES_DECRYPT(pass3, &#39;key&#39;) |
+---------------------------+---------------------------+---------------------------+
| 明文1   | text2   | 明文_text3   |
+---------------------------+---------------------------+---------------------------+
1 row in set (0.00 sec)

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

方法②:

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

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

암호화된 암호문을 복호화한 후 NULL이 된다는 뜻입니다.


그녀가 보낸 테이블 구조를 살펴보세요:


다시 살펴보면 AES_DECRYPT() 함수를 통해 문자열을 암호화한 후 삽입했습니다. 실행이 성공한 후 경고가 표시되었습니다.

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(&#39;hello world&#39;, &#39;key2&#39;)));
Query OK, 1 row affected (0.00 sec)
mysql> SELECT AES_DECRYPT(UNHEX(pass1), &#39;key2&#39;) FROM t_passwd_2; 
+-----------------------------------+
| AES_DECRYPT(UNHEX(pass1), &#39;key2&#39;) |
+-----------------------------------+
| hello world   |
+-----------------------------------+
1 row in set (0.00 sec)

(오류는 없지만 경고는 sql_mode 때문일 듯)

이때 경고를 무시한 후 AES_DECRYPT()를 통해 복호화하여 발견한 내용 제거되었습니다. 일반 텍스트가 NULL입니다. 테이블 구조를 다시 살펴보면 필드 속성이 "varchar" &&이고 문자 집합이 ut8임을 확인했습니다.

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(&#39;text&#39;, &#39;key3&#39;);
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0

mysql> SELECT AES_DECRYPT(pass, &#39;key3&#39;) FROM t_passwd_3;
+---------------------------+
| AES_DECRYPT(pass, &#39;key3&#39;) |
+---------------------------+
| text   |
+---------------------------+
1 row in set (0.00 sec)

문서를 확인하고 사용 방법을 살펴보세요. 이 두 가지 기능은

rrreee

그럼 어떻게 저장하나요?


방법 ①:

필드 속성을 varbinary/binary/4 blob 유형으로 설정하고 기타 바이너리 필드 속성을 설정합니다.

varbinary, binary 및 blob 속성을 사용하여 세 개의 필드를 만듭니다.

'plaintext1', 'text2', 'plaintext_text3'을 키 키로 암호화하여 테이블에 저장합니다.

마지막으로 꺼내세요.

rrreee

물론, 속성 괄호 안의 길이는 평문의 길이에 따라 달라집니다. 여기서 평문은 더 짧아서 16개만 주어집니다. 방법 ②:

🎜🎜🎜🎜암호문을 16진수로 변환한 후 varchar/char 열에 저장합니다. 🎜🎜🎜여기서 입금하려면 HEX()를 사용하고 출금하려면 UNHEX()를 사용해야 합니다. 🎜🎜문자열 속성이 있는 필드를 만듭니다. 🎜🎜🎜'key2' 키를 사용하여 AES로 'hello world'를 암호화한 다음 HEX 함수를 통해 암호화된 문자열을 16진수로 변환합니다. 🎜🎜🎜마지막으로 UNHEX를 통해 암호화된 문자열을 꺼내고 AES 키 'key2'를 통해 복호화합니다. 🎜rrreee🎜 마찬가지로 일반 텍스트의 길이에 따라 AES_ENCRYPT 암호화된 문자열의 길이도 달라지므로 HEX 후속 문자열의 길이도 달라집니다. 🎜실제 사용시에는 사업성을 토대로 합리적인 가치를 평가해야 합니다. 🎜🎜🎜🎜🎜방법 ③: 🎜🎜🎜🎜🎜16진수 변환 없이 varchar에 직접 저장합니다. 🎜🎜문제의 처음으로 돌아가 보면 암호화된 문자열을 utf8 문자 집합에 저장할 수 없으며 속성이 varchar입니다. 🎜🎜사실 문자 집합을 latin1로 변경하면 됩니다. 🎜🎜🎜삽입 시 경고가 보고되지 않습니다. 🎜rrreee🎜이 방법은 아름답지만 필드 문자 세트를 latin1로 설정하기만 하면 되지만 숨겨진 위험이 발생할 수 있습니다. 🎜🎜🎜문서에 다음 문장이 기록되어 있습니다. 🎜🎜🎜많은 암호화 및 압축 기능이 문자열을 반환합니다. 결과에는 임의의 바이트 값이 포함될 수 있습니다. 이러한 결과를 저장하려면 VARBINARY 또는 BLOB 이진 문자열 데이터 유형이 있는 열을 사용하십시오. 이렇게 하면 데이터 값을 변경하는 후행 공백 제거 또는 문자 집합 변환과 관련된 잠재적인 문제를 피할 수 있습니다. 바이너리가 아닌 문자열 데이터 유형(CHAR, VARCHAR, TEXT)을 사용하는 경우 발생합니다. 일반적인 아이디어는 ③ 방법을 사용하는 경우 암호화된 문자열을 char/varchar/text 유형에 직접 저장한 다음 문자를 생성하는 것입니다. 변환할 때나 공백을 제거할 때 잠재적인 영향을 미칩니다. 🎜🎜그래서 char/varchar/text에 저장해야 한다면 ②방법을 참고하여 16진수로 변환하세요. 🎜🎜🎜또는 방법 ①과 마찬가지로 바이너리 필드에 직접 저장합니다. 🎜🎜🎜🎜요약🎜🎜🎜

위 내용은 MySQL이 암호화 및 암호 해독을 위해 AES_ENCRYPT() 및 AES_DECRYPT()를 사용하는 방법의 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.