Password Generator — C# 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 C# implementation — the same logic the interactive tool runs, in a shareable, citable form.
// password-generator — CSPRNG password generation + entropy scoring. Language: C# (.NET 6+; System.Security.Cryptography CSPRNG). Port of src/lib/password.ts.
using System;
using System.Security.Cryptography;
using System.Text;
var o = new PasswordOptions(Length: 20, Upper: true, Lower: true,
Numbers: true, Symbols: true, ExcludeAmbiguous: true);
var cs = Password.BuildCharset(o);
var bits = Password.EntropyBits(o.Length, cs.Length);
Console.WriteLine($"{Password.Generate(o)} — {bits:F1} bits, {Password.StrengthTier(bits)}");
record PasswordOptions(int Length, bool Upper = false, bool Lower = false,
bool Numbers = false, bool Symbols = false, bool ExcludeAmbiguous = false);
static class Password
{
const string Lower = "abcdefghijklmnopqrstuvwxyz";
const string Upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string Numbers = "0123456789";
const string Symbols = "!@#$%^&*()-_=+[]{};:,.<>?/";
const string Ambiguous = "O0Il1|"; // O/0, I/l/1, pipe — dropped on request
// Concat the selected pools, then drop ambiguous glyphs (mirrors buildCharset).
public static string BuildCharset(PasswordOptions o)
{
var cs = new StringBuilder();
if (o.Lower) cs.Append(Lower);
if (o.Upper) cs.Append(Upper);
if (o.Numbers) cs.Append(Numbers);
if (o.Symbols) cs.Append(Symbols);
if (o.ExcludeAmbiguous)
for (int i = cs.Length - 1; i >= 0; i--)
if (Ambiguous.IndexOf(cs[i]) >= 0) cs.Remove(i, 1);
return cs.ToString();
}
// Uniform index in [0, n): reject uint32 CSPRNG draws >= the largest
// multiple of n fitting in 2^32, so `% n` carries no modulo bias.
static uint UnbiasedIndex(uint n)
{
const ulong Max = 1UL << 32;
ulong limit = Max - Max % n, r;
Span<byte> b = stackalloc byte[4];
do
{
RandomNumberGenerator.Fill(b);
r = BitConverter.ToUInt32(b);
} while (r >= limit);
return (uint)(r % n);
}
// Returns "" for an empty pool or length < 1 — same contract as the TS lib.
public static string Generate(PasswordOptions o)
{
var cs = BuildCharset(o);
if (cs.Length == 0 || o.Length < 1) return "";
var pw = new char[o.Length];
for (int i = 0; i < o.Length; i++) pw[i] = cs[(int)UnbiasedIndex((uint)cs.Length)];
return new string(pw);
}
// Theoretical entropy in bits: length * log2(|alphabet|).
public static double EntropyBits(int length, int charsetSize) =>
length <= 0 || charsetSize <= 1 ? 0.0 : length * Math.Log2(charsetSize);
// Strength meter tiers, 1:1 with the TS thresholds.
public static string StrengthTier(double bits) =>
bits >= 100 ? "very strong"
: bits >= 70 ? "strong"
: bits >= 45 ? "fair"
: bits >= 28 ? "weak"
: "very weak";
}
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 →