You shouldn't think of it as ‘using an IV with AES’. In fact, unless you are a cryptographer, you should forget that ‘AES’ itself exists as a thing: it is a pseudorandom permutation family $\operatorname{AES}_k\colon \{0,1\}^{128} \to \{0,1\}^{128}$, which is a technical jargon term that is practically meaningless to any application developer.
Instead, you should first identify what you are trying to do, such as send messages—arbitrary-length bit strings—from Alice to Bob who share a secret key. You should also have in mind how many messages Alice and Bob will send (a handful? a few thousand? a few quadrillion?), and how long they might be (a kilobyte? a gigabyte? an exabyte?). Then you should identify the adversary's capabilities, such as either eavesdropping on or possibly interfering with the channel from Alice to Bob. Then you should decide what security properties you want: Should the adversary be prevented from reading messages? From forging messages?
Once you have these written down in a design document for your application, then you can think about how crypto can help you.
Usually what you want is to make sure that an adversary can't read or forge messages, unless you have a very compelling reason to argue that the adversary doesn't even have the opportunity to forge messages in the first place (example: disk encryption on your laptop—if customs takes your laptop out of sight at the border, you don't really want to use that laptop again) or sell analytics about your users' conversations to authoritarian fascist regimes.
To thwart an adversary who can eavesdrop on and meddle with the channel between Alice and Bob, you should pick an authenticated cipher, or authenticated encryption with associated data (AEAD) scheme.
An authenticated cipher at the sender's end takes a key and a message (an arbitrary bit string) and some other parameters and returns a ciphertext, and at the receiver's end takes a key and a ciphertext and some other parameters and either screams FORGERY!!!1 or returns a message.
Here's an example of an authenticated cipher: AES-GCM. Don't read AES-GCM as ‘the block cipher pseudorandom permutation family AES, in the Galois/Counter mode of operation’—read AES-GCM as the following contract:
This is a contract, between you, an application developer, and AES-GCM, a spell cast by high wizards of cryptography endorsed by the United States federal government and other lesser empires.
Your obligations:
- You must pick a 256-bit secret key $k$ uniformly at random and keep it secret.
- For each message you send under the same key $k$, you must use a unique 96-bit nonce $n$ (sometimes also called initialization vector) which sender and receiver agree on for each message. (You may transmit it alongside the message, or you might infer it from context, such as a message sequence number. If Alice and Bob exchange messages in both directions, they must not choose the same nonce, so make sure, e.g., Alice uses even nonces and Bob uses odd nonces.)
- You must not send more than $2^{60}$ bytes of data total using the same key $k$.
- If you pick $n$ randomly, you must not send more than $2^{32}$ messages using the same key $k$. If you pick $n$ sequentially, you must not send more than $2^{48}$ messages using the same key $k$.
IN EXCHANGE, AES-GCM guarantees, against an adversary who can adaptively influence plaintexts sent by Alice and Bob and ciphertexts opened by Alice and Bob,
- The adversary cannot distinguish the ciphertexts of two equal-length messages even of their choice sent between Alice and Bob, and thus cannot read messages chosen by Alice or Bob.
- The adversary cannot forge messages not chosen by Alice or Bob.
If you violate any terms of this contract, the security properties provided by AES-GCM shall be rendered null and void.
The security contract for AES-CBC is a little bit different, partly because AES-CBC does not provide authentication, which are words that should scare the ever-living daylights out of you. AES-CBC is only an encryption scheme, not an authenticated-encryption scheme. AES-CBC also requires you to pad your messages, e.g. with PKCS#7 padding, which is a source of disasters called padding oracle attacks.
This is a contract between you, an application developer, and AES-CBC, a meager spell cast by early wizards of cryptography who ill-understood the consequences or persistence of the magic they were weaving in a bygone era of primordial cryptosorcery before the modern foundations on whose shoulders we now stand were built.
Your obligations:
- You must pick a 256-bit secret key $k$ uniformly at random and keep it secret.
- You must ensure your messages are always an integer multiple of 128 bits long.
- For each message you send under the same key $k$, you must choose a 128-bit initialization vector that is (a) unique and (b) unpredictable in advance. (You may transmit it alongside the message, or you might derive it from context, such as by a pseudorandom function of the message sequence number under another secret key shared by sender and receiver.)
- You must not send more than $2^{60}$ bytes of data total using the same key $k$.
- You must not send more than $2^{48}$ messages using the same key $k$.
IN EXCHANGE, AES-CBC guarantees, against an adversary who can adaptively influence plaintexts sent by Alice and Bob,
- The adversary cannot distinguish the ciphertexts of two equal-length messages even of their choice sent between Alice and Bob, and thus cannot read messages chosen by Alice or Bob.
- That's all. You don't get any more out of this contract, buddy.
If you violate term (3)(a) of your obligations, the adversary can tell when two ciphertexts conceal the same messages. If you violate any other terms of this contract, the security properties provided by AES-CBC shall be rendered null and void.
There are other widely deployed authenticated ciphers out there, such as NaCl crypto_secretbox_xsalsa20poly1305 or libsodium's variants, which are all-around safer than AES-GCM but have fewer imperial endorsements. There are also other spells built out of AES, sometimes colloquially called ‘modes of operation’ by cryptographers who value job security over the ability of anyone outside the high priesthood to handle cryptographic spells and user privacy and secrets and integrity, but this is not the forum for a catalog of all the spells—you need to write that design document first before we can say more about what crypto you should use if an authenticated cipher is not what you need.
Finally, to answer the question you asked: It does not make sense to fail to provide an initialization vector for an operation that takes one.
But there are some APIs that are well-designed to maximize the confusion of dear readers like you by providing an endless array of hyperconfigurable options to pick a block or stream cipher and which cipher and key length and key and mode of operation and initialization vector and nonce and authentication tag and padding scheme and message encoding and message—all this to season your indecipherable acronym soup.
In these APIs, if you fail to provide some optional function parameter specifying an IV, or if you don't call the set_iv
method or what-have-you, gnomes behind the scenes might silently choose an IV for you. I recommend avoiding these APIs, or, if you must use them, treating them like nuclear waste requiring high degrees of protective gear and hand-holding by experts.