Skip to content

Instantly share code, notes, and snippets.

@themighty1
Last active August 25, 2025 12:00
Show Gist options
  • Select an option

  • Save themighty1/8ae1fd5ca8ff8552fc81eaa928a48b74 to your computer and use it in GitHub Desktop.

Select an option

Save themighty1/8ae1fd5ca8ff8552fc81eaa928a48b74 to your computer and use it in GitHub Desktop.
tls 1.3 prf cost
// ------------ TLDR ----------------
Total MPC cost (in sha256 compressions) :
- reduced PRF: 22 (+5 extra round trips)
- full PRF: 32
// How the above numbers were calculated is described below.
// -----------------------TLS 1.3 PRF---------------
//
// Copied from: https://tls13.xargs.org
// Below are the steps of TLS 1.3 PRF with an MPC cost (the number of sha 256 compressions)
// for the reduced PRF variant (the number next to it in () is for the full PRF).
//
// The reduced PRF variant incurs an extra roundtrip between the MPC parties.
// Reminder:
//
// HKDF-Expand-Label(key, label, ctx, len) == HMAC(key, len | "tls13 " | label | ctx)
// HKDF-Extract(salt, IKM) == HMAC(salt, IKM)
//
// Note that even though HKDF-Extract calls its second argument "input
// keying material", in HMAC terminology the first argument is the key
// and the second is the message to authenticate.
// In the above example `salt` becomes the HMAC's key, while `IKM` is
// HMAC's message.
//
// Compress(hash_state, msg) takes as an input the hash state and the msg
// to compress.
early_secret = HKDF-Extract(salt: 00, key: 00...)
empty_hash = SHA256("")
// derived_secret is always deterministic
derived_secret = HKDF-Expand-Label(key: early_secret, label: "derived", ctx: empty_hash, len: 32)
// MPC cost: 2 (2)
//
// (each party computes inner_partial and outer_partial locally)
//
// inner_hash = Compress(inner_partial, shared_secret)
// handshake_secret = Compress(outer_partial, inner_hash)
//
//
// handshake_secret is secret-shared
handshake_secret = HKDF-Extract(salt: derived_secret, key: shared_secret)
// MPC cost: 2 (2)
//
// inner_partial = Compress(INIT_STATE, handshake_secret+ipad)
// outer_partial = Compress(INIT_STATE, handshake_secret+opad)
//
// inner_partial is made public
// outer_partial is secret-shared
// Assuming an AES128-GCM ciphersuite is used (16-byte keys and 12-byte IVs)
// MPC cost: 1 (2)
//
// client_secret = Compress(outer_partial, inner_hash)
//
// client_secret is revealed to prover
client_secret = HKDF-Expand-Label(key: handshake_secret, label: "c hs traffic", ctx: hello_hash, len: 32)
// MPC cost: 1 (2)
//
// server_secret = Compress(outer_partial, inner_hash)
//
// server_secret is revealed to prover
server_secret = HKDF-Expand-Label(key: handshake_secret, label: "s hs traffic", ctx: hello_hash, len: 32)
// Prover computes locally and finishes the handshake
client_handshake_key = HKDF-Expand-Label(key: client_secret, label: "key", ctx: "", len: 16)
server_handshake_key = HKDF-Expand-Label(key: server_secret, label: "key", ctx: "", len: 16)
client_handshake_iv = HKDF-Expand-Label(key: client_secret, label: "iv", ctx: "", len: 12)
server_handshake_iv = HKDF-Expand-Label(key: server_secret, label: "iv", ctx: "", len: 12)
empty_hash = SHA256("")
// MPC cost: 1 (2)
//
// derived_secret = Compress(outer_partial, inner_hash)
//
// derived_secret is secret-shared
derived_secret = HKDF-Expand-Label(key: handshake_secret, label: "derived", ctx: empty_hash, len: 32)
// MPC cost: 3 (4)
//
// inner_partial = Compress(INIT_STATE, derived_secret+ipad)
// outer_partial = Compress(INIT_STATE, derived_secret+opad)
//
// inner_partial is made public
// outer_partial is secret-shared
//
// master_secret = Compress(outer_partial, inner_hash)
//
// master_secret is secret-shared
master_secret = HKDF-Extract(salt: derived_secret, key: 00...)
// MPC cost: 2 (2)
//
// inner_partial = Compress(INIT_STATE, master_secret+ipad)
// outer_partial = Compress(INIT_STATE, master_secret+opad)
//
// inner_partial is made public
// outer_partial is secret-shared
// MPC cost: 1 (2)
// client_secret = Compress(outer_partial, inner_hash)
//
// client_secret is secret-shared
client_secret = HKDF-Expand-Label(key: master_secret, label: "c ap traffic", ctx: handshake_hash, len: 32)
// MPC cost: 1 (2)
// server_secret = Compress(outer_partial, inner_hash)
//
// server_secret is secret-shared
server_secret = HKDF-Expand-Label(key: master_secret, label: "s ap traffic", ctx: handshake_hash, len: 32)
// MPC cost: 2 (2)
//
// inner_partial = Compress(INIT_STATE, client_secret+ipad)
// outer_partial = Compress(INIT_STATE, client_secret+opad)
//
// inner_partial is made public
// outer_partial is secret-shared
// MPC cost: 1 (2)
// client_application_key = Compress(outer_partial, inner_hash)
//
// client_application_key is secret-shared
client_application_key = HKDF-Expand-Label(key: client_secret, label: "key", ctx: "", len: 32)
// MPC cost: 1 (2)
// client_application_iv = Compress(outer_partial, inner_hash)
//
// client_application_iv is secret-shared
client_application_iv = HKDF-Expand-Label(key: client_secret, label: "iv", ctx: "", len: 12)
// MPC cost: 2 (2)
//
// inner_partial = Compress(INIT_STATE, server_secret+ipad)
// outer_partial = Compress(INIT_STATE, server_secret+opad)
//
// inner_partial is made public
// outer_partial is secret-shared
// MPC cost: 1 (2)
// server_application_key = Compress(outer_partial, inner_hash)
//
// server_application_key is secret-shared
server_application_key = HKDF-Expand-Label(key: server_secret, label: "key", ctx: "", len: 32)
// MPC cost: 1 (2)
// server_application_iv = Compress(outer_partial, inner_hash)
//
// server_application_iv is secret-shared
server_application_iv = HKDF-Expand-Label(key: server_secret, label: "iv", ctx: "", len: 12)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment