nsmithuk / local-kms

A mock version of AWS' Key Management Service, for local development and testing.
MIT License
198 stars 34 forks source link

Unable to do encrypt/decrypt roundtrip with key aliases #28

Closed whummer closed 3 years ago

whummer commented 3 years ago

Hi @nsmithuk - thanks for providing this great library. (As you know, we're happily using it in LocalStack..)

Question regarding encrypt/decrypt roundtrip - this might be related to incorrect usage, or potentially may point to an issue in the implementation.

$ key_id=$(awslocal kms create-key | jq -r '.KeyMetadata.KeyId')
$ awslocal kms create-alias --alias-name alias/test --target-key-id $key_id
...
$ encrypted=$(awslocal kms encrypt --plaintext=test --key-id=alias/test --query=CiphertextBlob --output text)

$ # attempting to decrypt, without key-id specified
$ awslocal kms decrypt --output text  --query=CiphertextBlob --ciphertext-blob $encrypted
An error occurred (AccessDeniedException) when calling the Decrypt operation: The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access.

$ # attempting to decrypt, with key-id specified
$ awslocal kms decrypt --key-id $key_id --output text  --query=CiphertextBlob --ciphertext-blob $encrypted
An error occurred (InvalidCiphertextException) when calling the Decrypt operation: 

If you can point us in the right direction, we can also try to contribute a PR to fix this issue (just wanted to confirm first if there's a workaround for this). Thanks for your help!

nsmithuk commented 3 years ago

Hi @whummer

A fun quirk of KMS via the CLI

Thus hopefully the following works as you'd expect:

key_id=$(awslocal kms create-key | jq -r '.KeyMetadata.KeyId')

awslocal kms create-alias --alias-name alias/test --target-key-id $key_id

encrypted=$(awslocal kms encrypt --plaintext=test --key-id=alias/test --query=CiphertextBlob --output text)

echo $encrypted | base64 --decode > encrypted.dat

awslocal kms decrypt --output text  --query=Plaintext --ciphertext-blob fileb://encrypted.dat

I will sense check that error message when I get a moment to ensure it matches what AWS actually return.

There are examples of doing symmetric encryption with KMS here: https://nsmith.net/aws-kms-cli

nsmithuk commented 3 years ago

@whummer Looking into this further, I am struggling to replicate your issue.

What you had runs fine for me, with the exception of your --query= on the decrypt needs to be looking for Plaintext. So:

key_id=$(awslocal kms create-key | jq -r '.KeyMetadata.KeyId')
awslocal kms create-alias --alias-name alias/test --target-key-id $key_id
encrypted=$(awslocal kms encrypt --plaintext=test --key-id=alias/test --query=CiphertextBlob --output text)
awslocal kms decrypt --output text --query=Plaintext --ciphertext-blob $encrypted

Do you know what version of Local KMS you're seeing your exception on?

whummer commented 3 years ago

Thanks for your quick response @nsmithuk . Looks like there seems to be a difference between AWS CLI v1 and v2.

In the test below, awslocal is using the v1 CLI, and awslocal2 is using the v2 CLI. It seems to be working with v2, but not with v1:

$ awslocal kms decrypt --ciphertext-blob $(awslocal kms encrypt --plaintext=test --key-id=alias/test --query=CiphertextBlob --output text)

An error occurred (AccessDeniedException) when calling the Decrypt operation: The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access.
$ awslocal2 kms decrypt --ciphertext-blob $(awslocal2 kms encrypt --plaintext=test --key-id=alias/test --query=CiphertextBlob --output text)
{
    "KeyId": "arn:aws:kms:eu-central-1:000000000000:key/3c6edd3d-b405-4854-81ec-fc0b94e7e0f4",
    "Plaintext": "test",
    "EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}

I think we can close this issue for now - will create follow-up tickets in case any other issues come up. Thanks!