quicwg / load-balancers

In-progress version of draft-ietf-quic-load-balancers

Home Page:https://quicwg.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Align stream cipher and block cipher formats

huitema opened this issue · comments

The clear text stream cipher and block cipher formats are specified as:

[B][nonce][server-ID][server-use]
[B][server-ID][server-use]

I think that this difference is not necessary. In the block cipher format, the first 16-length_of_sid bytes are effectively used as a nonce: using the same value and the same server ID would result in the same initial 16 bytes, with exactly the same privacy effect as failing to properly initialize the nonce in the stream-cipher case. I wish we could unify these two formats, to:

[B][server-ID][server-use]

With just three parameters:

[B][     server-ID      ][     server-use     ]
   <-- length of SID -->
   <--- scope of encryption --->
<--------------- length of CID --------------->

The scope of encryption would be 0 bytes for the clear text format, 16 bytes for the block cipher format, and a value greater than server-ID length and lower than the length of the CID for the stream cipher format. This will of course require that the first bytes of the server-use field act as a nonce. Alternately, we could have:

[B][     server-ID      ][ nonce ][ server-use  ]
   <-- length of SID -->
   <---- scope of encryption ---->
<---------------- length of CID ---------------->

Which achieves the same unification result, but is maybe a bit more explicit.

I think this would simplify things, yes. Though it might be worth it to separate the server-use bit into a nonce and server-use, since one has uniqueness constraints and one doesn't.

Thinking of that a bit more, it is possible to further simplify. In the case of the stream cipher, the "nonce" part cannot be more than 16 bytes long. This means that the nonce will include:

  • All of the "server-use" bytes if the are fewer than 16 such bytes
  • The initial 16 bytes of the "server use" field if there are more
[B][     server-ID     ][ server-use ]
   <-- length of SID -->
   <------ scope of encryption ------>
<---------- length of CID ----------->

[B][     server-ID     ][ server-use (> 16B) ]
   <-- length of SID --><-- 16 bytes -->
   <------- scope of encryption ------->
<-------------- length of CID --------------->

With that, for all schemes we will require just two parameters, the length of the SID and the length of the CID. This simplifies configuration and APIs.

At that point, the "nonce" requirement is not particularly onerous. There is already an operational requirement that CID as a whole be unique -- conflicting values would lead to packets delivered to the wrong context. If we use "all the bytes" then the server-use field is effectively a nonce. The requirement only applies to the cases where the server use field is larger than 16 bytes. We can mention it, the same way we should mention it for the block cipher.

There is a small technical weakness, because the uniqueness of the CID could also result from the randomness of the first byte. This could be fixed by using the first byte in the encryption passes: use first-byte + server ID when encrypting the nonce if the server ID is fewer than 16 bytes. (Is there really a use case for a 16 bytes server ID? Would 15 bytes be sufficient?)

I like how this is developing.

I should clarify that the "CID length" is actually the minimum length of the CID -- that's all the LB will look at. The server can pad it out to 20B but that's not relevant to the algorithm.

Regarding the first byte: if using length-self-encoding, there will be little or not entropy there.

I don't think the case for a 16B SID is compelling.