类别:

加密函数

ENCRYPT_RAW

使用 BINARY 密钥对 BINARY 值进行加密。

另请参阅:

ENCRYPTDECRYPTDECRYPT_RAWTRY_DECRYPTTRY_DECRYPT_RAW

语法

ENCRYPT_RAW( <value_to_encrypt> , <key> , <iv> ,
         [ [ <additional_authenticated_data> , ] <encryption_method> ]
       )
Copy

实参

必填:

value_to_encrypt

要加密的二进制值。

key

用于加密/解密数据的密钥。密钥必须是 BINARY 值。只要长度正确,密钥可以是任意值。例如,对于 AES128,密钥必须是 128 位(16 字节),而对于 AES256,密钥必须是 256 位(32 字节)。

用于加密该值的密钥必须用于解密该值。

iv

此参数包含用于加密和解密此数据块的初始化向量 (IV)。IV 必须是特定长度的 BINARY 值:

  • 对于 GCM,此字段必须是 96 位(12 字节)。虽然 GCM 加密方法允许此字段具有不同的大小,但 Snowflake 目前仅支持 96 位。

  • 对于 CCM,此字段应该是 56 位(7 字节)。

  • 对于 ECB,不需要此参数。

  • 对于所有其他支持的加密模式,此字段应该是 128 位(16 字节)。

此值用于初始化第一轮加密。您永远不应该多次使用相同的 IV 和密钥组合,尤其对于 GCM 之类的加密模式。

如果此参数设置为 NULL,则实施时将在每次调用期间选择新的伪随机 IV。

可选:

additional_authenticated_data

经过身份验证的额外数据 (AAD) 是在解密过程中机密性和真实性都有保证的附加数据。然而,此 AAD 未加密,并且不作为字段包含在 ENCRYPT 或者 ENCRYPT_RAW 函数的返回值中。

如果 AAD 被传递给加密函数(ENCRYPT 或 ENCRYPT_RAW),那么相同的 AAD 也必须传递给解密函数(DECRYPT 或者 DECRYPT_RAW)。如果传递给解密函数的 AAD 与 AAD 不匹配,则解密失败。

AAD 和 passphrase 之间的区别是密码短语旨在保密(否则,加密实际上毫无价值),而 AAD 可以保持公开。AAD 有助于验证公共信息和加密值是否相互关联。ENCRYPT 函数中的示例部分包括一个示例,展示了 AAD 匹配与不匹配时的行为。

对于 ENCRYPT_RAW 和 DECRYPT_RAW,AAD 的数据类型应为 BINARY。对于 ENCRYPT 和 DECRYPT,AAD 的数据类型可以是 VARCHAR 或者 BINARY,并且不需要匹配加密值的数据类型。

AAD 仅支持启用 AEAD 的加密模式,例如 GCM (默认)。

encryption_method

该字符串指定用于加密/解密数据的方法。该字符串包含子字段:

<algorithm>-<mode> [ /pad: <padding> ]
Copy

algorithm 目前仅限于:

  • 'AES':传递加密短语时(例如,传递至 ENCRYPT),该函数会使用 AES-256 加密(256 位)。传递密钥时(例如,传递至 ENCRYPT_RAW),该函数使用 128、192 或 256 位加密,具体取决于密钥长度。

algorithm 不区分大小写。

mode 指定应使用哪种分组密码模式来加密消息。下表显示了哪些模式受支持,以及其中哪些模式支持填充:

模式

填充

描述

'ECB'

使用密钥单独加密每个分组。通常不鼓励使用此模式,包含此模式只是为了与外部实现兼容。

'CBC'

加密后的分组是与前一个分组 XORed。

'GCM'

Galois/Counter 模式是一种启用了 AEAD 的高性能加密模式。AEAD 通过生成一个额外的 AEAD 标签来确保加密数据的真实性和机密性。而且,AEAD 支持 AAD (经过身份验证的额外数据)。

'CTR'

计数器模式。

'OFB'

输出反馈。密文是附带块纯文本的 XORed。

'CFB'

密码反馈由 OFB 和 CBC 组成。

mode 不区分大小写。

padding 指定如何填充长度不是块大小倍数的消息。填充仅适用于 ECB 和 CBC 模式;对于其他模式,填充将被忽略。填充的可能值为:

  • 'PKCS':将 PKCS5 用于块填充。

  • 'NONE':无填充。用户在使用 ECB 或者 CBC 模式时需要注意填充。

padding 不区分大小写。

默认设置:'AES-GCM'

如果未指定 mode,则会使用 GCM。

如果未指定 padding,则会使用 PKCS。

返回

该函数返回加密值。返回值的数据类型是 VARIANT。

虽然只返回一个值,但该值包含两个或三个字段:

  • 第一个字段是初始化向量 (IV)。加密和解密均使用 IV。

  • 第二个字段是 value_to_encrypt 的密文(加密值)。

  • 如果加密模式启用 AEAD,则返回值还包含第三个字段,即 AEAD 标签。

IV 和标签大小取决于加密模式。

VARIANT 内的所有 3 个字段属于类型 BINARY。

使用说明

  • 要解密通过 ENCRYPT() 加密的数据,请使用 DECRYPT()。请勿使用 DECRYPT_RAW()

  • 要解密通过 ENCRYPT_RAW() 加密的数据,请使用 DECRYPT_RAW()。请勿使用 DECRYPT()

  • 为了安全起见,已掩码该函数的参数。以下所示的敏感信息在查询日志中不可见,并且对 Snowflake 不可见:

    • 要加密或解密的字符串或二进制值。

    • 加密短语或密钥。

  • 这些函数使用兼容 FIPS 的密码库,有效地执行加密和解密。

  • 用于解密数据的加密短语或密钥必须与用于加密该数据的加密短语或密钥相同。

