2020-11-17 14:05:33 +00:00
---
toc_priority: 67
2021-03-08 14:54:44 +00:00
toc_title: "Функции для шифрования"
2020-11-17 14:05:33 +00:00
---
# Функции шифрования {#encryption-functions}
Даннвые функции реализуют шифрование и расшифровку данных с помощью AES (Advanced Encryption Standard) алгоритма.
Длина ключа зависит от режима шифрования. Он может быть длинной в 16, 24 и 32 байта для режимов шифрования `-128-` , `-196-` и `-256-` соответственно.
Длина инициализирующего вектора всегда 16 байт (лишнии байты игнорируются).
2021-02-16 19:38:20 +00:00
Обратите внимание, что до версии Clickhouse 21.1 эти функции работали медленно.
2020-11-17 14:05:33 +00:00
## encrypt {#encrypt}
Функция поддерживает шифрование данных следующими режимами:
- aes-128-ecb, aes-192-ecb, aes-256-ecb
- aes-128-cbc, aes-192-cbc, aes-256-cbc
- aes-128-cfb1, aes-192-cfb1, aes-256-cfb1
- aes-128-cfb8, aes-192-cfb8, aes-256-cfb8
- aes-128-cfb128, aes-192-cfb128, aes-256-cfb128
- aes-128-ofb, aes-192-ofb, aes-256-ofb
- aes-128-gcm, aes-192-gcm, aes-256-gcm
**Синтаксис**
``` sql
encrypt('mode', 'plaintext', 'key' [, iv, aad])
```
2021-03-13 18:18:45 +00:00
**Аргументы**
2020-11-17 14:05:33 +00:00
- `mode` — режим шифрования. [String ](../../sql-reference/data-types/string.md#string ).
- `plaintext` — текст, который будет зашифрован. [String ](../../sql-reference/data-types/string.md#string ).
- `key` — ключ шифрования. [String ](../../sql-reference/data-types/string.md#string ).
- `iv` — инициализирующий вектор. Обязателен для `-gcm` режимов, для остальных режимов необязателен. [String ](../../sql-reference/data-types/string.md#string ).
- `aad` — дополнительные аутентифицированные данные. Н е шифруются, но влияют на расшифровку. Параметр работает только с `-gcm` режимами. Для остальных вызовет исключение. [String ](../../sql-reference/data-types/string.md#string ).
**Возвращаемое значение**
2021-02-25 11:19:26 +00:00
- Бинарная зашифрованная строка. [String ](../../sql-reference/data-types/string.md#string ).
2020-11-17 14:05:33 +00:00
**Примеры**
Создадим такую таблицу:
Запрос:
``` sql
CREATE TABLE encryption_test
(
2021-02-11 16:29:46 +00:00
`comment` String,
`secret` String
)
ENGINE = Memory;
2020-11-17 14:05:33 +00:00
```
2021-02-11 16:29:46 +00:00
Вставим некоторые данные (замечание: не храните ключи или инициализирующие векторы в базе данных, так как это компрометирует всю концепцию шифрования), также хранение "подсказок" небезопасно и используется только для наглядности:
2020-11-17 14:05:33 +00:00
Запрос:
``` sql
2021-02-11 16:29:46 +00:00
INSERT INTO encryption_test VALUES('aes-256-cfb128 no IV', encrypt('aes-256-cfb128', 'Secret', '12345678910121314151617181920212')),\
('aes-256-cfb128 no IV, different key', encrypt('aes-256-cfb128', 'Secret', 'keykeykeykeykeykeykeykeykeykeyke')),\
('aes-256-cfb128 with IV', encrypt('aes-256-cfb128', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv')),\
('aes-256-cbc no IV', encrypt('aes-256-cbc', 'Secret', '12345678910121314151617181920212'));
2020-11-17 14:05:33 +00:00
```
Запрос:
``` sql
2021-02-11 16:29:46 +00:00
SELECT comment, hex(secret) FROM encryption_test;
2020-11-17 14:05:33 +00:00
```
Результат:
``` text
2021-02-11 16:29:46 +00:00
┌─comment─────────────────────────────┬─hex(secret)──────────────────────┐
│ aes-256-cfb128 no IV │ B4972BDC4459 │
│ aes-256-cfb128 no IV, different key │ 2FF57C092DC9 │
│ aes-256-cfb128 with IV │ 5E6CB398F653 │
│ aes-256-cbc no IV │ 1BC0629A92450D9E73A00E7D02CF4142 │
└─────────────────────────────────────┴──────────────────────────────────┘
2020-11-17 14:05:33 +00:00
```
Пример в режиме `-gcm` :
Запрос:
``` sql
2021-02-11 16:29:46 +00:00
INSERT INTO encryption_test VALUES('aes-256-gcm', encrypt('aes-256-gcm', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv')), \
('aes-256-gcm with AAD', encrypt('aes-256-gcm', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv', 'aad'));
2020-11-17 14:05:33 +00:00
2021-02-11 16:29:46 +00:00
SELECT comment, hex(secret) FROM encryption_test WHERE comment LIKE '%gcm%';
2020-11-17 14:05:33 +00:00
```
Результат:
``` text
2021-02-11 16:29:46 +00:00
┌─comment──────────────┬─hex(secret)──────────────────────────────────┐
│ aes-256-gcm │ A8A3CCBC6426CFEEB60E4EAE03D3E94204C1B09E0254 │
│ aes-256-gcm with AAD │ A8A3CCBC6426D9A1017A0A932322F1852260A4AD6837 │
└──────────────────────┴──────────────────────────────────────────────┘
2020-11-17 14:05:33 +00:00
```
## aes_encrypt_mysql {#aes_encrypt_mysql}
Совместима с шифрованием myqsl, результат может быть расшифрован функцией [AES_DECRYPT ](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_aes-decrypt ).
2021-02-16 19:32:59 +00:00
При одинаковых входящих значениях зашифрованный текст будет совпадать с результатом, возвращаемым функцией `encrypt` . Однако если `key` или `iv` длиннее, чем должны быть, `aes_encrypt_mysql` будет работать аналогично функции `aes_encrypt` в MySQL: свернет ключ и проигнорирует лишнюю часть `iv` .
2021-02-11 16:29:46 +00:00
2020-11-17 14:05:33 +00:00
Функция поддерживает шифрофание данных следующими режимами:
- aes-128-ecb, aes-192-ecb, aes-256-ecb
- aes-128-cbc, aes-192-cbc, aes-256-cbc
- aes-128-cfb1, aes-192-cfb1, aes-256-cfb1
- aes-128-cfb8, aes-192-cfb8, aes-256-cfb8
- aes-128-cfb128, aes-192-cfb128, aes-256-cfb128
- aes-128-ofb, aes-192-ofb, aes-256-ofb
**Синтаксис**
2021-02-11 16:29:46 +00:00
``` sql
2020-11-17 14:05:33 +00:00
aes_encrypt_mysql('mode', 'plaintext', 'key' [, iv])
```
2021-03-13 18:18:45 +00:00
**Аргументы**
2020-11-17 14:05:33 +00:00
- `mode` — режим шифрования. [String ](../../sql-reference/data-types/string.md#string ).
- `plaintext` — текст, который будет зашифрован. [String ](../../sql-reference/data-types/string.md#string ).
2021-02-11 16:29:46 +00:00
- `key` — ключ шифрования. Если ключ длиннее, чем требует режим шифрования, производится специфичная для MySQL свертка ключа. [String ](../../sql-reference/data-types/string.md#string ).
- `iv` — инициализирующий вектор. Необязателен, учитываются только первые 16 байтов. [String ](../../sql-reference/data-types/string.md#string ).
2020-11-17 14:05:33 +00:00
**Возвращаемое значение**
2021-02-25 11:20:42 +00:00
- Бинарная зашифрованная строка. [String ](../../sql-reference/data-types/string.md#string ).
2020-11-17 14:05:33 +00:00
**Примеры**
2021-02-16 19:33:19 +00:00
При одинаковых входящих значениях результаты шифрования у функций `encrypt` и `aes_encrypt_mysql` совпадают.
2020-11-17 14:05:33 +00:00
Запрос:
``` sql
2021-02-11 16:29:46 +00:00
SELECT encrypt('aes-256-cfb128', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv') = aes_encrypt_mysql('aes-256-cfb128', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv') AS ciphertexts_equal;
2020-11-17 14:05:33 +00:00
```
2021-02-11 16:29:46 +00:00
Результат:
``` text
┌─ciphertexts_equal─┐
│ 1 │
└───────────────────┘
```
2021-02-16 19:33:32 +00:00
Функция `encrypt` генерирует исключение, если `key` или `iv` длиннее чем нужно:
2020-11-17 14:05:33 +00:00
Запрос:
``` sql
2021-02-11 16:29:46 +00:00
SELECT encrypt('aes-256-cfb128', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123');
```
Результат:
``` text
Received exception from server (version 21.1.2):
Code: 36. DB::Exception: Received from localhost:9000. DB::Exception: Invalid key size: 33 expected 32: While processing encrypt('aes-256-cfb128', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123').
2020-11-17 14:05:33 +00:00
```
2021-02-16 19:33:57 +00:00
Однако функция `aes_encrypt_mysql` в аналогичном случае возвращает результат, который может быть обработан MySQL:
2020-11-17 14:05:33 +00:00
Запрос:
``` sql
2021-02-11 16:29:46 +00:00
SELECT hex(aes_encrypt_mysql('aes-256-cfb128', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123')) AS ciphertext;
2020-11-17 14:05:33 +00:00
```
Результат:
2021-02-11 16:29:46 +00:00
```text
┌─ciphertext───┐
│ 24E9E4966469 │
└──────────────┘
2020-11-17 14:05:33 +00:00
```
2021-02-11 16:29:46 +00:00
Если передать `iv` еще длиннее, результат останется таким же:
2020-11-17 14:05:33 +00:00
Запрос:
``` sql
2021-02-11 16:29:46 +00:00
SELECT hex(aes_encrypt_mysql('aes-256-cfb128', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123456')) AS ciphertext
2020-11-17 14:05:33 +00:00
```
Результат:
``` text
2021-02-11 16:29:46 +00:00
┌─ciphertext───┐
│ 24E9E4966469 │
└──────────────┘
```
2021-02-16 19:34:43 +00:00
Это совпадает с результатом, возвращаемым MySQL при таких же входящих значениях:
2021-02-11 16:29:46 +00:00
``` sql
mysql> SET block_encryption_mode='aes-256-cfb128';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT aes_encrypt('Secret', '123456789101213141516171819202122', 'iviviviviviviviv123456') as ciphertext;
+------------------------+
| ciphertext |
+------------------------+
| 0x24E9E4966469 |
+------------------------+
1 row in set (0.00 sec)
2020-11-17 14:05:33 +00:00
```
## decrypt {#decrypt}
2021-02-16 19:34:33 +00:00
Функция расшифровывает зашифрованный текст и может работать в следующих режимах:
2020-11-17 14:05:33 +00:00
- aes-128-ecb, aes-192-ecb, aes-256-ecb
- aes-128-cbc, aes-192-cbc, aes-256-cbc
- aes-128-cfb1, aes-192-cfb1, aes-256-cfb1
- aes-128-cfb8, aes-192-cfb8, aes-256-cfb8
- aes-128-cfb128, aes-192-cfb128, aes-256-cfb128
- aes-128-ofb, aes-192-ofb, aes-256-ofb
- aes-128-gcm, aes-192-gcm, aes-256-gcm
**Синтаксис**
2021-02-11 16:29:46 +00:00
``` sql
2020-11-17 14:05:33 +00:00
decrypt('mode', 'ciphertext', 'key' [, iv, aad])
```
2021-03-13 18:18:45 +00:00
**Аргументы**
2020-11-17 14:05:33 +00:00
- `mode` — режим шифрования. [String ](../../sql-reference/data-types/string.md#string ).
- `ciphertext` — зашифрованный текст, который будет расшифрован. [String ](../../sql-reference/data-types/string.md#string ).
- `key` — ключ шифрования. [String ](../../sql-reference/data-types/string.md#string ).
- `iv` — инициализирующий вектор. Обязателен для `-gcm` режимов, для остальных режимов опциональный. [String ](../../sql-reference/data-types/string.md#string ).
2021-03-13 18:18:45 +00:00
- `aad` — дополнительные аутентифицированные данные. Текст не будет расшифрован, если это значение неверно. Работает только с `-gcm` режимами. Для остальных вызовет исключение. [String ](../../sql-reference/data-types/string.md#string ).
2020-11-17 14:05:33 +00:00
**Возвращаемое значение**
- Расшифрованная строка. [String ](../../sql-reference/data-types/string.md#string ).
**Примеры**
2021-02-16 19:35:07 +00:00
Рассмотрим таблицу из примера для функции [encrypt ](#encrypt ).
2020-11-17 14:05:33 +00:00
Запрос:
``` sql
2021-02-11 16:29:46 +00:00
SELECT comment, hex(secret) FROM encryption_test;
2020-11-17 14:05:33 +00:00
```
2021-02-11 16:29:46 +00:00
Результат:
2020-11-17 14:05:33 +00:00
2021-02-11 16:29:46 +00:00
``` text
┌─comment──────────────┬─hex(secret)──────────────────────────────────┐
│ aes-256-gcm │ A8A3CCBC6426CFEEB60E4EAE03D3E94204C1B09E0254 │
│ aes-256-gcm with AAD │ A8A3CCBC6426D9A1017A0A932322F1852260A4AD6837 │
└──────────────────────┴──────────────────────────────────────────────┘
┌─comment─────────────────────────────┬─hex(secret)──────────────────────┐
│ aes-256-cfb128 no IV │ B4972BDC4459 │
│ aes-256-cfb128 no IV, different key │ 2FF57C092DC9 │
│ aes-256-cfb128 with IV │ 5E6CB398F653 │
│ aes-256-cbc no IV │ 1BC0629A92450D9E73A00E7D02CF4142 │
└─────────────────────────────────────┴──────────────────────────────────┘
2020-11-17 14:05:33 +00:00
```
2021-02-11 16:29:46 +00:00
Теперь попытаемся расшифровать эти данные:
2020-11-17 14:05:33 +00:00
Запрос:
``` sql
2021-02-16 19:35:12 +00:00
SELECT comment, decrypt('aes-256-cfb128', secret, '12345678910121314151617181920212') as plaintext FROM encryption_test;
2020-11-17 14:05:33 +00:00
```
Результат:
2021-02-11 16:29:46 +00:00
``` text
┌─comment─────────────────────────────┬─plaintext─┐
│ aes-256-cfb128 no IV │ Secret │
│ aes-256-cfb128 no IV, different key │ <20> 4<EFBFBD>
<20> │
│ aes-256-cfb128 with IV │ <20> <> <EFBFBD> 6<EFBFBD> ~ │
│aes-256-cbc no IV │ <20> 2*4<> h3c<33> 4w<34> <77> @
└─────────────────────────────────────┴───────────┘
2020-11-17 14:05:33 +00:00
```
2021-02-16 19:35:23 +00:00
Обратите внимание, что только часть данных была расшифрована верно. Оставшаяся часть расшифрована некорректно, так как при шифровании использовались другие значения `mode` , `key` , или `iv` .
2021-02-11 16:29:46 +00:00
2020-11-17 14:05:33 +00:00
## aes_decrypt_mysql {#aes_decrypt_mysql}
Совместима с шифрованием myqsl и может расшифровать данные, зашифрованные функцией [AES_ENCRYPT ](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_aes-encrypt ).
2021-02-16 19:35:43 +00:00
При одинаковых входящих значениях расшифрованный текст будет совпадать с результатом, возвращаемым функцией `decrypt` . Однако если `key` или `iv` длиннее, чем должны быть, `aes_decrypt_mysql` будет работать аналогично функции `aes_decrypt` в MySQL: свернет ключ и проигнорирует лишнюю часть `iv` .
2021-02-11 16:29:46 +00:00
2021-02-16 19:35:48 +00:00
Функция поддерживает расшифровку данных в следующих режимах:
2020-11-17 14:05:33 +00:00
- aes-128-ecb, aes-192-ecb, aes-256-ecb
- aes-128-cbc, aes-192-cbc, aes-256-cbc
- aes-128-cfb1, aes-192-cfb1, aes-256-cfb1
- aes-128-cfb8, aes-192-cfb8, aes-256-cfb8
- aes-128-cfb128, aes-192-cfb128, aes-256-cfb128
- aes-128-ofb, aes-192-ofb, aes-256-ofb
**Синтаксис**
2021-02-11 16:29:46 +00:00
``` sql
2020-11-17 14:05:33 +00:00
aes_decrypt_mysql('mode', 'ciphertext', 'key' [, iv])
```
2021-03-13 18:18:45 +00:00
**Аргументы**
2020-11-17 14:05:33 +00:00
- `mode` — режим шифрования. [String ](../../sql-reference/data-types/string.md#string ).
- `ciphertext` — зашифрованный текст, который будет расшифрован. [String ](../../sql-reference/data-types/string.md#string ).
- `key` — ключ шифрования. [String ](../../sql-reference/data-types/string.md#string ).
- `iv` — инициализирующий вектор. Необязателен. [String ](../../sql-reference/data-types/string.md#string ).
**Возвращаемое значение**
- Расшифрованная строка. [String ](../../sql-reference/data-types/string.md#string ).
**Примеры**
2021-02-16 19:36:01 +00:00
Расшифруем данные, которые до этого были зашифрованы в MySQL:
2020-11-17 14:05:33 +00:00
``` sql
2021-02-11 16:29:46 +00:00
mysql> SET block_encryption_mode='aes-256-cfb128';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT aes_encrypt('Secret', '123456789101213141516171819202122', 'iviviviviviviviv123456') as ciphertext;
+------------------------+
| ciphertext |
+------------------------+
| 0x24E9E4966469 |
+------------------------+
1 row in set (0.00 sec)
2020-11-17 14:05:33 +00:00
```
Запрос:
``` sql
2021-02-16 19:35:55 +00:00
SELECT aes_decrypt_mysql('aes-256-cfb128', unhex('24E9E4966469'), '123456789101213141516171819202122', 'iviviviviviviviv123456') AS plaintext;
2020-11-17 14:05:33 +00:00
```
Результат:
``` text
2021-02-11 16:29:46 +00:00
┌─plaintext─┐
│ Secret │
└───────────┘
2020-11-17 14:05:33 +00:00
```
[Original article ](https://clickhouse.tech/docs/ru/sql-reference/functions/encryption_functions/ ) <!--hide-->