跳到主要内容
跳到主要内容

加密函数

这些函数使用 AES(Advanced Encryption Standard,高级加密标准)算法对数据进行加密和解密。

密钥长度取决于加密模式:在 -128--196--256- 模式下,密钥长度分别为 162432 字节。

初始化向量长度始终为 16 字节(超过 16 字节的部分会被忽略)。

HMAC

引入于:v25.12

使用指定的哈希算法和密钥,为给定消息计算 HMAC(基于哈希的消息认证码)。

支持的哈希算法:

  • RSA-MD4(别名:MD4,RSA-MD4)
  • RSA-MD5(别名:MD5,RSA-MD5)
  • RSA-MDC2(别名:MDC2,RSA-MDC2)
  • RSA-RIPEMD160(别名:RIPEMD160,RSA-RIPEMD160)
  • RSA-SHA1(别名:RSA-SHA1,SHA1)
  • RSA-SHA1-2(别名:RSA-SHA1,RSA-SHA1-2)
  • RSA-SHA224(别名:RSA-SHA224,SHA224)
  • RSA-SHA256(别名:RSA-SHA256,SHA256)
  • RSA-SHA3-224(别名:RSA-SHA3-224,SHA3-224)
  • RSA-SHA3-256(别名:RSA-SHA3-256,SHA3-256)
  • RSA-SHA3-384(别名:RSA-SHA3-384,SHA3-384)
  • RSA-SHA3-512(别名:RSA-SHA3-512,SHA3-512)
  • RSA-SHA384(别名:RSA-SHA384,SHA384)
  • RSA-SHA512(别名:RSA-SHA512,SHA512)
  • RSA-SHA512/224(别名:RSA-SHA512/224,SHA512-224)
  • RSA-SHA512/256(别名:RSA-SHA512/256,SHA512-256)
  • RSA-SM3(别名:RSA-SM3,SM3)
  • blake2b512
  • blake2s256
  • id-rsassa-pkcs1-v1_5-with-sha3-224(别名:SHA3-224,id-rsassa-pkcs1-v1_5-with-sha3-224)
  • id-rsassa-pkcs1-v1_5-with-sha3-256(别名:SHA3-256,id-rsassa-pkcs1-v1_5-with-sha3-256)
  • id-rsassa-pkcs1-v1_5-with-sha3-384(别名:SHA3-384,id-rsassa-pkcs1-v1_5-with-sha3-384)
  • id-rsassa-pkcs1-v1_5-with-sha3-512(别名:SHA3-512,id-rsassa-pkcs1-v1_5-with-sha3-512)
  • md4
  • md4WithRSAEncryption(别名:MD4,md4WithRSAEncryption)
  • md5
  • md5-sha1
  • md5WithRSAEncryption(别名:MD5,md5WithRSAEncryption)
  • mdc2
  • mdc2WithRSA(别名:MDC2,mdc2WithRSA)
  • ripemd(别名:RIPEMD160,ripemd)
  • ripemd160
  • ripemd160WithRSA(别名:RIPEMD160,ripemd160WithRSA)
  • rmd160(别名:RIPEMD160,rmd160)
  • sha1
  • sha1WithRSAEncryption(别名:SHA1,sha1WithRSAEncryption)
  • sha224
  • sha224WithRSAEncryption(别名:SHA224,sha224WithRSAEncryption)
  • sha256
  • sha256WithRSAEncryption(别名:SHA256,sha256WithRSAEncryption)
  • sha3-224
  • sha3-256
  • sha3-384
  • sha3-512
  • sha384
  • sha384WithRSAEncryption(别名:SHA384,sha384WithRSAEncryption)
  • sha512
  • sha512-224
  • sha512-224WithRSAEncryption(别名:SHA512-224,sha512-224WithRSAEncryption)
  • sha512-256
  • sha512-256WithRSAEncryption(别名:SHA512-256,sha512-256WithRSAEncryption)
  • sha512WithRSAEncryption(别名:SHA512,sha512WithRSAEncryption)
  • shake128
  • shake256
  • sm3
  • sm3WithRSAEncryption(别名:SM3,sm3WithRSAEncryption)
  • ssl3-md5(别名:MD5,ssl3-md5)
  • ssl3-sha1(别名:SHA1,ssl3-sha1)
  • whirlpool

语法

HMAC(mode, message, key)

参数

  • mode — 哈希算法名称(不区分大小写)。支持:md5、sha1、sha224、sha256、sha384、sha512。String
  • message — 用于计算 HMAC 的消息。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

解密由 MySQL 的 AES_ENCRYPT 函数加密的数据。

对于相同的输入,会生成与 decrypt 相同的明文。 当 keyiv 长于正常长度时,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

示例

解密 MySQL 数据

