* Pad your source URL using the [PKCS #7](https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS#5_and_PKCS#7) method so it becomes 16-byte aligned. Some libraries like Ruby's `openssl` do the message padding for you
* Generate a 16-byte long initialization vector (IV)
* Encrypt the padded source URL with the AES-CBC algorithm using the configured key and the IV generated in the previous step
* Create the following string: IV + encrypted URL
* Encode the result of the previous step with URL-safe Base64
#### IV generation
AES-CBC requires IV to be unique between unencrypted messages (source URLs in our case). Usually, it's recommended to use a counter when generating an IV to be sure it never repeats. However, in our case, this leads to a major drawback: using a unique IV every time you encrypt the same source URL will lead to different cipher texts and thus different imgproxy URLs. And this leads to a situation where requests to imgproxy will never hit the CDNs cache.
On the other hand, reusing the IV with the same message is safe but ONLY while with this message. Thus, there are some tradeoffs:
1. Cache IVs. Store IV somewhere so you need to generate it only once for each source URL and extract it if needed. Depending on the level of security you need, you may also want to encrypt stored IVs with a different key so a DB leak won't reveal the message-IV pairs.
2. Use a deterministic method of generation. For example, you can calculate an HMAC hash of the plain source URL with a different key and truncate it to the IV size. Though this method doesn't guarantee that it will always generate unique IVs, the chances of generating repeatable IVs with it are considerably rare.
### Example
**You can find helpful code snippets in various programming languages in the [examples](https://github.com/imgproxy/imgproxy/tree/master/examples) folder. There's a good chance you'll find a snippet in your favorite programming language that you'll be able to use right away.**
And here is a step-by-step example of a source URL encryption:
Before we start, we need an encryption key. We will use the AES-256-CBC algorithm in this example, so we need a 32-byte key. Let's assume we used a random generator and got the following hex-encoded key:
**📝 Note:** The imgproxy URL in this example is not signed but signing URLs is especially important when using encrypted source URLs to prevent a padding oracle attack.