Password Generator — Swift source
Generate cryptographically-random passwords with a CSPRNG using rejection sampling (no modulo bias). Shows live entropy in bits, a 5-tier strength meter, average offline-GPU crack time, and a Pro mode with the entropy formula, a crack-time-vs-length curve, and a 4-scenario attack table. Everything runs locally - nothing is sent anywhere.
This is the Swift implementation — the same logic the interactive tool runs, in a shareable, citable form.
// password-generator — CSPRNG password generation + entropy scoring. Language: Swift 5 (SystemRandomNumberGenerator — backed by the OS CSPRNG). Port of src/lib/password.ts.
import Foundation
struct PasswordOptions {
var length: Int
var upper = false, lower = false, numbers = false, symbols = false
var excludeAmbiguous = false
}
let lower = "abcdefghijklmnopqrstuvwxyz"
let upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
let numbers = "0123456789"
let symbols = "!@#$%^&*()-_=+[]{};:,.<>?/"
let ambiguous = Set("O0Il1|") // O/0, I/l/1, pipe — dropped on request
enum PasswordGenerator {
private static var rng = SystemRandomNumberGenerator()
// Concat the selected pools, then drop ambiguous glyphs (mirrors buildCharset).
static func buildCharset(_ o: PasswordOptions) -> String {
var cs = ""
if o.lower { cs += lower }
if o.upper { cs += upper }
if o.numbers { cs += numbers }
if o.symbols { cs += symbols }
if o.excludeAmbiguous { cs.removeAll(where: { ambiguous.contains($0) }) }
return cs
}
// Uniform index in [0, n): reject uint32 system-CSPRNG draws >= the largest
// multiple of n fitting in 2^32, so `% n` carries no modulo bias.
static func unbiasedIndex(_ n: Int) -> Int {
let max = 1 << 32
let limit = UInt64(max - max % n)
while true {
let r = UInt32(truncatingIfNeeded: rng.next())
if UInt64(r) < limit { return Int(r) % n }
}
}
// Returns "" for an empty pool or length < 1 — same contract as the TS lib.
static func generate(_ o: PasswordOptions) -> String {
let cs = buildCharset(o)
guard !cs.isEmpty, o.length >= 1 else { return "" }
return String((0..<o.length).map { _ in
cs[cs.index(cs.startIndex, offsetBy: unbiasedIndex(cs.count))]
})
}
// Theoretical entropy in bits: length * log2(|alphabet|).
static func entropyBits(_ length: Int, _ charsetSize: Int) -> Double {
guard length > 0, charsetSize > 1 else { return 0.0 }
return Double(length) * log2(Double(charsetSize))
}
// Strength meter tiers, 1:1 with the TS thresholds.
static func strengthTier(_ bits: Double) -> String {
switch bits {
case 100...: return "very strong"
case 70...: return "strong"
case 45...: return "fair"
case 28...: return "weak"
default: return "very weak"
}
}
// Average crack time (s) = 2^(bits-1) / guesses-per-second.
static func crackTimeSeconds(_ bits: Double, _ guessesPerSecond: Double) -> Double {
pow(2, bits - 1) / guessesPerSecond
}
}
let o = PasswordOptions(length: 20, upper: true, lower: true,
numbers: true, symbols: true, excludeAmbiguous: true)
let cs = PasswordGenerator.buildCharset(o)
let bits = PasswordGenerator.entropyBits(o.length, cs.count)
print("\(PasswordGenerator.generate(o)) — \(String(format: "%.1f", bits)) bits, \(PasswordGenerator.strengthTier(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 →