
AES-GCM-SIV: Nonce Misuse-Resistant Authenticated Encryption - conductor
https://tools.ietf.org/html/rfc8452
======
colmmacc
Here's a TLDR in case you're curious:

AES-GCM is an API that takes 4 inputs. AES-GCM(key, nonce, additional_data,
plaintext). The nonce is also called an initialization vector (IV). The key
and nonce/IV are used to encrypt the plaintext using AES-CTR. A keyed hash,
GHASH, is then computed over the additional data and the cipher text. That
hash is encrypted with AES too, and you get an authentication tag.

AES-GCM-SIV has two big differences. Firstly, GHASH is replaced with POLYVAL,
a hash that is almost exactly the same but reverses the order of some bytes
because it turns out that's more efficient on most platforms. Secondly, rather
than using the key and a nonce to initialize the AES-CTR encryption, a
synthetic IV is computed from the nonce that the caller provides and an
encrypted POLYVAL hash of the plaintext.

This difference means that even if the caller uses the same nonce twice, which
is bad, that the synthetic IV will still be different as long as the plaintext
messages are different. This is what makes the nonce resistance. This is great
for cases where we're using the same key over and over in a distributed way,
and all of the senders can't guarantee not to use the same nonces, they might
collide. TLS session tickets and cookies are good examples of that.

Two small gotchas: the biggest is that when encrypting the message, we have to
pass over it twice, once to compute the hash, and once to encrypt it. The
second is that it's still possible to screw things up on the caller side, SIV
doesn't magically make it ok not to make an attempt at setting a random nonce.
For example if you use the null/all-zeroes nonce over and over, identical
messages are going to be trivially finger-printable.

~~~
metalliqaz
Related to gotcha #1 - it also means that you have to have the entire message
available when you start encryption. Lightweight embedded systems may not be
able to meet that requirement.

~~~
olliej
the problem with gcm’s nonce reuse weakness is that the best way to generate a
unique nonce is as a hash of the input message - otherwise you technically
have to record every nonce you’ve ever used.

I guess an alternative would be to have a secret key and a counter and then
have the nonce be something like aes(key, counter++) but obviously that has
scalability issues

I’m sure @tqpf/@tqbf (I cant recall) has opinions :)

~~~
admax88q
> the best way to generate a unique nonce is as a hash of the input message -
> otherwise you technically have to record every nonce you’ve ever used.

That doesn't sound right.

I would wager that using a cryptographically secure RNG is less likely to
produce the same number twice, or at the very least equally as likely. If you
have a very strong hash, then the hash algorithm should act the same as an
RNG.

~~~
olliej
The problem with gcm is that you absolutely cannot ever reuse a nonce, hence
gcm-siv using a hash of the message - assuming a cryptographically strong hash
the hash collision rate should theoretically have lower odds than a pure ring
(sqrt(hashsize) vs likelihood of non-random different data colliding in
_practice_ )

Of course all of this is on the assumption that any hashes and rngs you use
are secure :)

In practice: many sites using gcm were using rng based nonces that end up
colliding

~~~
admax88q
I get why 'SIV' used a hash of the message in addition to the user provided
nonce.

My point was I disagree on your sentence "the best way to generate a unique
nonce is as a hash of the input message - _otherwise_ you technically have to
record every nonce you’ve ever used."

That implies that a hash is strong enough that you don't need to track
messages. If you believe that to be the case then a CSRNG would be equally as
strong of not stronger and less complex. Still sqrt(n) chance of collision.

------
praseodym
> some AEADs (including AES-GCM) suffer catastrophic failures of
> confidentiality and/or integrity when two distinct messages are encrypted
> with the same key and nonce. While the requirements for AEADs specify that
> the pair of (key, nonce) shall only ever be used once, and thus prohibit
> this, this is a worry in practice.

Could anyone explain what this catastrophic failure entails? Do both messages
suddenly get decryptable, or is the entire AES key compromised?

~~~
CiPHPerCoder
You immediately lose your integrity protections, which allows you to launch
attacks against AES-CTR as if it had no authentication tag.

[https://cryptologie.net/article/361/breaking-https-aes-
gcm-o...](https://cryptologie.net/article/361/breaking-https-aes-gcm-or-a-
part-of-it/)

~~~
amluto
You also learn the XOR or the two plaintexts, which can be a catastrophic loss
of confidentiality.

