QUIC:修订间差异

来自WHY42
Riguz留言 | 贡献
Riguz留言 | 贡献
第62行: 第62行:
* HKDF-Extract - given a salt and some bytes of key material create 256 bits (32 bytes) of new key material, with the input key material's entropy evenly distributed in the output.
* HKDF-Extract - given a salt and some bytes of key material create 256 bits (32 bytes) of new key material, with the input key material's entropy evenly distributed in the output.
* HKDF-Expand-Label - given the inputs of key material, label, and context data, create a new key of the requested length.
* HKDF-Expand-Label - given the inputs of key material, label, and context data, create a new key of the requested length.
<syntaxhighlight lang="bash">
$ init_salt=38762cf7f55934b34d179ae6a4c80cadccbb7f0a
$ init_dcid=0001020304050607
$ init_secret=$(./hkdf extract $init_salt $init_dcid)
$ csecret=$(./hkdf expandlabel $init_secret "client in" "" 32)
$ ssecret=$(./hkdf expandlabel $init_secret "server in" "" 32)
$ client_init_key=$(./hkdf expandlabel $csecret "quic key" "" 16)
$ server_init_key=$(./hkdf expandlabel $ssecret "quic key" "" 16)
$ client_init_iv=$(./hkdf expandlabel $csecret "quic iv" "" 12)
$ server_init_iv=$(./hkdf expandlabel $ssecret "quic iv" "" 12)
$ client_init_hp=$(./hkdf expandlabel $csecret "quic hp" "" 16)
$ server_init_hp=$(./hkdf expandlabel $ssecret "quic hp" "" 16)
$ echo ckey: $client_init_key
$ echo civ: $client_init_iv
$ echo chp: $client_init_hp
$ echo skey: $server_init_key
$ echo siv: $server_init_iv
$ echo shp: $server_init_hp
ckey: b14b918124fda5c8d79847602fa3520b
civ: ddbc15dea80925a55686a7df
chp: 6df4e9d737cdf714711d7c617ee82981
skey: d77fc4056fcfa32bd1302469ee6ebf90
siv: fcb748e37ff79860faa07477
shp: 440b2725e91dc79b370711ef792faa3d
</syntaxhighlight>
From this we get the following encryption keys and IVs:
<syntaxhighlight lang="bash">
client initial key: b14b918124fda5c8d79847602fa3520b
client initial IV: ddbc15dea80925a55686a7df
server initial key: d77fc4056fcfa32bd1302469ee6ebf90
server initial IV: fcb748e37ff79860faa07477
</syntaxhighlight>
We also get the following "header protection keys", which will be explained below:
client initial header protection key: 6df4e9d737cdf714711d7c617ee82981
server initial header protection key: 440b2725e91dc79b370711ef792faa3d
At this point there is still no data sent over the network.


Ref:
Ref:

2024年1月29日 (一) 20:09的版本

QUIC is a new multiplexed transport built on top of UDP. HTTP/3 is designed to take advantage of QUIC's features, including lack of Head-Of-Line blocking between streams.


The QUIC project started as an alternative to TCP+TLS+HTTP/2, with the goal of improving user experience, particularly page load times. The QUIC working group at the IETF defined a clear boundary between the transport(QUIC) and application(HTTP/3) layers, as well as migrating from QUIC Crypto to TLS 1.3.

Because TCP is implemented in operating system kernels and middleboxes, widely deploying significant changes to TCP is next to impossible. However, since QUIC is built on top of UDP and the transport functionality is encrypted, it suffers from no such limitations.

Key features of QUIC and HTTP/3 over TCP+TLS and HTTP/2 include[1]

  • Reduced connection establishment time - 0 round trips in the common case
  • Improved congestion control feedback
  • Multiplexing without head of line blocking
  • Connection migration
  • Transport extensibility
  • Optional unreliable delivery

Algorithm

Client key change generation

The connection begins with the client generating a private/public keypair for key exchange. Key exchange is a technique where two parties can agree on the same number without an eavesdropper being able to tell what the number is.

The private key is chosen by selecting an integer between 0 and 2^256-1. The client does this by generating 32 bytes (256 bits) of random data. The private key selected is[2]:

202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f

The public key calculated is:

