The difference between a queryable TextEncryptor and a standard TextEncryptor has to do with initialization vector (iv) handling. The iv used in a queryable TextEncryptor#encrypt operation is shared, or constant, and is not randomly generated. This means the same text encrypted multiple times will always produce the same encryption result. This is less secure, but necessary for encrypted data that needs to be queried against. An example of queryable encrypted text would be an OAuth apiKey.
Looking at the source, it seems to use
AES/CBC/PKCS5Padding with a constant all-zero IV. (Note: In Java,
PKCS5Padding really means PKCS#7 padding).
The purpose of this method seems to be for using the ciphertext as a key (the "key into a map/index/etc." meaning, not the "encryption key" meaning).
My questions are:
- What is a practical use of such scheme? I tried to think of one, but it just seems contrived:
- The system has a secret key (for example, a sequential primary key that it doesn't want an attacker to enumerate).
- The system gives the ciphertext to a user that will send it back at a later time to query information related to it.
- When the user sends back the ciphertext, the system will decrypt it, query the databse, and return the information.
For the above contrived scenario, I can think of many better solutions to the problem:
- If the system will decrypt it before querying, why have the same ciphertext for the same plaintext? Just use proper encryption with random IV.
- If the system will not decrypt it, why not use an opaque sufficiently-long randomly-generated ID?
- Or better yet, have proper access control when the user queries the information.
- From the documentation quote above, why would an OAuth apiKey be encrypted in the first place?
So what exactly is this method good for?
- What are the security implications of this "less secure" (as the documentation calls it) encryption if used as designed?