Skip to content

Secure Token Generator — Ruby source

Generate cryptographically-secure random tokens in your browser. Pick the entropy size and format - hex, base32, base64, base62, or alphanumeric - and see the real strength in bits. Runs entirely client-side.

This is the Ruby implementation — the same logic the interactive tool runs, in a shareable, citable form.

# token-generator — cryptographically-secure random tokens in hex/base32/base64/base62/... alphabets, with unbiased symbol selection and entropy/strength estimates. Ruby (3.x) port of src/lib/token-generator.ts — same logic as this dir's javascript.js; the full 8-entry alphabet table, custom alphabets and injectable RNG omitted for the 80-line budget (see javascript.js / python.py).
require 'securerandom'

ALPHABETS = {
  'hex'       => '0123456789abcdef',
  'base32'    => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',                    # RFC 4648
  'base64url' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' \
                 'abcdefghijklmnopqrstuvwxyz0123456789-_',
  'base62'    => '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
}.freeze

# Resolve an alphabet name to its symbol string; unknown -> hex (the default).
def resolve_alphabet(name)
  ALPHABETS.fetch(name, ALPHABETS['hex'])
end

# Characters needed to carry `bytes` bytes of entropy through `size` symbols.
def output_length(bytes, size)
  return 0 if bytes < 1 || size < 2

  (bytes * 8 / Math.log2(size)).ceil
end

# Pick alphabet[n] WITHOUT modulo bias: naive draw % size favors trailing
# symbols whenever size does not divide the draw range (base62 etc.), so any
# draw at or above the largest multiple of size fitting in 32 bits is
# rejected and redrawn. SecureRandom.random_number(1 << 32) draws a uniform
# integer in [0, 2^32) from the OS CSPRNG.
def select_unbiased(alphabet, n)
  size = alphabet.length
  limit = 0xFFFFFFFF / size * size
  Array.new(n) do
    x = SecureRandom.random_number(1 << 32)
    x = SecureRandom.random_number(1 << 32) while x >= limit
    alphabet[x % size]
  end.join
end

# Generate a token carrying `bytes` bytes of entropy through `alpha_name`.
def generate_token(bytes, alpha_name)
  alphabet = resolve_alphabet(alpha_name)
  return '' if alphabet.length < 2

  select_unbiased(alphabet, output_length(bytes, alphabet.length))
end

# Bucket an entropy estimate (bits) into the tool's strength tiers:
# weak <64 · fair 64-127 · strong 128-255 · very strong >=256.
def strength_label(bits)
  return 'weak' if bits < 64
  return 'fair' if bits < 128
  return 'strong' if bits < 256

  'very strong'
end

# Demo: the island's three showcase rows — 16-byte hex, 20-byte base62,
# 32-byte base32 — each labeled with its real strength in bits.
[['hex', 16], ['base62', 20], ['base32', 32]].each do |name, bytes|
  token = generate_token(bytes, name)
  bits = token.length * Math.log2(resolve_alphabet(name).length)
  puts format('%-8s %2d bytes -> %s  (%.0f bits, %s)', name, bytes, token, bits, strength_label(bits))
end

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →