Browse the docs

silk.system.random.

The Random effect: random bytes that are safe for secrets.

When to use#

Require &mut Random for anything that an attacker must not guess: keys, nonces, tokens, passwords, and session IDs. The program provides a cryptographically secure random number generator. For simulations, games, and tests that must repeat, use silk.system.insecure_random.

Details#

A provider implements one operation, Random.fillBytes, that fills a slice. Random.nextU64, Random.nextBool, and Random.below use it. The number of bytes that each one reads is fixed, so a test provider gives the same results each time.

Gotchas#

A provider must return fresh, unpredictable bytes. If it cannot, it must stop the program. It must never return weak or predictable data instead. A test provider like the one below is only for tests.

Examples#

Test code that uses random words with a fixed provider#

silk
import silk.core.effect { Effect }
import silk.system.random { Random }

// A test provider. Never use it for secrets.
struct Scripted {
  filled: usize,
}

impl Random for Scripted {
  effect fn fillBytes(self: &mut Self, output: &mut [u8]) -> () {
    let mut index: usize = 0
    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: 0 }
  let word = run Random.nextU64() |> Effect.provideMut<Random>(&mut provider)
  if word != 42 || provider.filled != 8 {
    return 1
  }
  return 0
}

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

Public declarations: 1.

Random#

silk
pub service Random

The effect for random bytes that are safe for secrets.

When to use#

Require &mut Random for anything that an attacker must not guess: keys, nonces, tokens, passwords, and session IDs. For simulations, games, and tests that must repeat, use silk.system.insecure_random.

Details#

A provider implements Random.fillBytes. Random.nextU64, Random.nextBool, and Random.below use it, and the number of bytes that each one reads is fixed, so a test provider gives the same results each time. /// A provider fills each requested byte. For an empty slice, it does nothing and does not use randomness. If it cannot get random bytes, it must stop the program.

Operation fillBytes#

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

Fills all of output with fresh random bytes.

Implementation Random#

silk
impl Random

Associated function nextU64#

silk
pub effect fn nextU64() -> u64 ? &mut Random

Returns a random u64. It reads 8 bytes and uses the first byte as the least significant byte.

Associated function nextBool#

silk
pub effect fn nextBool() -> bool ? &mut Random

Returns a random bool. It reads one u64 and returns true if its highest bit is set.

Associated function below#

silk
pub effect fn below(upperExclusive: u64) -> Option<u64> ? &mut Random

Returns a random value from 0 to upperExclusive - 1, with the same chance for each value. Returns an absent option if upperExclusive is 0.

Details#

It reads u64 values and drops values that would make some results more likely than others, so it can read more than one u64. For 0, it reads nothing.

Category: System.

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