~~~
joe_xyz
You can also determine the keyed hash function key if you collect enough
plaintexts, which would let you forge authentication tags

[https://csrc.nist.gov/csrc/media/projects/block-cipher-
techn...](https://csrc.nist.gov/csrc/media/projects/block-cipher-
techniques/documents/bcm/comments/800-38-series-drafts/gcm/joux_comments.pdf)

------
jopsen
Why is it that most implementation require me to specify the nonce/IV, and why
not include it in the cipher text?

Most implementations could easily call an internal RNG and harvest an IV on my
behalf, preventing me from being stupid. So why not?

Similarly, if the specification said that the IV must be prepended to the
cipher text, then I would never need to specify the IV when decrypting.

(Is it wrong to send the IV in plaintext?)

~~~
regecks
It's interesting that even libsodium's box/secretbox have nonce as a separate
part of its 'easy to use' interface.

I also would like to know why it isn't just an opaque part of the ciphertext.

I'm aware that nonces are not always random but sometimes a counter, which
creates an easy way to track nonce re-use. Is that the only reason?

~~~
jopsen
Also because it's not part of the cipher text I always end up wondering if I
can transmit it in plaintext -- thus, I search stackoverflow for some sketchy
answer that says it can -- because nobody every documents this in a library..

------
AnaniasAnanas
There is also HS1-SIV which uses Chacha20.

------
bondolo
Thank you to the authors for being entirely explicit about the implementation
to the point of providing pseudo code and not having any expectation that
implementors or users will know anything about cryptography.

------
wolf550e
is XChaCha20-Poly1305 better if I don't need the performance of hardware
accelerated AES GCM or am not guaranteed to always run on a device that has
that hardware acceleration (AESNI, CLMUL)?

~~~
FiloSottile
If you trust your CSPRNG and you wanted AES-GCM-SIV just to be allowed to use
random nonces, yeah. If there is any reason you might still repeat a nonce,
XChaCha will break.

~~~
metalliqaz
Presumably you could form a similar IV construction with Poly1305 as your
hash, no?

~~~
CiPHPerCoder
S2V for XChaCha20-Poly1305 has actually been discussed on the CFRG mailing
list (and a little bit off-list between myself and others interested in this
topic). The only question that hasn't been addressed at the time of the last
email was, where does it fit?

XChaCha20 uses HChaCha20 to derive a 256-bit subkey between the 256-bit key
and first 128 bits of the nonce. Then it uses ChaCha20 with the subkey and the
remaining 64 bits of the nonce. ChaCha20 has an internal counter that goes
between 0 and 2^64 - 1.

AEAD_XChaCha20_Poly1305 uses the first 32 bytes of the XChaCha20 keystream to
determine the Poly1305 key for that message, then begins the encryption
starting at the next block. (The remaining 32 bytes of block_counter = 0 are
discarded in XChaCha20, but not in XSalsa20; this is a subtle difference that
probably only makes streaming APIs easier to design and has no significant
security considerations.)

With that in mind: XChaCha20 is already deriving a key from the key and
(extended) nonce. And it already has an internal block counter (which side-
steps counter/nonce wrapping issue that was addressed with AES-CTR in the AES-
GCM-SIV design).

The simplest solution is to, instead of just trusting your CSPRNG, do this:

    
    
      function crypto_aead_xchacha20poly1305siv_encrypt(msg, key) {
        let nonce = Buffer.alloc(24);
        sodium.randombytes_buf(nonce);
        
        // Synthetic nonce here:
        s2v(nonce, msg);
    
        let cipher = Buffer.alloc(msg.length + 16);
        sodium.crypt_aead_xchacha20poly1305_ietf_encrypt(cipher, msg, nonce, key);
        return [nonce, cipher];
      }
    

But this would be, strictly speaking, indistinguishable from
XChaCha20-Poly1305 without SIV.

For context: I authored the XChaCha20 RFC draft, implemented it in pure-PHP
(twice; the second time was to support 32-bit systems).

------
jwilk
HTML version:

[https://tools.ietf.org/html/rfc8452](https://tools.ietf.org/html/rfc8452)

~~~
sctb
Thanks! The RFC markup is so respectful of text I don't feel bad for updating
it from [https://www.rfc-editor.org/rfc/rfc8452.txt](https://www.rfc-
editor.org/rfc/rfc8452.txt).