-- 让我们解密之前用 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─┐
│ 秘密      │
└───────────┘

aes_encrypt_mysql

引入版本:v20.12

以与 MySQL 的 AES_ENCRYPT 函数相同的方式加密文本。 生成的密文可以使用 MySQL 的 AES_DECRYPT 函数解密。 对相同输入,生成的密文与 encrypt 函数相同。 当 keyiv 的长度超过通常的限制时,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 特有的密钥折叠规则。String
  • iv — 可选。初始化向量。仅前 16 个字节生效。String

返回值

密文(二进制字符串)。String

示例

相同输入比较

-- 给定相同的输入,encrypt 和 aes_encrypt_mysql 生成相同的密文:
SELECT encrypt('aes-256-ofb', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv') = aes_encrypt_mysql('aes-256-ofb', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv') AS ciphertexts_equal;
┌─ciphertexts_equal─┐
│                 1 │
└───────────────────┘

密钥过长导致加密失败

-- 但当密钥或初始化向量长度超过预期时,encrypt 会失败:
SELECT encrypt('aes-256-ofb', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123');
从服务器收到异常(版本 22.6.1):
代码:36. DB::Exception: 从 localhost:9000 收到。DB::Exception: 密钥大小无效:期望 32,实际 33:处理 encrypt('aes-256-ofb', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123') 时。

MySQL 兼容性

-- aes_encrypt_mysql 生成与 MySQL 兼容的输出:
SELECT hex(aes_encrypt_mysql('aes-256-ofb', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123')) AS ciphertext;
┌─密文───┐
│ 24E9E4966469 │
└──────────────┘

使用更长的 IV 会得到相同的结果

-- 注意,即使提供更长的 IV 也会产生相同的结果
SELECT hex(aes_encrypt_mysql('aes-256-ofb', 'Secret', '123456789101213141516171819202122', 'iviviviviviviviv123456')) AS ciphertext
┌─密文───┐
│ 24E9E4966469 │
└──────────────┘

decrypt

自 v20.12 引入

此函数使用以下模式,对经 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

示例

正确解密已加密的数据

-- 重用 encrypt 函数示例中的表
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
-- 注意仅有部分数据被正确解密,其余部分为乱码,这是因为加密时使用的 `mode`、`key` 或 `iv` 参数不同所致。
┌─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 引入

使用 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

返回值

返回二进制字符串形式的密文。String

示例

加密示例

CREATE TABLE encryption_test
(
    `comment` String,
    `secret` String
)
ENGINE = MergeTree;

INSERT INTO encryption_test VALUES
('aes-256-ofb 无 IV', encrypt('aes-256-ofb', 'Secret', '12345678910121314151617181920212')),
('aes-256-ofb 无 IV,不同密钥', encrypt('aes-256-ofb', 'Secret', 'keykeykeykeykeykeykeykeykeykeyke')),
('aes-256-ofb 带 IV', encrypt('aes-256-ofb', 'Secret', '12345678910121314151617181920212', 'iviviviviviviviv')),
('aes-256-cbc 无 IV', encrypt('aes-256-cbc', 'Secret', '12345678910121314151617181920212'));

SELECT comment, hex(secret) FROM encryption_test;
┌─comment──────────────────────────┬─hex(secret)──────────────────────┐
│ aes-256-ofb 无 IV                │ B4972BDC4459                     │
│ aes-256-ofb 无 IV, 不同密钥      │ 2FF57C092DC9                     │
│ aes-256-ofb 带 IV                │ 5E6CB398F653                     │
│ aes-256-cbc 无 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 起引入

类似于 decrypt 函数,但在因使用错误密钥而解密失败时返回 NULL

语法

tryDecrypt(mode, ciphertext, key[, iv, aad])

参数

  • mode — 解密模式。String
  • ciphertext — 需要解密的密文。String
  • key — 解密密钥。String
  • iv — 可选。初始化向量。在 -gcm 模式下是必需的,在其他模式下可选。String
  • aad — 可选。附加认证数据。如果该值不正确,则无法解密。仅适用于 -gcm 模式,在其他模式下会抛出异常。String

返回值

返回解密后的 String,如果解密失败则返回 NULLNullable(String)

示例

创建表并插入数据

-- 创建一个表,其中 user_id 是唯一用户标识符,encrypted 是加密字符串字段,iv 是解密/加密的初始向量。
-- 假设用户知道自己的 ID 和解密该加密字段的密钥:
CREATE TABLE decrypt_null
(
    dt DateTime,
    user_id UInt32,
    encrypted String,
    iv String
)
ENGINE = MergeTree;

-- 插入一些数据:
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');

-- 尝试使用单个密钥解密
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 │ ᴺᵁᴸᴸ   │
└─────────────────────┴─────────┴────────┘