Browse the docs

silk.crypto.hkdf.

Derive keys with HKDF (RFC 5869) over SHA-256 or SHA-384.

When to use#

Use HkdfSha256 or HkdfSha384 to turn a shared secret, such as the result of an X25519 key exchange, into one or more keys of the length that you need. Give each key a different info label so that the keys are independent.

Details#

HKDF has two steps. extract mixes the input key material with a salt and returns a pseudorandom key (PRK) of one digest length. expand turns the PRK and an info label into output of any length up to 255 digests: 8160 bytes for SHA-256, 12240 bytes for SHA-384. Nothing allocates.

Errors#

  • OutputTooLongError from expand if the output is longer than the maximum. The output does not change.

Gotchas#

HKDF is not for passwords. A password needs a slow function such as Argon2 or scrypt. The PRK is a secret and is not erased.

Examples#

Derive two keys from one secret#

silk
import silk.crypto.hkdf { HkdfSha256, OutputTooLongError }
import silk.core.result { Result }

pub fn main() -> i32 {
  let prk = HkdfSha256.extract(b"salt", b"shared secret")
  let mut encryption: [u8; 32] = [0; 32]
  let mut authentication: [u8; 32] = [0; 32]
  match HkdfSha256.expand(&prk, b"app v1 encryption", &mut encryption) {
    Result<(), OutputTooLongError>.Success { value: _ } => {}
    Result<(), OutputTooLongError>.Failure { error: _ } => {
      return 1
    }
  }
  match HkdfSha256.expand(&prk, b"app v1 authentication", &mut authentication) {
    Result<(), OutputTooLongError>.Success { value: _ } => {}
    Result<(), OutputTooLongError>.Failure { error: _ } => {
      return 1
    }
  }

  // Different labels give different keys.
  if encryption[0] == authentication[0] && encryption[1] == authentication[1] {
    return 1
  }
  return 0
}

Import as HkdfSha256 with import silk.crypto.hkdf { HkdfSha256 }.

Public declarations: 3.

OutputTooLongError#

silk
pub struct OutputTooLongError

The error that expand returns when the output is longer than 255 digests.

Field requested#

silk
pub requested: usize

The output length that you asked for.

Field maximum#

silk
pub maximum: usize

The maximum output length: 8160 for SHA-256 and 12240 for SHA-384.

Implementation Debug for OutputTooLongError#

silk
impl Debug for OutputTooLongError

Operation debug#

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

Writes the fields, as OutputTooLongError { requested: ..., maximum: ... }.

HkdfSha256#

silk
pub struct HkdfSha256

HKDF with SHA-256 as the hash (RFC 5869). The PRK is 32 bytes and the output is at most 8160 bytes.

When to use#

Use it to turn a shared secret, such as the result of an X25519 key exchange, into one or more keys of the length that you need. Give each key a different info label so that the keys are independent.

Details#

HKDF has two steps. extract mixes the input key material with a salt and returns a pseudorandom key (PRK). expand turns the PRK and an info label into output of any length up to 8160 bytes. Nothing allocates.

Gotchas#

HKDF is not for passwords. A password needs a slow function such as Argon2 or scrypt. The PRK is a secret and is not erased.

Implementation HkdfSha256#

silk
impl HkdfSha256

Associated function extract#

silk
pub fn extract(salt: &[u8], ikm: &[u8]) -> [u8; 32]

Returns the 32-byte pseudorandom key (PRK) for the input key material ikm and salt.

An empty salt is the same as 32 zero bytes. Use a random salt if the protocol has one. Pass the result to HkdfSha256.expand.

Gotchas#

The program traps if salt or ikm is longer than the hash allows (2^64 bits).

Associated function expand#

silk
pub fn expand(prk: &([u8; 32]), info: &[u8], output: &mut [u8]) -> Result<(), OutputTooLongError>

Fills all of output with key material from prk and the label info.

prk must come from HkdfSha256.extract, or be another uniformly random key of 32 bytes. An empty info and an empty output are valid. The same prk and info always give the same bytes, and a shorter output is a prefix of a longer one.

Errors#

HkdfSha384#

silk
pub struct HkdfSha384

HKDF with SHA-384 as the hash (RFC 5869). The PRK is 48 bytes and the output is at most 12240 bytes.

When to use#

Use it to turn a shared secret, such as the result of an X25519 key exchange, into one or more keys of the length that you need. Give each key a different info label so that the keys are independent.

Details#

HKDF has two steps. extract mixes the input key material with a salt and returns a pseudorandom key (PRK). expand turns the PRK and an info label into output of any length up to 12240 bytes. Nothing allocates.

Gotchas#

HKDF is not for passwords. A password needs a slow function such as Argon2 or scrypt. The PRK is a secret and is not erased.

Implementation HkdfSha384#

silk
impl HkdfSha384

Associated function extract#

silk
pub fn extract(salt: &[u8], ikm: &[u8]) -> [u8; 48]

Returns the 48-byte pseudorandom key (PRK) for the input key material ikm and salt.

An empty salt is the same as 48 zero bytes. Use a random salt if the protocol has one. Pass the result to HkdfSha384.expand.

Gotchas#

The program traps if salt or ikm is longer than the hash allows (2^128 bits).

Associated function expand#

silk
pub fn expand(prk: &([u8; 48]), info: &[u8], output: &mut [u8]) -> Result<(), OutputTooLongError>

Fills all of output with key material from prk and the label info.

prk must come from HkdfSha384.extract, or be another uniformly random key of 48 bytes. An empty info and an empty output are valid. The same prk and info always give the same bytes, and a shorter output is a prefix of a longer one.

Errors#

Category: Cryptography.

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