以下部分介绍了 BigQuery 支持的 AEAD 加密函数。如需了解 AEAD 加密函数的工作原理,请参阅 AEAD 加密概念。
KEYS.NEW_KEYSET
KEYS.NEW_KEYSET(key_type)
说明
返回一个序列化密钥集,其中包含基于 key_type
的新密钥。返回的密钥集是序列化 BYTES
形式的 google.crypto.tink.Keyset,其中包含一个主要加密密钥,不包含其他密钥。您可以将密钥集与 AEAD.ENCRYPT
、AEAD.DECRYPT_BYTES
和 AEAD.DECRYPT_STRING
函数结合使用进行加密和解密,也可与密钥相关函数和密钥集相关函数的 KEYS
组结合使用。
key_type
是 STRING
字面量形式的要创建的密钥类型。key_type
不得为 NULL
。AEAD_AES_GCM_256
是 key_type
目前唯一支持的值。KEYS.NEW_KEYSET(AEAD_AES_GCM_256)
使用 OpenSSL 提供的伪随机数生成器创建一个 256 位密钥。该密钥将使用 AES-GCM 进行加密和解密操作。
返回数据类型
BYTES
示例
以下查询会为 CustomerIds
中的每一行创建一个密钥集,随后该密钥集可用于加密数据。每个密钥集包含单个加密密钥与随机生成的密钥数据。输出中的每一行包含一个 customer_id
和一个 BYTES
形式的 'AEAD_AES_GCM_256'
密钥。
SELECT customer_id, KEYS.NEW_KEYSET('AEAD_AES_GCM_256') AS keyset
FROM (
SELECT 1 AS customer_id UNION ALL
SELECT 2 UNION ALL
SELECT 3
) AS CustomerIds;
KEYS.ADD_KEY_FROM_RAW_BYTES
KEYS.ADD_KEY_FROM_RAW_BYTES(keyset, key_type, raw_key_bytes)
说明
返回一个 BYTES
形式的序列化密钥集,并基于 key_type
和 raw_key_bytes
向 keyset
添加密钥。
主要加密密钥仍与 keyset
中相同。raw_key_bytes
的预期长度取决于 key_type
的值。以下是受支持的 key_types
:
'AES_CBC_PKCS'
:使用密码分组链接和 PKCS 填充为 AES 解密创建密钥。raw_key_bytes
应是长度为 16、24 或 32 的原始密钥BYTES
值;这些长度的大小分别为 128、192 和 256 位。BigQuery AEAD 函数不支持使用这些类型的密钥进行加密;相反,'AEAD_AES_GCM_256'
或'AES_GCM'
是首选的密钥类型。'AES_GCM'
:采用伽罗瓦/计数器模式为 AES 解密或加密创建密钥。raw_key_bytes
必须是长度为 16 或 32 的原始密钥BYTES
值;这些长度的大小分别为 128 和 256 位。当此类型密钥是AEAD.ENCRYPT
的输入时,输出密文不包含指示输入密钥的特定于 Tink 的前缀。
返回数据类型
BYTES
示例
以下查询会创建一个包含原始密钥字节的名为 CustomerRawKeys
的客户 ID 表和一个名为 CustomerIds
的唯一 ID 表。查询会为每个 customer_id
创建一个新的 'AEAD_AES_GCM_256'
密钥集;然后使用与该 customer_id
相对应的 raw_key_bytes
值向每个密钥集添加新密钥。输出是一个表,表中的每一行包含一个 customer_id
和一个 BYTES
形式的密钥集(包含使用 KEYS.ADD_KEY_FROM_RAW_BYTES 添加的原始密钥)。
WITH CustomerRawKeys AS (
SELECT 1 AS customer_id, b'0123456789012345' AS raw_key_bytes UNION ALL
SELECT 2, b'9876543210543210' UNION ALL
SELECT 3, b'0123012301230123'
), CustomerIds AS (
SELECT 1 AS customer_id UNION ALL
SELECT 2 UNION ALL
SELECT 3
)
SELECT
ci.customer_id,
KEYS.ADD_KEY_FROM_RAW_BYTES(
KEYS.NEW_KEYSET('AEAD_AES_GCM_256'),
'AES_CBC_PKCS',
(SELECT raw_key_bytes FROM CustomerRawKeys AS crk
WHERE crk.customer_id = ci.customer_id)
) AS keyset
FROM CustomerIds AS ci;
每个输出密钥集包含两项:使用 KEYS.NEW_KEYSET('AEAD_AES_GCM_256')
创建的主要加密密钥和使用 KEYS.ADD_KEY_FROM_RAW_BYTES
添加的原始密钥。如果输出中的密钥集与 AEAD.ENCRYPT
结合使用,则 BigQuery 会使用 KEYS.NEW_KEYSET('AEAD_AES_GCM_256')
创建的主要加密密钥来加密输入明文。如果密钥集与 AEAD.DECRYPT_STRING
或 AEAD.DECRYPT_BYTES
结合使用,并且任一密钥成功解密密文,则 BigQuery 会返回生成的明文。
AEAD.DECRYPT_BYTES
AEAD.DECRYPT_BYTES(keyset, ciphertext, additional_data)
说明
使用 keyset
中的匹配密钥来解密 ciphertext
并使用 additional_data
验证数据的完整性。如果解密或验证失败,则返回错误。
keyset
是其中一个 KEYS
函数返回的序列化 BYTES
值。keyset
必须包含用于加密 ciphertext
的密钥,该密钥必须处于 'ENABLED'
状态,否则函数会返回错误。AEAD.DECRYPT_BYTES
通过查找密钥 ID 与 ciphertext
中加密的密钥相匹配的密钥,来识别 keyset
中的匹配密钥。
ciphertext
是一个 BYTES
值,它是调用 AEAD.ENCRYPT
的结果,其中输入 plaintext
的类型为 BYTES
。
additional_data
是一个 STRING
或 BYTES
值,可保证加密数据的真实性和完整性。此函数会将任何 STRING
值转换为 BYTES
。此变量必须与提供给 AEAD.ENCRYPT
用于加密 ciphertext
的 additional_data
相同(忽略其类型),否则函数会返回错误。
返回数据类型
BYTES
示例
此示例会创建唯一 ID 的表,其中包含相关明文值和密钥集。然后,它使用这些密钥集将明文值加密为 BYTES
并将其存储在新表中。最后,该示例使用 AEAD.DECRYPT_BYTES
解密已加密的值,并将其显示为明文。
以下语句会创建一个 CustomerKeysets
表,其中包含唯一 ID 列、AEAD_AES_GCM_256
密钥集列和最喜欢的动物列。
CREATE TABLE aead.CustomerKeysets AS
SELECT
1 AS customer_id,
KEYS.NEW_KEYSET('AEAD_AES_GCM_256') AS keyset,
b'jaguar' AS favorite_animal
UNION ALL
SELECT
2 AS customer_id,
KEYS.NEW_KEYSET('AEAD_AES_GCM_256') AS keyset,
b'zebra' AS favorite_animal
UNION ALL
SELECT
3 AS customer_id,
KEYS.NEW_KEYSET('AEAD_AES_GCM_256') AS keyset,
b'nautilus' AS favorite_animal;
以下语句会创建一个 EncryptedCustomerData
表,其中包含唯一 ID 列和密文列。该语句使用 CustomerKeysets
中与每个唯一 ID 相对应的密钥集值来加密明文 favorite_animal
。
CREATE TABLE aead.EncryptedCustomerData AS
SELECT
customer_id,
AEAD.ENCRYPT(keyset, favorite_animal, CAST(customer_id AS STRING))
AS encrypted_animal
FROM
aead.CustomerKeysets AS ck;
以下查询使用 CustomerKeysets
表中的密钥集来解密 EncryptedCustomerData
表中的数据。
SELECT
ecd.customer_id,
AEAD.DECRYPT_BYTES(
(SELECT ck.keyset
FROM aead.CustomerKeysets AS ck
WHERE ecd.customer_id = ck.customer_id),
ecd.encrypted_animal,
CAST(ecd.customer_id AS STRING)
) AS favorite_animal
FROM aead.EncryptedCustomerData AS ecd;
AEAD.DECRYPT_STRING
AEAD.DECRYPT_STRING(keyset, ciphertext, additional_data)
说明
与 AEAD.DECRYPT_BYTES
类似,但其中 plaintext
的类型为 STRING
。
返回数据类型
STRING
AEAD.ENCRYPT
AEAD.ENCRYPT(keyset, plaintext, additional_data)
说明
使用 keyset
中的算法和主要加密密钥来加密明文。将 additional_data
合并到返回的密文中。如果任何输入是 NULL
,则返回 NULL
。
keyset
是其中一个 KEYS
函数返回的序列化 BYTES
值。
plaintext
是要加密的 STRING
或 BYTES
值。
additional_data
是一个要合并到返回的密文中的 STRING
或 BYTES
值。plaintext
和 additional_data
的类型必须相同。AEAD.ENCRYPT(keyset, string1, string2)
等效于 AEAD.ENCRYPT(keyset, CAST(string1 AS BYTES), CAST(string2 AS BYTES))
。
输出是密文 BYTES
。密文将包含特定于 Tink 的前缀,该前缀指示执行加密所用的密钥(该密钥是 'AES_GCM'
密钥时除外)。
返回数据类型
BYTES
示例
以下查询使用 CustomerKeysets
表中的每个 customer_id
的密钥集来加密 PlaintextCustomerData
表中与该 customer_id
相对应的明文 favorite_animal
的值。输出包含 customer_id
值的列和 BYTES
形式的相应密文输出的列。
WITH CustomerKeysets AS (
SELECT 1 AS customer_id, KEYS.NEW_KEYSET('AEAD_AES_GCM_256') AS keyset UNION ALL
SELECT 2, KEYS.NEW_KEYSET('AEAD_AES_GCM_256') UNION ALL
SELECT 3, KEYS.NEW_KEYSET('AEAD_AES_GCM_256')
), PlaintextCustomerData AS (
SELECT 1 AS customer_id, 'elephant' AS favorite_animal UNION ALL
SELECT 2, 'walrus' UNION ALL
SELECT 3, 'leopard'
)
SELECT
pcd.customer_id,
AEAD.ENCRYPT(
(SELECT keyset
FROM CustomerKeysets AS ck
WHERE ck.customer_id = pcd.customer_id),
pcd.favorite_animal,
CAST(pcd.customer_id AS STRING)
) AS encrypted_animal
FROM PlaintextCustomerData AS pcd;
KEYS.KEYSET_FROM_JSON
KEYS.KEYSET_FROM_JSON(json_keyset)
说明
返回序列化 BYTES
形式的输入 json_keyset
STRING
,这是其他 KEYS
和 AEAD
函数的有效输入。JSON STRING
必须与 google.crypto.tink.Keyset 协议缓冲区消息的定义兼容:JSON 密钥集应为 JSON 对象,其中包含与 google.crypto.tink.Keyset 定义中的“keyset”消息的内容相对应的对象和名称-值对。您可以使用 KEYS.KEYSET_TO_JSON
将序列化 BYTES
形式的输出转换回 JSON STRING
。
返回数据类型
BYTES
示例
KEYS.KEYSET_FROM_JSON
接受 JSON 格式的 STRING
值,如下所示:
{
"key":[
{
"keyData":{
"keyMaterialType":"SYMMETRIC",
"typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey",
"value":"GiD80Z8kL6AP3iSNHhqseZGAIvq7TVQzClT7FQy8YwK3OQ=="
},
"keyId":3101427138,
"outputPrefixType":"TINK",
"status":"ENABLED"
}
],
"primaryKeyId":3101427138
}
以下查询会根据 JSON 格式的 STRING
json_keyset
创建一个新的密钥集:
SELECT KEYS.KEYSET_FROM_JSON(json_keyset);
这将返回序列化为 BYTES
的 json_keyset
,如下所示:
\x08\x9d\x8e\x85\x82\x09\x12d\x0aX\x0a0
type.googleapis.com/google.crypto.tink.AesGcmKey\x12\"\x1a qX\xe4IG\x87\x1f\xde
\xe3)+e\x98\x0a\x1c}\xfe\x88<\x12\xeb\xc1t\xb8\x83\x1a\xcd\xa8\x97\x84g\x18\x01
\x10\x01\x18\x9d\x8e\x85\x82\x09 \x01
KEYS.KEYSET_TO_JSON
KEYS.KEYSET_TO_JSON(keyset)
说明
返回 JSON STRING
形式的输入 keyset
。返回的 JSON STRING
与 google.crypto.tink.Keyset 协议缓冲区消息的定义兼容。您可以使用 KEYS.KEYSET_FROM_JSON
将 JSON STRING
形式转换回 BYTES
。
返回数据类型
STRING
示例
以下查询会以 JSON 格式的 STRING
返回一个新的 'AEAD_AES_GCM_256'
密钥集。
SELECT KEYS.KEYSET_TO_JSON(KEYS.NEW_KEYSET('AEAD_AES_GCM_256'));
结果是 STRING
,如下所示。
{
"key":[
{
"keyData":{
"keyMaterialType":"SYMMETRIC",
"typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey",
"value":"GiD80Z8kL6AP3iSNHhqseZGAIvq7TVQzClT7FQy8YwK3OQ=="
},
"keyId":3101427138,
"outputPrefixType":"TINK",
"status":"ENABLED"
}
],
"primaryKeyId":3101427138
}
KEYS.ROTATE_KEYSET
KEYS.ROTATE_KEYSET(keyset, key_type)
说明
根据 key_type
向 keyset
添加一个新密钥。该新密钥将成为新密钥集的主要加密密钥。返回序列化为 BYTES
的新密钥集。
输入 keyset
中的旧主要加密密钥仍是返回的密钥集中的额外密钥。
返回数据类型
BYTES
示例
以下语句会创建一个表,其中包含唯一 customer_id
值的列和 'AEAD_AES_GCM_256'
密钥集。然后,它使用 KEYS.ROTATE_KEYSET
在源表中的每个密钥集内创建一个新的主要加密密钥。输出中的每一行包含一个 customer_id
和 BYTES
形式的 'AEAD_AES_GCM_256'
密钥集。
WITH ExistingKeysets AS (
SELECT 1 AS customer_id, KEYS.NEW_KEYSET('AEAD_AES_GCM_256') AS keyset
UNION ALL
SELECT 2, KEYS.NEW_KEYSET('AEAD_AES_GCM_256') UNION ALL
SELECT 3, KEYS.NEW_KEYSET('AEAD_AES_GCM_256')
)
SELECT customer_id, KEYS.ROTATE_KEYSET(keyset, 'AEAD_AES_GCM_256') AS keyset
FROM ExistingKeysets;
KEYS.KEYSET_LENGTH
KEYS.KEYSET_LENGTH(keyset)
说明
返回所提供密钥集中的密钥数。
返回数据类型
INT64
示例
此示例引用了一个名为 json_keyset
且包含两个密钥的 JSON 格式字符串:
{
"primaryKeyId":1354994251,
"key":[
{
"keyData":{
"keyMaterialType":"SYMMETRIC",
"typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey",
"value":"GiD9sxQRgFj4aYN78vaIlxInjZkG/uvyWSY9a8GN+ELV2Q=="
},
"keyId":1354994251,
"outputPrefixType":"TINK",
"status":"ENABLED"
}
],
"key":[
{
"keyData":{
"keyMaterialType":"SYMMETRIC",
"typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey",
"value":"PRn76sxQRgFj4aYN00vaIlxInjZkG/uvyWSY9a2bLRm"
},
"keyId":852264701,
"outputPrefixType":"TINK",
"status":"DISABLED"
}
]
}
以下查询会将 json_keyset
转换为密钥集,然后返回该密钥集中的密钥数:
SELECT KEYS.KEYSET_LENGTH(KEYS.KEYSET_FROM_JSON(json_keyset)) as key_count;
+-----------+
| key_count |
+-----------+
| 2 |
+-----------+