3

我正在尝试解密 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

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

4

2 回答 2

6

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

encoded_text = base64.b64encode(plaintext)

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

因此,当您将密文传递gcloud kms encrypt给 Python 库进行解密时,您必须先对其进行 base64 编码。将 snippets.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 示例代码,并仔细检查其他语言的示例代码。

于 2017-08-16T15:09:44.430 回答
0

鉴于问题的日期,接受的答案应该是@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
于 2019-09-27T13:15:08.147 回答