Google Cloud KMS:无法解密

Posted

技术标签:

【中文标题】Google Cloud KMS:无法解密【英文标题】:Google Cloud KMS: Unable to decrypt 【发布时间】:2018-01-23 18:21:55 【问题描述】:

我正在尝试解密 kms 加密文件并遇到以下错误:

UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 3: invalid start byte

我正在使用示例解密代码。

我可以使用命令行解密文件。

从这里抛出异常:

cipher_text.decode('utf-8')

代码:https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/kms/api-client/snippets.py

如果我在这里遗漏了什么,请告诉我。

【问题讨论】:

发现使用命令行实用程序加密的文件无法使用 Python 解密 API 解密(不确定它是否与其他语言 API 相同)。因此,要通过 Python API 解密加密文件,还必须通过 encrypt Python API 进行加密。不确定我的理解是否正确,但使用上述方法使其工作。 【参考方案1】:

使用 Python 库时,所有输入都必须经过 base64 编码,输出也必须经过 base64 编码。在 sn-ps.py 中的 encrypt 函数中,您可以看到代码在将明文传递给 KMS 加密 API 之前对明文进行 base64 编码。

encoded_text = base64.b64encode(plaintext)

使用gcloud kms encrypt命令时,明文不用自己base64编码,密文也不是base64编码的。

因此,当您将密文从gcloud kms encrypt 传递给Python 库进行解密时,您必须先对其进行base64 编码。将 sn-ps.py 中的解密函数更改为对文件数据进行 base64 编码,然后再发送。

# Read cipher text from the input file.
with io.open(encrypted_file_name, 'rb') as encrypted_file:
    ciphertext = encrypted_file.read()
encoded_text = base64.b64encode(ciphertext)

# Use the KMS API to decrypt the text.
cryptokeys = kms_client.projects().locations().keyRings().cryptoKeys()
request = cryptokeys.decrypt(
    name=name, body='ciphertext': encoded_text.decode('utf-8'))
response = request.execute()

您可以将 base64 编码视为传输层的实现细节:只有这样才能以 JSON 格式发送任意二进制数据,它只接受 Unicode 字符串。因此,Cloud KMS API 要求对这些数据进行 base64 编码,并且还必须对输出进行 base64 编码。但是 gcloud 命令会为您完成这项工作,因此您不必这样做。

我认为 Python 示例代码具有误导性。它应该始终对 API 的输入进行 base64 编码,并对输出进行 base64 解码,而不是有时才这样做。我会尽快更新 Python 示例代码,并仔细检查其他语言的示例代码。

【讨论】:

感谢您的澄清。有道理。 Python示例代码已修复,见github.com/GoogleCloudPlatform/python-docs-samples/commit/…。【参考方案2】:

鉴于问题的日期,接受的答案应该是@Russ(另外,感谢您更新 git)。 由于文档稍有改动,这里有一个处理已加密 json 文件的函数。

使用 GCloud 命令行加密:

gcloud kms encrypt \
  --plaintext-file=[SECRETS.json] \
  --ciphertext-file=[ENCRYPTED-SECRETS.json.enc] \
  --location=[REGION] \
  --keyring=[KEYRING-NAME] \
  --key=[KEY-NAME]

这里是解密所述文件的函数(cipher_file[ENCRYPTED-SECRETS.json.enc]的路径):

def decrypt(cipher_file):
    project_id = "project"
    location_id = "region"
    key_ring_id = "key-ring"
    crypto_key_id = "key"

    # Creates an API client for the KMS API.
    client = kms_v1.KeyManagementServiceClient()

    # The resource name of the CryptoKey.
    name = client.crypto_key_path_path(project_id, location_id, key_ring_id,
                                       crypto_key_id)

    # Use the KMS API to decrypt the data.
    with io.open(cipher_file, "rb") as file:
        c_text = file.read()

    response = client.decrypt(name, c_text)

    secret_dict = json.loads(response.plaintext.decode("utf-8"))

    return secret_dict

【讨论】:

以上是关于Google Cloud KMS:无法解密的主要内容,如果未能解决你的问题,请参考以下文章

Google Cloud KMS App Engine 加密不起作用

获取解密密文时使用的 Google KMS 密钥的版本

您可以在具有服务角色的项目之间共享 Google Cloud KMS 密钥吗?

管理员无法在 AWS KMS 中加密/解密

使用默认 aws/S3 KMS 密钥对解密对象进行跨账户访问

从非 Google 系统调用时,CloudKMS 加密/解密如何安全工作?