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 (C11; getrandom(2) — C stdlib has no CSPRNG; arc4random_buf/SecRandomCopyBytes elsewhere). Port of src/lib/password.ts. */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/random.h>
static const char LOWER[] = "abcdefghijklmnopqrstuvwxyz", UPPER[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const char NUMBERS[] = "0123456789", SYMBOLS[] = "!@#$%^&*()-_=+[]{};:,.<>?/";
static const char AMBIGUOUS[] = "O0Il1|"; /* O/0, I/l/1, pipe — dropped on request */
typedef struct { int length, upper, lower, numbers, symbols, exclude_ambiguous; } PasswordOptions;
/* Concat the selected pools, then drop ambiguous glyphs (mirrors buildCharset). */
static size_t build_charset(const PasswordOptions *o, char *cs)
{
const struct { const char *set; int on; } pools[4] = {
{ LOWER, o->lower }, { UPPER, o->upper },
{ NUMBERS, o->numbers }, { SYMBOLS, o->symbols },
};
size_t n = 0;
for (int p = 0; p < 4; p++)
if (pools[p].on) {
size_t len = strlen(pools[p].set);
memcpy(cs + n, pools[p].set, len);
n += len;
}
if (o->exclude_ambiguous) {
size_t w = 0;
for (size_t i = 0; i < n; i++)
if (!strchr(AMBIGUOUS, cs[i])) cs[w++] = cs[i];
n = w;
}
cs[n] = '\0';
return n;
}
/* Uniform index in [0, n): reject uint32 getrandom draws >= the largest multiple of n fitting in 2^32, so `r % n` carries no modulo bias. */
static unsigned unbiased_index(unsigned n)
{
const unsigned long MAX = 1UL << 32;
unsigned long limit = MAX - MAX % n, r;
do {
if (getrandom(&r, sizeof r, 0) != (long)sizeof r) exit(1);
} while (r >= limit);
return (unsigned)(r % n);
}
/* pw needs o->length + 1 bytes; returns 0 for an empty pool or length < 1 (the TS lib returns "" for both). */
static int generate_password(const PasswordOptions *o, char *pw)
{
char cs[128];
size_t n = build_charset(o, cs);
if (n == 0 || o->length < 1) return 0;
for (int i = 0; i < o->length; i++) pw[i] = cs[unbiased_index((unsigned)n)];
pw[o->length] = '\0';
return 1;
}
/* Theoretical entropy in bits: length * log2(|alphabet|). */
static double entropy_bits(int length, size_t charset_size)
{
return (length <= 0 || charset_size <= 1) ? 0.0 : length * log2((double)charset_size);
}
/* Strength meter tiers, 1:1 with the TS thresholds. */
static const char *strength_tier(double bits)
{
if (bits >= 100) return "very strong";
if (bits >= 70) return "strong";
if (bits >= 45) return "fair";
if (bits >= 28) return "weak";
return "very weak";
}
int main(void)
{
PasswordOptions o = { 20, 1, 1, 1, 1, 1 }; /* 20 chars, all pools, drop ambiguous */
char pw[128];
if (!generate_password(&o, pw)) return 1;
double bits = entropy_bits(20, 83); /* 26+26+10+26 minus O0Il1 (| not in symbols) */
printf("%s — %.1f bits, %s\n", pw, bits, strength_tier(bits));
return 0;
}
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 →