I’m using serverless-kms-secrets on serverless frameword to set some ENV variables I want to consume using Ruby.
I can confirm that the plugin works perfectly, it generated the file with the encrypted variable and I can see the encrypted variable in my environment on AWS lambda. The problem is that I can’t decrypt it in Ruby. The code that decrypts it (correctly) in the plugin is here, I understand it gets the string saved in the file and encodes it using Base64, so no big deal. In Ruby:
token = "blablabla"
client = Aws::KMS::Client.new(region: 'us-east-1')
blob = Base64.encode64(token)
client.decrypt({ciphertext_blob: blob})
....
Aws::KMS::Errors::InvalidCiphertextException ()
The client should get my credentials automatically, but I’m not sure I understand how the keyArn is used, doesn’t look relevant though.
Does anybody have any idea how to solve this?
Instead of encoding the string I had to decode it.
token = "blablabla"
client = Aws::KMS::Client.new(region: 'us-east-1')
blob = Base64.decode64(token)
client.decrypt({ciphertext_blob: blob})
It looks like the ciphertext_blob
argument in Aws::KMS::Client#decrypt
expects a binary string that includes the encrypted Ciphertext that you want to decrypt.
In your example, you are passing in an unencrypted Base64 encoded string into decrypt
. Instead, you need to to pass in an encrypted binary string.
To get an encrypted string we can call Aws::KMS::Client#encrypt
with your keyId (also know as your ARN) and the string you want to encrypt in plaintext.
In the response from that call we get back a ciphertext_blob
which is the encrypted binary string that we need to use in order to decode.
Sometimes you might see that binary data "unpacked", which you can demonstrate doing ciphertext_blob.unpack('H*')
. If you have unpacked data and want to decrypt it, you will need to pack it: encrypted_upacked_blob.pack('H*')
.
Here's a full example of a round trip encoding and decoding of a plaintext string:
require 'aws-sdk-kms'
client = Aws::KMS::Client.new
key_id = 'arn:aws:kms:us-east-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
plaintext_to_encrypt = 'blablabla'
encrypt_response = client.encrypt({
key_id: key_id,
plaintext: plaintext_to_encrypt,
})
encrypt_response.ciphertext_blob
# => "\x01\x02\x02\x00xt/Jyu\x85B\xCA\x16v\xDAa3DM1$\e8Y\xF9\x812\x1E\xA9\xD3\xE3R\x1E/}\xCA\x...
encrypted_upacked_blob = encrypt_response.ciphertext_blob.unpack('H*')
# => ["0102020078742f4a79758542ca1676da6133444d31241b3859f981321ea9d3e3521e2f7dca01a7f89f2ee03...
encrypted_packed_blob = encrypted_upacked_blob.pack('H*')
# => "\x01\x02\x02\x00xt/Jyu\x85B\xCA\x16v\xDAa3DM1$\e8Y\xF9\x812\x1E\xA9\xD3\xE3R\x1E/}\xCA\x...
decrypt_response = client.decrypt({
ciphertext_blob: encrypted_packed_blob
})
decrypted_plaintext = decrypt_response.plaintext
# => "blablabla"
This example combines two examples provided by AWS: Encrypting Data in AWS KMS using Ruby SDK and Decrypting a Data Blob in AWS KMS.
For a better understand of what [blob].pack("H*")
is doing, check out this StackOverflow post and Ruby's Array#pack
documentation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With