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#
LabelErrorif 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#
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#
pub union LabelErrorA length that the key schedule does not accept. It holds no secret bytes.
LabelLength#
LabelLengthThe label is empty or longer than 249 bytes.
Field requested#
pub requested: usizeThe requested length in bytes.
Field maximum#
pub maximum: usizeThe largest accepted length in bytes.
ContextLength#
ContextLengthThe context is longer than 255 bytes.
Field requested#
pub requested: usizeThe requested length in bytes.
Field maximum#
pub maximum: usizeThe largest accepted length in bytes.
OutputLength#
OutputLengthThe output is longer than 255 hash blocks.
Field requested#
pub requested: usizeThe requested length in bytes.
Field maximum#
pub maximum: usizeThe largest accepted length in bytes.
MessageTooLong#
MessageTooLongThe messages are longer than SHA-256 allows.
Field requested#
pub requested: u64The requested length in bytes.
Field maximum#
pub maximum: u64The largest accepted length in bytes.
Implementation Debug for LabelError#
impl Debug for LabelErrorOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut WriterWrites the name of the variant and its fields, such as LabelLength { ... }.
TlsHkdfSha256#
pub struct TlsHkdfSha256The 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#
impl TlsHkdfSha256Associated function expandLabel#
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#
LabelLengthiflabelis not 1 to 249 bytes.ContextLengthifcontextis longer than 255 bytes.OutputLengthifoutputis longer than 8160 bytes.
Associated function deriveSecret#
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#
LabelLengthiflabelis not 1 to 249 bytes.MessageTooLongifmessagesis too long.
Gotchas#
If you already have the transcript hash, use TlsHkdfSha256.deriveSecretFromHash. This
function hashes its input again.
Associated function deriveSecretFromHash#
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#
LabelLengthiflabelis 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#
pub struct TlsHkdfSha384The 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#
impl TlsHkdfSha384Associated function expandLabel#
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#
LabelLengthiflabelis not 1 to 249 bytes.ContextLengthifcontextis longer than 255 bytes.OutputLengthifoutputis longer than 12240 bytes.
Associated function deriveSecret#
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#
LabelLengthiflabelis not 1 to 249 bytes.MessageTooLongifmessagesis too long.
Gotchas#
If you already have the transcript hash, use TlsHkdfSha384.deriveSecretFromHash. This
function hashes its input again.
Associated function deriveSecretFromHash#
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#
LabelLengthiflabelis 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.