I have a database where I intend to store KMS-encrypted blobs. Some of the fields are unencrypted (and need to be encrypted) and some of the fields have already been KMS-encrypted.
Looking at the raw data, all of the KMS-encrypted stuff looks kind of similar. Ideally, the AWS KMS API or AWS SDK should have something like a isEncrypted()
method, but it doesn't appear to.
Is there a good way to locally detect whether my field is encrypted or not, short of catching the InvalidCiphertextException
from the decrypt
API?
I think your observation that the encrypted stuff sort of looks the same is valid. It's valid because in the body, the first part is actually the key name that was used to encrypt. that's how KMS knows how to decrypt without you specifying the key (so basically when you encrypt you get something back that's: key description + actually encrypted stuff).
Now, the questions is: do you really want to rely on this observation to ensure if something is encrypted? Do you want to do this at runtime?
As far as the isEncrypted method: how is that different from calling decrypt? It's still a method call.
The real answer is: You should not rely on KMS to encrypt/decrypt stuff you store. You should rely on KMS to encrypt/decrypt the keys you use to encrypt/decrypt your stuff (ie what's called envelope encryption). If you decrypt/encrypt directly via KMS you are going to be limited by the number of calls you can make agains KMS and the max size of what you want to encrypt.
If you switch to envelope encryption it should be trivial to just attempt to decrypt and figure out if content is encrypted or not. That being said, I would recommend to actually be very strict about what is encrypted and enforce it (ie don't guess).
Since we're here: also look at the encryption context for KMS