The general method for shortest ciphertext goes
- Compress [but see cautionary note], perhaps using a general-purpose lossless compression such as (among many) Deflate or LZFSE; or some context-aware compression.
- Encrypt, using authenticated encryption such as (among many) AES(-256)-GCM-SIV.
- If the context requires, reformat to fit requirement, e.g. as Base64.
Decryption undoes each layer in reverse order. It is critical to use authenticated encryption or (much preferably, and) a robust de-compressor to avoid all kind of attacks, or crashes when deciphering an invalid ciphertext or decryption key.
For “a list of data URIs (that) are thousands of characters in length”, compression in step 1 will I guess reduce size by more than 1/4. It can outweigh the (small, constant) expansion in 2, and the ≈1/3 expansion of Base64 in step 3.
CAUTION: with compression, the size of ciphertext will reveal something about the size and compressibility of the plaintext, when normally encryption reveals only the size. This is known to be an issue in some contexts (including, digitized voice). Knowledge about the nature of the URI and what's confidential in them would be required to determine if that's an issue . If in doubt, don't compress.
Note: if size is paramount, and it is not an issue (or perhaps, if it is desired) that encryption of the same data with the same key always yields the same ciphertext, then it is safe to use a constant (e.g. all-zero and implicit) Initialization Vector in an authenticated encryption with the aforementioned AES-GCM-SIV.