This is a super short post, but something that I came across that others may run into.
Use 16-bytes for AES-GCM IVs. It’s what everyone else seems to be using.
We use 256-bit AES-GCM keys to secure our device linking flows, which run over IPFS PubSub (i.e. on WebRTC), as well as on a custom hosted WebSocket relay as fallback. This makes it a critical component for us here at Fission.
We ran into a problem where our CLI could link to other CLIs just fine, browsers could link to each other, but not across. After much debugging, the issue was a mismatched initialization vector (IV) length.
The original 2007 AES-GCM NIST paper recommends using a 12-byte IV because…
For IVs, it is recommended that implementations restrict support to the length of 96 bits [12 bytes], to promote interoperability, efficiency, and simplicity of design.
As such, the MDN docs on AES for WebCrypto have an example that uses a 12-byte IV, and links to that paper.
Our CLI is written in Haskell, and has a hardcoded 16-byte IV requirement (it checks on parse). By coincidence, a base64 encoded 16-byte IV looks like 12-bytes, so we effectively had the wrong IV (my bad). Looking around at other libraries in Java, C, Go, and others, they all default to 16-bytes.
The W3C WebCrypto API spec makes no recommendation on IV size, other than requiring that it be smaller than 264 bytes.
Also fun fact: the
openssl CLI tool includes AES in its ciphers, but fails with a “AEAD ciphers not supported” message when you try to use them.