0
votes

I have a python script trying to encrypt a file with AWS KMS using boto3. I can get the file encrypted and wrote into a file. But when I tried to decrypted the file using the second part code, it raised an error as below, could someone help on this or there are any better solutions? Many thanks.

Traceback (most recent call last): File "runtime/lib/python3.4/site-packages/botocore/client.py", line 357, in _api_call return self._make_api_call(operation_name, kwargs) File "runtime/lib/python3.4/site-packages/botocore/client.py", line 661, in _make_api_call raise error_class(parsed_response, operation_name) botocore.errorfactory.InvalidCiphertextException: An error occurred (InvalidCiphertextException) when calling the Decrypt operation:

Encrypt a file

client = boto3.client(
    'kms',
region_name='us-east-1',
    aws_access_key_id=aws_access_key_id,
    aws_secret_access_key=aws_secret_access_key
)

with open(src_file, 'rb') as infile :

    with open(ret_file, 'wb') as outfile :

        while True:
            chunk = infile.read(chunk_size)
            if not chunk :
                break
            resp = client.encrypt(KeyId=kms_id, Plaintext=chunk)['CiphertextBlob']
            outfile.write(resp)

Decrypt the file encrypted before

client = boto3.client(
    'kms',
    region_name='us-east-1',
    aws_access_key_id=aws_access_key_id,
    aws_secret_access_key=aws_secret_access_key
)

with open(src_file, 'rb') as infile :

    with open(ret_file, 'wb') as outfile :

        while True:
            chunk = infile.read(chunk_size)
            if not chunk :
                break
            resp = client.decrypt(CiphertextBlob=chunk)['Plaintext']
            outfile.write(resp)
1

1 Answers

1
votes

The reason why you are getting that error is because the ciphertext you get back from KMS is not the same length as the plaintext you encrypted. Furthermore, KMS makes no guarantees about the size or format of that ciphertext remaining constant. You should treat the KMS ciphertext as a black box.

Additionally, KMS does not recommend that you send your plaintext directly to KMS. Rather, they recommend that you instead use envelope encryption: use KMS to encrypt data keys, and use those data keys to encrypt your data. Not only does this result in far fewer calls to KMS in cases like yours, it also creates a separation of resources: at no time does KMS have both your encrypted data and the key needed to decrypt it.

For your use case, have you considered using the AWS Encryption SDK[1][2]? It provides an easy to use implementation of envelope encryption and makes it simple to use KMS to protect your data. You can find an example of configuring it to use KMS here[3] and an example of encrypting and decrypting a file here[4].

[1] https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html

[2] https://aws-encryption-sdk-python.readthedocs.io/en/stable/

[3] https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/basic_encryption.py#L29

[4] https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/basic_file_encryption_with_multiple_providers.py#L96-L107