示例

此示例展示加密和解密。

为了便于阅读,请将 BINARY_OUTPUT_FORMAT 设置为 HEX:

ALTER SESSION SET BINARY_OUTPUT_FORMAT='HEX';
Copy

创建并加载表。

小心

为简化此示例,加密/解密密钥存储在包含加密值的表中。这是不安全的;密钥 决不能 作为未加密的值存储在用于存储加密数据的表中。

CREATE OR REPLACE TABLE binary_table (
    encryption_key BINARY,   -- DO NOT STORE REAL ENCRYPTION KEYS THIS WAY!
    initialization_vector BINARY(12), -- DO NOT STORE REAL IV'S THIS WAY!!
    binary_column BINARY,
    encrypted_binary_column VARIANT,
    aad_column BINARY);

INSERT INTO binary_table (encryption_key,
                          initialization_vector,
                          binary_column,
                          aad_column)
    SELECT SHA2_BINARY('NotSecretEnough', 256),
            SUBSTR(TO_BINARY(HEX_ENCODE('AlsoNotSecretEnough'), 'HEX'), 0, 12),
            TO_BINARY(HEX_ENCODE('Bonjour'), 'HEX'),
            TO_BINARY(HEX_ENCODE('additional data'), 'HEX')
    ;
Copy

加密:

UPDATE binary_table SET encrypted_binary_column =
    ENCRYPT_RAW(binary_column, 
        encryption_key, 
        initialization_vector, 
        aad_column,
        'AES-GCM');
+------------------------+-------------------------------------+
| number of rows updated | number of multi-joined rows updated |
|------------------------+-------------------------------------|
|                      1 |                                   0 |
+------------------------+-------------------------------------+
Copy

此示例显示 DECRYPT_RAW() 函数的相应调用。初始化向量 (IV) 取自加密值;您不需要单独存储初始化向量。同样,AEAD 标签也从加密值中读取。

小心

为简化此示例,加密/解密密钥从包含加密值的表中读取。这是不安全的;密钥 决不能 作为未加密的值存储在用于存储加密数据的表中。

SELECT 'Bonjour' as original_value,
       binary_column,
       hex_decode_string(to_varchar(binary_column)) as decoded,
       encrypted_binary_column,
       decrypt_raw(as_binary(get(encrypted_binary_column, 'ciphertext')),
                  encryption_key,
                  as_binary(get(encrypted_binary_column, 'iv')),
                  aad_column,
                  'AES-GCM',
                  as_binary(get(encrypted_binary_column, 'tag')))
           as decrypted,
       hex_decode_string(to_varchar(decrypt_raw(as_binary(get(encrypted_binary_column, 'ciphertext')),
                  encryption_key,
                  as_binary(get(encrypted_binary_column, 'iv')),
                  aad_column,
                  'AES-GCM',
                  as_binary(get(encrypted_binary_column, 'tag')))
                  ))
           as decrypted_and_decoded
    FROM binary_table;
+----------------+----------------+---------+---------------------------------------------+----------------+-----------------------+
| ORIGINAL_VALUE | BINARY_COLUMN  | DECODED | ENCRYPTED_BINARY_COLUMN                     | DECRYPTED      | DECRYPTED_AND_DECODED |
|----------------+----------------+---------+---------------------------------------------+----------------+-----------------------|
| Bonjour        | 426F6E6A6F7572 | Bonjour | {                                           | 426F6E6A6F7572 | Bonjour               |
|                |                |         |   "ciphertext": "CA2F4A383F6F55",           |                |                       |
|                |                |         |   "iv": "416C736F4E6F745365637265",         |                |                       |
|                |                |         |   "tag": "91F28FBC6A2FE9B213D1C44B8D75D147" |                |                       |
|                |                |         | }                                           |                |                       |
+----------------+----------------+---------+---------------------------------------------+----------------+-----------------------+
Copy

前面的示例重复了对 DECRYPT_RAW() 的长调用。您可以使用 WITH 子句来减少重复:

WITH
    decrypted_but_not_decoded as (
        decrypt_raw(as_binary(get(encrypted_binary_column, 'ciphertext')),
                      encryption_key,
                      as_binary(get(encrypted_binary_column, 'iv')),
                      aad_column,
                      'AES-GCM',
                      as_binary(get(encrypted_binary_column, 'tag')))
    )
SELECT 'Bonjour' as original_value,
       binary_column,
       hex_decode_string(to_varchar(binary_column)) as decoded,
       encrypted_binary_column,
       decrypted_but_not_decoded,
       hex_decode_string(to_varchar(decrypted_but_not_decoded))
           as decrypted_and_decoded
    FROM binary_table;
+----------------+----------------+---------+---------------------------------------------+---------------------------+-----------------------+
| ORIGINAL_VALUE | BINARY_COLUMN  | DECODED | ENCRYPTED_BINARY_COLUMN                     | DECRYPTED_BUT_NOT_DECODED | DECRYPTED_AND_DECODED |
|----------------+----------------+---------+---------------------------------------------+---------------------------+-----------------------|
| Bonjour        | 426F6E6A6F7572 | Bonjour | {                                           | 426F6E6A6F7572            | Bonjour               |
|                |                |         |   "ciphertext": "CA2F4A383F6F55",           |                           |                       |
|                |                |         |   "iv": "416C736F4E6F745365637265",         |                           |                       |
|                |                |         |   "tag": "91F28FBC6A2FE9B213D1C44B8D75D147" |                           |                       |
|                |                |         | }                                           |                           |                       |
+----------------+----------------+---------+---------------------------------------------+---------------------------+-----------------------+
Copy
语言: 中文