Эти функции реализуют шифрование и расшифрование данных с использованием алгоритма AES (Advanced Encryption Standard).
Длина ключа зависит от режима шифрования: 16, 24 и 32 байта для режимов -128-, -196- и -256- соответственно.
Длина вектора инициализации всегда составляет 16 байт (байты сверх 16 игнорируются).
HMAC
Добавлено в: v25.12.0
Вычисляет HMAC (Hash-based Message Authentication Code) для указанного сообщения с использованием заданного алгоритма хеширования и секретного ключа.
Поддерживаемые алгоритмы хеширования:
- blake2b512
- blake2s256
- md4
- md5
- md5-sha1
- mdc2
- ripemd (псевдонимы: RIPEMD160, ripemd)
- ripemd160
- rmd160 (псевдонимы: RIPEMD160, rmd160)
- sha1
- sha224
- sha256
- sha3-224
- sha3-256
- sha3-384
- sha3-512
- sha384
- sha512
- sha512-224
- sha512-256
- shake128
- shake256
- sm3
- ssl3-md5 (псевдонимы: MD5, ssl3-md5)
- ssl3-sha1 (псевдонимы: SHA1, ssl3-sha1)
- whirlpool
Синтаксис
Аргументы
mode — Имя алгоритма хеширования (регистронезависимое). Поддерживаются: md5, sha1, sha224, sha256, sha384, sha512. String
message — Сообщение, для которого вычисляется код аутентификации. String
key — Секретный ключ для HMAC. String
Возвращаемое значение
Возвращает бинарную строку, содержащую дайджест HMAC. String
Примеры
Простейший HMAC-SHA256
SELECT hex(HMAC('sha256', 'The quick brown fox jumps over the lazy dog', 'secret_key'));
┌─hex(HMAC('sha256', 'The quick brown fox jumps over the lazy dog', 'secret_key'))─┐
│ 31FD15FA0F61FD40DC09D919D4AA5B4141A0B27C1D51E74A6789A890AAAA187C │
└──────────────────────────────────────────────────────────────────────────────────┘
Разные алгоритмы хеширования
SELECT
hex(HMAC('md5', 'message', 'key')) AS hmac_md5,
hex(HMAC('sha1', 'message', 'key')) AS hmac_sha1,
hex(HMAC('sha256', 'message', 'key')) AS hmac_sha256;
┌─hmac_md5─────────────────────────┬─hmac_sha1────────────────────────────────┬─hmac_sha256──────────────────────────────────────────────────────┐
│ 4E4748E62B463521F6775FBF921234B5 │ 2088DF74D5F2146B48146CAF4965377E9D0BE3A4 │ 6E9EF29B75FFFC5B7ABAE527D58FDADB2FE42E7219011976917343065F58ED4A │
└──────────────────────────────────┴──────────────────────────────────────────┴──────────────────────────────────────────────────────────────────┘
Режим без учета регистра
SELECT
hmac('SHA256', 'message', 'key') = HMAC('sha256', 'message', 'key') AS same_result,
HMAC('SHA256', 'message', 'key') = Hmac('Sha256', 'message', 'key') AS also_same;
┌─same_result─┬─also_same─┐
│ 1 │ 1 │
└─────────────┴───────────┘
aes_decrypt_mysql
Появилась в версии v20.12.0
Расшифровывает данные, зашифрованные функцией MySQL AES_ENCRYPT.
Для одинаковых входных данных возвращает тот же открытый текст, что и decrypt.
Если key или iv длиннее, чем должны быть, aes_decrypt_mysql ведет себя так же, как функция MySQL aes_decrypt: «сворачивает» key и игнорирует лишние биты iv.
Поддерживает следующие режимы расшифрования:
- aes-128-ecb, aes-192-ecb, aes-256-ecb
- aes-128-cbc, aes-192-cbc, aes-256-cbc
- aes-128-cfb128
- aes-128-ofb, aes-192-ofb, aes-256-ofb
Синтаксис
aes_decrypt_mysql(mode, ciphertext, key[, iv])
Аргументы
mode — режим расшифровки. String
ciphertext — зашифрованный текст, который нужно расшифровать. String
key — ключ расшифровки. String
iv — необязательный параметр. Вектор инициализации. String
Возвращаемое значение
Возвращает расшифрованное значение типа String. String
Примеры
Расшифровка данных MySQL
-- Let's decrypt data we've previously encrypted with MySQL:
mysql> SET block_encryption_mode='aes-256-ofb';
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)
SELECT aes_decrypt_mysql('aes-256-ofb', unhex('24E9E4966469'), '123456789101213141516171819202122', 'iviviviviviviviv123456') AS plaintext
┌─plaintext─┐
│ Secret │
└───────────┘
aes_encrypt_mysql
Появилась в версии: v20.12.0
Шифрует текст тем же способом, что и функция MySQL AES_ENCRYPT.
Полученный шифротекст может быть расшифрован функцией MySQL AES_DECRYPT.
При тех же входных данных выдаёт тот же шифротекст, что и функция encrypt.
Когда key или iv длиннее, чем обычно требуется, aes_encrypt_mysql ведёт себя так же, как MySQL aes_encrypt, то есть «сворачивает» key и игнорирует лишние биты iv.
Поддерживаемые режимы шифрования:
- aes-128-ecb, aes-192-ecb, aes-256-ecb
- aes-128-cbc, aes-192-cbc, aes-256-cbc
- aes-128-ofb, aes-192-ofb, aes-256-ofb
Синтаксис
aes_encrypt_mysql(mode, plaintext, key[, iv])
Аргументы
mode — Режим шифрования. String
plaintext — Текст, подлежащий шифрованию. String
key — Ключ шифрования. Если ключ длиннее, чем требуется для mode, выполняется специфическая для MySQL свёртка ключа (key folding). String
iv — Необязательный параметр. Вектор инициализации. Учитываются только первые 16 байт. String
Возвращаемое значение
Бинарная строка зашифрованного текста. String
Примеры
Сравнение одинаковых входных данных
-- Given equal input encrypt and aes_encrypt_mysql produce the same ciphertext:
SELECT encrypt('aes-256-ofb', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv') = aes_encrypt_mysql('aes-256-ofb', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv') AS ciphertexts_equal;
┌─ciphertexts_equal─┐
│ 1 │
└───────────────────┘
Сбой Encrypt при слишком длинном ключе
-- But encrypt fails when key or iv is longer than expected:
SELECT encrypt('aes-256-ofb', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123');
Received exception from server (version 22.6.1):
Code: 36. DB::Exception: Received from localhost:9000. DB::Exception: Invalid key size: 33 expected 32: While processing encrypt('aes-256-ofb', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123').
Совместимость с MySQL
-- aes_encrypt_mysql produces MySQL-compatible output:
SELECT hex(aes_encrypt_mysql('aes-256-ofb', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123')) AS ciphertext;
┌─ciphertext───┐
│ 24E9E4966469 │
└──────────────┘
Более длинный IV даёт тот же результат
-- Notice how supplying even longer IV produces the same result
SELECT hex(aes_encrypt_mysql('aes-256-ofb', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123456')) AS ciphertext
┌─ciphertext───┐
│ 24E9E4966469 │
└──────────────┘
decrypt
Впервые представлена в: v20.12.0
Эта функция расшифровывает двоичную строку, зашифрованную с помощью AES, с использованием следующих режимов:
- aes-128-ecb, aes-192-ecb, aes-256-ecb
- aes-128-cbc, aes-192-cbc, aes-256-cbc
- aes-128-ofb, aes-192-ofb, aes-256-ofb
- aes-128-gcm, aes-192-gcm, aes-256-gcm
- aes-128-ctr, aes-192-ctr, aes-256-ctr
- aes-128-cfb, aes-128-cfb1, aes-128-cfb8
Синтаксис
decrypt(mode, ciphertext, key[, iv, aad])
Аргументы
mode — режим расшифровки. String
ciphertext — зашифрованный текст, который необходимо расшифровать. String
key — ключ для расшифровки. String
iv — вектор инициализации. Обязателен для режимов -gcm, для остальных — необязателен. String
aad — дополнительные аутентифицированные данные. Расшифровка не произойдёт, если это значение неверно. Работает только в режимах -gcm, для остальных генерируется исключение. String
Возвращаемое значение
Возвращает расшифрованный открытый текст. String
Примеры
Правильная расшифровка зашифрованных данных
-- Re-using the table from the encrypt function example
SELECT comment, hex(secret) FROM encryption_test;
┌─comment──────────────┬─hex(secret)──────────────────────────────────┐
│ aes-256-gcm │ A8A3CCBC6426CFEEB60E4EAE03D3E94204C1B09E0254 │
│ aes-256-gcm with AAD │ A8A3CCBC6426D9A1017A0A932322F1852260A4AD6837 │
└──────────────────────┴──────────────────────────────────────────────┘
┌─comment──────────────────────────┬─hex(secret)──────────────────────┐
│ aes-256-ofb no IV │ B4972BDC4459 │
│ aes-256-ofb no IV, different key │ 2FF57C092DC9 │
│ aes-256-ofb with IV │ 5E6CB398F653 │
│ aes-256-cbc no IV │ 1BC0629A92450D9E73A00E7D02CF4142 │
└──────────────────────────────────┴──────────────────────────────────┘
Неверная расшифровка зашифрованных данных
SELECT comment, decrypt('aes-256-cfb128', secret, '12345678910121314151617181920212') AS plaintext FROM encryption_test
-- Notice how only a portion of the data was properly decrypted, and the rest is gibberish since either `mode`, `key`, or `iv` were different upon encryption.
┌─comment──────────────┬─plaintext──┐
│ aes-256-gcm │ OQ�E
�t�7T�\���\� │
│ aes-256-gcm with AAD │ OQ�E
�\��si����;�o�� │
└──────────────────────┴────────────┘
┌─comment──────────────────────────┬─plaintext─┐
│ aes-256-ofb no IV │ Secret │
│ aes-256-ofb no IV, different key │ �4�
� │
│ aes-256-ofb with IV │ ���6�~ │
│aes-256-cbc no IV │ �2*4�h3c�4w��@
└──────────────────────────────────┴───────────┘
encrypt
Добавлена в версии: v20.12.0
Шифрует открытый текст в шифртекст с использованием AES в одном из следующих режимов:
- aes-128-ecb, aes-192-ecb, aes-256-ecb
- aes-128-cbc, aes-192-cbc, aes-256-cbc
- aes-128-ofb, aes-192-ofb, aes-256-ofb
- aes-128-gcm, aes-192-gcm, aes-256-gcm
- aes-128-ctr, aes-192-ctr, aes-256-ctr
- aes-128-cfb, aes-128-cfb1, aes-128-cfb8
Синтаксис
encrypt(mode, plaintext, key[, iv, aad])
Аргументы
mode — режим шифрования. String
plaintext — текст, который нужно зашифровать. String
key — ключ шифрования. String
iv — вектор инициализации. Обязателен для режимов -gcm, для остальных — необязателен. String
aad — дополнительные аутентифицированные данные. Они не шифруются, но влияют на расшифровку. Работает только в режимах -gcm, для остальных генерируется исключение. String
Возвращаемое значение
Возвращает бинарную строку с зашифрованными данными (ciphertext). String
Примеры
Пример шифрования
CREATE TABLE encryption_test
(
`comment` String,
`secret` String
)
ENGINE = MergeTree;
INSERT INTO encryption_test VALUES
('aes-256-ofb no IV', encrypt('aes-256-ofb', 'Secret', '12345678910121314151617181920212')),
('aes-256-ofb no IV, different key', encrypt('aes-256-ofb', 'Secret', 'keykeykeykeykeykeykeykeykeykeyke')),
('aes-256-ofb with IV', encrypt('aes-256-ofb', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv')),
('aes-256-cbc no IV', encrypt('aes-256-cbc', 'Secret', '12345678910121314151617181920212'));
SELECT comment, hex(secret) FROM encryption_test;
┌─comment──────────────────────────┬─hex(secret)──────────────────────┐
│ aes-256-ofb no IV │ B4972BDC4459 │
│ aes-256-ofb no IV, different key │ 2FF57C092DC9 │
│ aes-256-ofb with IV │ 5E6CB398F653 │
│ aes-256-cbc no IV │ 1BC0629A92450D9E73A00E7D02CF4142 │
└──────────────────────────────────┴──────────────────────────────────┘
Пример для режима GCM
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'));
SELECT comment, hex(secret) FROM encryption_test WHERE comment LIKE '%gcm%';
┌─comment──────────────┬─hex(secret)──────────────────────────────────┐
│ aes-256-gcm │ A8A3CCBC6426CFEEB60E4EAE03D3E94204C1B09E0254 │
│ aes-256-gcm with AAD │ A8A3CCBC6426D9A1017A0A932322F1852260A4AD6837 │
└──────────────────────┴──────────────────────────────────────────────┘
tryDecrypt
Добавлена в: v22.10.0
Аналогична функции decrypt, но возвращает NULL, если расшифровка не удалась при использовании неправильного ключа.
Синтаксис
tryDecrypt(mode, ciphertext, key[, iv, aad])
Аргументы
mode — Режим расшифровки. String
ciphertext — Зашифрованный текст, который нужно расшифровать. String
key — Ключ для расшифровки. String
iv — Необязательный параметр. Вектор инициализации. Обязателен для режимов -gcm, необязателен для остальных режимов. String
aad — Необязательный параметр. Дополнительные аутентифицируемые данные. Расшифровка не будет выполнена, если это значение неверно. Работает только в режимах -gcm, для других режимов выбрасывается исключение. String
Возвращаемое значение
Возвращает расшифрованный String или NULL, если расшифровка не удалась. Nullable(String)
Примеры
Создание таблицы и вставка данных
-- Let's create a table where user_id is the unique user id, encrypted is an encrypted string field, iv is an initial vector for decrypt/encrypt.
-- Assume that users know their id and the key to decrypt the encrypted field:
CREATE TABLE decrypt_null
(
dt DateTime,
user_id UInt32,
encrypted String,
iv String
)
ENGINE = MergeTree;
-- Insert some data:
INSERT INTO decrypt_null VALUES
('2022-08-02 00:00:00', 1, encrypt('aes-256-gcm', 'value1', 'keykeykeykeykeykeykeykeykeykey01', 'iv1'), 'iv1'),
('2022-09-02 00:00:00', 2, encrypt('aes-256-gcm', 'value2', 'keykeykeykeykeykeykeykeykeykey02', 'iv2'), 'iv2'),
('2022-09-02 00:00:01', 3, encrypt('aes-256-gcm', 'value3', 'keykeykeykeykeykeykeykeykeykey03', 'iv3'), 'iv3');
-- Try decrypt with one key
SELECT
dt,
user_id,
tryDecrypt('aes-256-gcm', encrypted, 'keykeykeykeykeykeykeykeykeykey02', iv) AS value
FROM decrypt_null
ORDER BY user_id ASC
┌──────────────────dt─┬─user_id─┬─value──┐
│ 2022-08-02 00:00:00 │ 1 │ ᴺᵁᴸᴸ │
│ 2022-09-02 00:00:00 │ 2 │ value2 │
│ 2022-09-02 00:00:01 │ 3 │ ᴺᵁᴸᴸ │
└─────────────────────┴─────────┴────────┘