Is an IV useless for encrypting database IDs? In my scenario I need to build a pseudo-anonimization service: a machine that given a plainID return a chiperID and vice-versa. chiperID are created when an unknown plainID is provided. So I have an identities table that grows keeping track of this mapping by storing the couple [plainID-chiperID]. To keep it safe against direct accesses to the db I need to encrypt one of them so I actually store [encryptedPlainID-chiperID]

My app is the only one that needs to encrypt and decrypt IDs so I am going to use a symmetric encryption algorithm like AES-256-* where the key is kept by the application. 

Hence:


to obtain the plainID by providing the chiperID the application
needs to query the identities table directly by chiperID and then
decrypt the encryptedPlainID.
Vice-versa, to obtain the chiperID by providing the plainID the
application firstly needs to encrypt the plainID and then query
the identities table by the encryptedPlainID


I know that not using an IV make the algorithm insecure but I have some doubt that storing the IV for later decryption along with the encrypted ID make the whole system secure. To be clear I wonder if I need to store in the identities table the triple [encryptedPlainID-IV-chiperID]

But with this schema I cannot do the point 2 because I don't know a priori the IV used to encrypt the plainID

What can I do? Does the block cipher mode of operation matter?
The mode of operation does not just matter; it defines the properties of the IV! The mode of operation is the part that specifies the size of the IV, the contents of the IV as well as the impact of abusing the IV. AES is a block cipher; by itself it only allows the key and a single message block as input; AES itself doesn't specify or know about any IV.

For instance, CBC mode requires an unpredictable (read: randomized) IV of the same size as the block size for common cryptographic purposes. If you fail to provide it then an adversary can detect identical ciphertext blocks and retrieve information on the plaintext blocks at the same location - very likely including IDs.

GCM mode on the other hand defaults to a 12 byte IV (although other sizes are possible). The IV is actually just a (binary) nonce: a number used once; you would be fine as long as it never repeats for the same key. However, if it fails then you can XOR ciphertext together to retrieve the XOR of two different plaintexts - which would quickly lead to a complete break of confidentiality for most types of plaintext.



Quite often IV's are simply prepended to the ciphertext. Most modes of operation have a statically sized IV (and if they haven't you can standardize the IV size for your specific protocol). Using a cryptographically secure, random IV is a well-established practice which you could use for your specific problem, as long as your DB is able to store the expanded ciphertext.

If you also want the IDs to be integrity protected you might also need storage space for an authentication tag. A mode such as GCM is often used for this; authentication tags are generally 8 to 16 bytes (with 16 bytes giving most protection of course). HMAC could also be used for integrity protection, in which case the IV should be included in the calculation.



Which brings us to the static IV (SIV) mode of operation. With SIV the IV doubles as an authentication tag. For SIV mode the uniqueness of the plaintext assures the uniqueness of the IV. It has storage advantages over IV + authentication tag, and it doesn't require any separate random input or state machine (for a nonce / counter). Although it does expand the ciphertext size it seems otherwise perfect for encrypting ID values - as long as they don't repeat for multiple users.

There is also AES-GCM-SIV which brings the efficiency of AES-GCM to SIV mode. The original SIV uses AES-CMAC as an authentication mechanism.



If IDs are unique and fit inside a single block then you could simply use a single block encrypt to store ID's. Beware that this is brittle; if somebody decides to expand the ID size then the scheme may well break. You can use ECB mode for this if the block cipher is not directly available. CBC mode with a zero IV would perform the same operation for the first block. Using ECB or CBC makes the scheme even more brittle of course; using two blocks or more could introduce vulnerabilities.

And finally, if you need to store the IDs within the same amount of data then you may have a look at Format-Preserving Encryption (FPE). This is a less efficient mode with a higher learning curve and limited support. Like SIV mode it depends on the uniqueness of the input to achieve confidentiality. Its main advantage is that it doesn't expand the ciphertext over the plaintext size, regardless of how much data is occupied by the plaintext. It isn't limited by the block size, in other words.



Notes:


It is also fine to store the random IV's somewhere else in the DB, e.g. in a separate row.
Adding an authentication tag only provides limited protection against active attacks, for instance an attacker swapping encrypted ID's of different users. Generally DB is about securing data at rest, providing confidentiality of the ID's in case the DB gets stolen for instance. It's up to you to decide if the additional space required for the authentication tag is worth the cost.
Beware that messages / IDs may also be repeated in time. Relying on the uniqueness of the ID may e.g. still allow an adversary to track the ID for a specific user. If this is an attack vector or not depends on the specific use case.