358072d6365880d1aeea329adf9121383851ed21a28e3b75e965d0d2cd166254

Client initialial key calculation

Next, the client continues to prepare for the connection by generating the encryption keys for the Initial packets. Because key exchange between client and server has not taken place there is limited security in these keys - any observer can derive the keys and read the traffic like the server will. Encrypting the Initial packets prevents certain kinds of attacks such as request forgery attacks.

The client begins by generating 8 bytes of random data, in this case the bytes:

0001020304050607

The client then derives encryption keys using the following process:

initial_salt = 38762cf7f55934b34d179ae6a4c80cadccbb7f0a
initial_random = (random bytes from client given above)
initial_secret = HKDF-Extract(salt: initial_salt, key: initial_random)
client_secret = HKDF-Expand-Label(key: initial_secret, label: "client in", ctx: "", len: 32)
server_secret = HKDF-Expand-Label(key: initial_secret, label: "server in", ctx: "", len: 32)
client_key = HKDF-Expand-Label(key: client_secret, label: "quic key", ctx: "", len: 16)
server_key = HKDF-Expand-Label(key: server_secret, label: "quic key", ctx: "", len: 16)
client_iv = HKDF-Expand-Label(key: client_secret, label: "quic iv", ctx: "", len: 12)
server_iv = HKDF-Expand-Label(key: server_secret, label: "quic iv", ctx: "", len: 12)
client_hp_key = HKDF-Expand-Label(key: client_secret, label: "quic hp", ctx: "", len: 16)
server_hp_key = HKDF-Expand-Label(key: server_secret, label: "quic hp", ctx: "", len: 16)

The use of the magic constant "38762cf7f55934b34d179ae6a4c80cadccbb7f0a" as the initial salt is interesting, as it is not derived from mathematical constants or cryptographic principles. It's the value of the first SHA-1 collision, co-discovered by Google researchers (QUIC itself was initially created, sponsored, and deployed by Google).

This has introduced two new cryptographic concepts from TLS 1.3:

  • HKDF-Extract - given a salt and some bytes of key material create 256 bits (32 bytes) of new key material, with the input key material's entropy evenly distributed in the output.
  • HKDF-Expand-Label - given the inputs of key material, label, and context data, create a new key of the requested length.
$ init_salt=38762cf7f55934b34d179ae6a4c80cadccbb7f0a
$ init_dcid=0001020304050607
$ init_secret=$(./hkdf extract $init_salt $init_dcid)
$ csecret=$(./hkdf expandlabel $init_secret "client in" "" 32)
$ ssecret=$(./hkdf expandlabel $init_secret "server in" "" 32)
$ client_init_key=$(./hkdf expandlabel $csecret "quic key" "" 16)
$ server_init_key=$(./hkdf expandlabel $ssecret "quic key" "" 16)
$ client_init_iv=$(./hkdf expandlabel $csecret "quic iv" "" 12)
$ server_init_iv=$(./hkdf expandlabel $ssecret "quic iv" "" 12)
$ client_init_hp=$(./hkdf expandlabel $csecret "quic hp" "" 16)
$ server_init_hp=$(./hkdf expandlabel $ssecret "quic hp" "" 16)
$ echo ckey: $client_init_key
$ echo civ: $client_init_iv
$ echo chp: $client_init_hp
$ echo skey: $server_init_key
$ echo siv: $server_init_iv
$ echo shp: $server_init_hp

ckey: b14b918124fda5c8d79847602fa3520b
civ: ddbc15dea80925a55686a7df
chp: 6df4e9d737cdf714711d7c617ee82981
skey: d77fc4056fcfa32bd1302469ee6ebf90
siv: fcb748e37ff79860faa07477
shp: 440b2725e91dc79b370711ef792faa3d

From this we get the following encryption keys and IVs:

client initial key: b14b918124fda5c8d79847602fa3520b
client initial IV: ddbc15dea80925a55686a7df
server initial key: d77fc4056fcfa32bd1302469ee6ebf90
server initial IV: fcb748e37ff79860faa07477

We also get the following "header protection keys", which will be explained below: client initial header protection key: 6df4e9d737cdf714711d7c617ee82981 server initial header protection key: 440b2725e91dc79b370711ef792faa3d At this point there is still no data sent over the network.

Ref: