Secure Token Generator — Swift 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 Swift 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. Swift (5.9) 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). UInt32.random uses SystemRandomNumberGenerator — the cryptographically secure generator Swift uses by default.
import Foundation
/// The fixed alphabets (subset).
let alphabets = [
"hex": "0123456789abcdef",
"base32": "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", // RFC 4648
"base64url": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
"base62": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
]
/// Resolve an alphabet name to its symbol string; unknown -> hex (the default).
func resolveAlphabet(_ name: String) -> String {
alphabets[name] ?? alphabets["hex"]!
}
/// Characters needed to carry `bytes` bytes of entropy through `size` symbols.
func outputLength(_ bytes: Double, alphabetSize size: Int) -> Int {
guard bytes >= 1, size >= 2 else { return 0 }
return Int((bytes * 8 / log2(Double(size))).rounded(.up))
}
/// 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. The 64-redraw cap stops a broken RNG from looping
/// forever — same guard as the TS/Python reference.
func selectUnbiased(_ alphabet: String, _ n: Int) -> String {
let symbols = Array(alphabet)
let size = UInt32(symbols.count)
let limit = UInt32.max / size * size
var out = ""
out.reserveCapacity(n)
for _ in 0..<n {
var x = UInt32.random(in: .min ... .max)
var redraws = 0
while x >= limit && redraws < 64 {
x = UInt32.random(in: .min ... .max)
redraws += 1
}
out.append(symbols[Int(x % size)])
}
return out
}
/// Bucket an entropy estimate (bits) into the tool's strength tiers:
/// weak <64 · fair 64-127 · strong 128-255 · very strong >=256.
func strengthLabel(_ bits: Double) -> String {
if bits < 64 { return "weak" }
if bits < 128 { return "fair" }
if bits < 256 { return "strong" }
return "very strong"
}
// Demo: the island's three showcase rows — 16-byte hex, 20-byte base62,
// 32-byte base32 — each labeled with its real strength in bits.
for (name, bytes) in [("hex", 16.0), ("base62", 20.0), ("base32", 32.0)] {
let alphabet = resolveAlphabet(name)
let token = selectUnbiased(alphabet, outputLength(bytes, alphabetSize: alphabet.count))
let bits = Double(token.count) * log2(Double(alphabet.count))
print(String(format: "%-8s %.0f bytes -> %@ (%.0f bits, %@)",
(name as NSString).utf8String!, bytes, token, bits, strengthLabel(bits)))
}
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 →