Browse the docs

silk.tls.hkdf.

The TLS 1.3 key schedule functions HKDF-Expand-Label and Derive-Secret (RFC 8446, section 7.1).

When to use#

Use TlsHkdfSha256 or TlsHkdfSha384 to derive TLS 1.3 secrets, keys, and IVs, or keys for a protocol that reuses the TLS key schedule, such as QUIC. For other uses, use silk.crypto.hkdf.

Details#

TlsHkdfSha256.expandLabel adds the prefix tls13 to the label and fills the output. TlsHkdfSha256.deriveSecret hashes the handshake messages and expands with that hash. TlsHkdfSha256.deriveSecretFromHash takes a transcript hash that you already have. Nothing allocates.

Errors#

  • LabelError if the label is not 1 to 249 bytes, the context is longer than 255 bytes, the output is too long, or the messages are too long. The output does not change.

Gotchas#

Give the label without tls13 , because it is always added. You choose the labels and build the transcript. Secrets are not erased.

Examples#

Derive a secret from messages or from their hash#

silk
import silk.core.result { Result }
import silk.crypto.sha2 { Sha256 }
import silk.tls.hkdf { LabelError, TlsHkdfSha256 }

pub fn main() -> i32 {
  let secret: [u8; 32] = [7; 32]
  let fromMessages = match TlsHkdfSha256.deriveSecret(&secret, b"derived", b"") {
    Result<[u8; 32], LabelError>.Success { value } => value
    Result<[u8; 32], LabelError>.Failure { error: _ } => {
      return 1
    }
  }

  // An empty transcript is the hash of no bytes, not 32 zero bytes.
  let emptyHash = Sha256.hash(b"")
  let fromHash = match TlsHkdfSha256.deriveSecretFromHash(&secret, b"derived", &emptyHash) {
    Result<[u8; 32], LabelError>.Success { value } => value
    Result<[u8; 32], LabelError>.Failure { error: _ } => {
      return 1
    }
  }
  let mut index: usize = 0
  while index < 32 {
    if fromMessages[index] != fromHash[index] {
      return 1
    }
    index = index + 1
  }
  return 0
}

Import as TlsHkdfSha256 with import silk.tls.hkdf { TlsHkdfSha256 }.

Public declarations: 3.

LabelError#

silk
pub union LabelError

A length that the key schedule does not accept. It holds no secret bytes.

LabelLength#

silk
LabelLength

The label is empty or longer than 249 bytes.

Field requested#

silk
pub requested: usize

The requested length in bytes.

Field maximum#

silk
pub maximum: usize

The largest accepted length in bytes.

ContextLength#

silk
ContextLength

The context is longer than 255 bytes.

Field requested#

silk
pub requested: usize

The requested length in bytes.

Field maximum#

silk
pub maximum: usize

The largest accepted length in bytes.

OutputLength#

silk
OutputLength

The output is longer than 255 hash blocks.

Field requested#

silk
pub requested: usize

The requested length in bytes.

Field maximum#

silk
pub maximum: usize

The largest accepted length in bytes.

MessageTooLong#

silk
MessageTooLong

The messages are longer than SHA-256 allows.

Field requested#

silk
pub requested: u64

The requested length in bytes.

Field maximum#

silk
pub maximum: u64

The largest accepted length in bytes.

Implementation Debug for LabelError#

silk
impl Debug for LabelError

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the name of the variant and its fields, such as LabelLength { ... }.

TlsHkdfSha256#

silk
pub struct TlsHkdfSha256

The TLS 1.3 key schedule with SHA-256: HKDF-Expand-Label and Derive-Secret (RFC 8446, section 7.1). Secrets and transcript hashes are 32 bytes.

When to use#

Use it to derive TLS 1.3 secrets, keys, and IVs, or keys for a protocol that reuses the TLS key schedule, such as QUIC. For other uses, use silk.crypto.hkdf.

Details#

expandLabel adds the prefix tls13 to the label and fills the output. deriveSecret hashes the handshake messages and expands with that hash. deriveSecretFromHash takes a transcript hash that you already have. Nothing allocates.

Gotchas#

Give the label without tls13 , because it is always added. You choose the labels and build the transcript. Secrets are not erased.

Implementation TlsHkdfSha256#

silk
impl TlsHkdfSha256

Associated function expandLabel#

silk
pub fn expandLabel(secret: &([u8; 32]), label: &[u8], context: &[u8], output: &mut [u8]) -> Result<
    (),
    LabelError,
  >

Fills output with HKDF-Expand-Label(secret, label, context, output.length).

The prefix tls13 is added to label. All lengths are checked before the first write.

Errors#

  • LabelLength if label is not 1 to 249 bytes.

  • ContextLength if context is longer than 255 bytes.

  • OutputLength if output is longer than 8160 bytes.

Associated function deriveSecret#

silk
pub fn deriveSecret(secret: &([u8; 32]), label: &[u8], messages: &[u8]) -> Result<
    [u8; 32],
    LabelError,
  >

Returns Derive-Secret(secret, label, messages): the 32-byte expansion with the SHA-256 hash of messages as the context.

Give the handshake messages as they are on the wire, in order.

Errors#

  • LabelLength if label is not 1 to 249 bytes.

  • MessageTooLong if messages is too long.

Gotchas#

If you already have the transcript hash, use TlsHkdfSha256.deriveSecretFromHash. This function hashes its input again.

Associated function deriveSecretFromHash#

silk
pub fn deriveSecretFromHash(secret: &([u8; 32]), label: &[u8], transcriptHash: &([u8; 32])) -> Result<
    [u8; 32],
    LabelError,
  >

Returns Derive-Secret with a SHA-256 transcript hash that you already computed.

Errors#

  • LabelLength if label is not 1 to 249 bytes.

Gotchas#

For an empty transcript, give the hash of no bytes. A hash of all zeros gives a different secret.

TlsHkdfSha384#

silk
pub struct TlsHkdfSha384

The TLS 1.3 key schedule with SHA-384: HKDF-Expand-Label and Derive-Secret (RFC 8446, section 7.1). Secrets and transcript hashes are 48 bytes.

When to use#

Use it to derive TLS 1.3 secrets, keys, and IVs, or keys for a protocol that reuses the TLS key schedule, such as QUIC. For other uses, use silk.crypto.hkdf.

Details#

expandLabel adds the prefix tls13 to the label and fills the output. deriveSecret hashes the handshake messages and expands with that hash. deriveSecretFromHash takes a transcript hash that you already have. Nothing allocates.

Gotchas#

Give the label without tls13 , because it is always added. You choose the labels and build the transcript. Secrets are not erased.

Implementation TlsHkdfSha384#

silk
impl TlsHkdfSha384

Associated function expandLabel#

silk
pub fn expandLabel(secret: &([u8; 48]), label: &[u8], context: &[u8], output: &mut [u8]) -> Result<
    (),
    LabelError,
  >

Fills output with HKDF-Expand-Label(secret, label, context, output.length).

The prefix tls13 is added to label. All lengths are checked before the first write.

Errors#

  • LabelLength if label is not 1 to 249 bytes.

  • ContextLength if context is longer than 255 bytes.

  • OutputLength if output is longer than 12240 bytes.

Associated function deriveSecret#

silk
pub fn deriveSecret(secret: &([u8; 48]), label: &[u8], messages: &[u8]) -> Result<
    [u8; 48],
    LabelError,
  >

Returns Derive-Secret(secret, label, messages): the 48-byte expansion with the SHA-384 hash of messages as the context.

Give the handshake messages as they are on the wire, in order.

Errors#

  • LabelLength if label is not 1 to 249 bytes.

  • MessageTooLong if messages is too long.

Gotchas#

If you already have the transcript hash, use TlsHkdfSha384.deriveSecretFromHash. This function hashes its input again.

Associated function deriveSecretFromHash#

silk
pub fn deriveSecretFromHash(secret: &([u8; 48]), label: &[u8], transcriptHash: &([u8; 48])) -> Result<
    [u8; 48],
    LabelError,
  >

Returns Derive-Secret with a SHA-384 transcript hash that you already computed.

Errors#

  • LabelLength if label is not 1 to 249 bytes.

Gotchas#

For an empty transcript, give the hash of no bytes. A hash of all zeros gives a different secret.

Category: TLS and certificates.

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.

View the source of this page