无法生成 Azure CustomerProvidedEncryptionKey (cpk)

Unable To Generate Azure CustomerProvidedEncryptionKey (cpk)

我正在尝试从 AWS S3 迁移到 Azure Blob 存储,但在生成客户提供的加密密钥时遇到了一些问题。作为参考,在 AWS 中,可以轻松启用服务器端加密 (AWS Server-Side Encryption)。在 Azure 中,使用 CustomerProvidedEncryptionKey 也应该可以做到这一点。

Microsoft 创建 CustomerProvidedEncryptionKey 的要求如下 (Microsoft Docs on CPK):

key_value: str (Required)
Base64-encoded AES-256 encryption key value.

key_hash: str (Required)
Base64-encoded SHA256 of the encryption key.

然而,当我创建任何 32 个字符长的 AES256 加密密钥及其 SHA256 哈希时,无论我如何生成或编码它们,我都无法让 python SDK 接受它们。

我目前的工作:

import hashlib
import base64
from azure.storage.blob import (
    ContainerClient,
    __version__,
    CustomerProvidedEncryptionKey,
)
import os

local_file_name = "sample.txt"
target_file_name = "sample-encrypted.txt"
container_name = "test"
connection_str = "<redacted>"

# Key and its Hash
key_value = b"32byteslongsecretkeyshallbegiven"
key_hash = hashlib.sha256(key_value).hexdigest().encode()

# Encode the key and its hash into base64
key_value_encoded = base64.b64encode(key_value)
key_hash_encoded = base64.b64encode(key_hash)

# Create cpk object to provide to Azure
cpk = CustomerProvidedEncryptionKey(key_value_encoded, key_hash_encoded)

# Create the BlobServiceClient object which will be used to create a container client
container_client = ContainerClient.from_connection_string(
    connection_str,
    container_name=container_name,
)

# Upload the blob
with open(local_file_name, "rb") as data:
    container_client.upload_blob(
        data=data, name=target_file_name, overwrite=True, cpk=cpk
    )

这将失败并显示消息:

ErrorCode:InvalidHeaderValue
headername:x-ms-encryption-key
headervalue:b'MzJieXRlc2xvbmdzZWNyZXRrZXlzaGFsbGJlZ2l2ZW4='

当使用微软创建的测试用例中的硬编码密钥和散列值时,我能够使用客户端提供的密钥进行服务器端加密对于 SDK (Azure SDK Test Case with hardcoded key).

TEST_ENCRYPTION_KEY = CustomerProvidedEncryptionKey(
key_value="MDEyMzQ1NjcwMTIzNDU2NzAxMjM0NTY3MDEyMzQ1Njc=",
key_hash="3QFFFpRA5+XANHqwwbT4yXDmrT/2JaLt/FKHjzhOdoE="
)

请注意,它们的硬编码键值和键哈希长度为 44 个字符,这意味着在本例中它是一个编码为 base64 的 32 个字符的字符串。这对哈希值很奇怪,因为真正的 SHA256 哈希值有 64 个字符长,如果用 base64 编码的话会更长。这意味着使用了其他一些(未知的)哈希算法来生成 key_hash.

如果我在上面的代码片段中没有提供密钥,则上传成功,如果我提供硬编码密钥及其散列,则上传成功并被加密。但是,我找不到任何方法来生成密钥及其哈希值以成功上传和加密任何 blob。

任何方向将不胜感激!

代码片段的问题在于密钥散列的编码。由于哈希的 hexdigest 是一个 python 表示十六进制字符串的字符串对象,因此我们必须特别注意对其进行解码并将其类型视为十六进制。此外,我们必须将 base64 编码的字符串重新编码为 python 字符串对象,然后再将其传递给 CustomerProvidedEncryptionKey。

有关完整的工作代码,请参阅 https://gist.github.com/CodyRichter/a18c293d80c9dd71a3905bf9c44e377f