Silk

silk/random

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

Provider-replaceable cryptographically secure random bytes and derived values.

When to use

Require Random for secrets, credentials, cryptographic keys, nonces, tokens, randomized protocols, or any value that must remain unpredictable. Supply an explicit production CSPRNG at the application boundary and a scripted provider only in deterministic tests.

Details

The service primitive exactly fills borrowed storage. nextU64, nextBool, and below have stable source-defined byte consumption and do not select a concrete provider.

Gotchas

A provider claiming this service must return fresh unpredictable bytes and must treat failure as fatal. An environment without such a source must omit the capability, never substitute deterministic data. Random.fillBytes performs no provider call for empty storage.

Examples

Test word decoding with scripted bytes

import silk.effect {Effect}

import silk.random {Random}

import silk.usize

// A deterministic test double; never supply it for secrets or credentials.
struct Scripted {
  filled: usize
}

impl Random for Scripted {
  effect fn fillBytes(self: &mut Self, output: &mut [u8]) -> () {
    let mut index = usize.ZERO
    while index < output.length {
      output[index] = 0
      index = index + 1
    }
    if output.length > 0 {
      output[0] = 42
    }
    self.filled = self.filled + output.length
    return ()
  }
}

pub fn main() -> i32 {
  let mut provider = Scripted {filled: usize.ZERO}
  let word = run Random.nextU64()
    |> Effect.provideMut<Random>(&mut provider)
  if word == 42 && provider.filled == 8 {
    return 42
  }
  return 0
}

Import as Random with import silk.random { Random }.

Public declarations: 1.

Random

pub service Random

An exclusive source of fresh cryptographically secure random bytes.

Details

Providers must fill every requested byte, must not advance for an empty slice, and must never return weak or partial data after failure.

Operation fillBytes

effect<'life0> fn fillBytes<'life0>(output: &'life0 mut [u8]) -> () ? &mut Random

Fills the complete exclusive byte slice with fresh unpredictable data.

Associated function Random.nextU64

pub effect<'static> fn nextU64() -> u64 ? &mut Random

Returns one secure u64 decoded least-significant byte first from exactly eight provider bytes.

Associated function Random.nextBool

pub effect<'static> fn nextBool() -> bool ? &mut Random

Returns whether bit 63 of one secure provider word is set.

Associated function Random.below

pub effect<'static> fn below(upperExclusive: u64) -> silk/option.Option<u64> ? &mut Random

Returns an unbiased secure value below upperExclusive, or None for zero.

Details

A zero bound consumes no provider bytes. Positive bounds use complete-word rejection sampling.

On this page