Skip to content

Privacy Score — C source

One number for your privacy health: your browser fingerprint, a test password's strength and breach exposure, and a site's security headers — four checks, one score, concrete fixes. Runs in your browser; only a 5-character hash prefix ever leaves it.

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

/*
 * privacy-score — composite privacy scoring engine.
 *
 * Language: C (C11, standard library only)
 * Source:   CosmoDev polyglot showcase port of the Privacy Score tool,
 *           ported from src/lib/privacy-score.ts (canonical TypeScript).
 * License:  display source — part of CosmoDev's polyglot tool pages.
 *
 * Four category checks, each scored out of 25; the overall percent is
 * renormalized over the categories that actually ran — skipping a check
 * never lowers your score. Letter bands: >=85 A, >=70 B, >=50 C, else D.
 */

#include <stdio.h>

/* Round half away from zero and pin into the 0..25 window. */
static int clamp25(double points)
{
    int r = (int)(points + (points >= 0 ? 0.5 : -0.5));
    return r < 0 ? 0 : (r > 25 ? 25 : r);
}

/* More distinguishable signals make a browser more unique: high-risk signals
 * cost 4 each, medium 1.5, and a large surface costs a little more. */
static int fingerprint_points(int signal_count, int high_risk, int medium_risk)
{
    double surface = (signal_count > 12 ? signal_count - 12 : 0) * 0.5;
    return clamp25(25.0 - high_risk * 4.0 - medium_risk * 1.5 - surface);
}

static int password_points(int score, int breached)
{
    int s = score < 0 ? 0 : (score > 4 ? 4 : score);
    double base = s / 4.0 * 25.0;
    /* Breached is urgent regardless of strength: x0.32 floors even a
     * score-4 password at 8 points -> bad -> change-it recommendation. */
    return clamp25(breached ? base * 0.32 : base);
}

/* grades is an array of 'A'..'F' characters of length n. */
static int headers_points(const char *grades, int n)
{
    int f = 0, c = 0, b = 0;
    for (int i = 0; i < n; i++) {
        if (grades[i] == 'F') f++;
        else if (grades[i] == 'C') c++;
        else if (grades[i] == 'B') b++;
    }
    if (f > 0) return 0;
    if (c > 0) return 10;
    if (b > 0) return 18;
    return n > 0 ? 25 : 0;
}

static int breach_points(int pwned) { return pwned ? 0 : 25; }
static char letter_for(int percent, int max)
{
    if (max == 0) return '-';
    if (percent >= 85) return 'A';
    if (percent >= 70) return 'B';
    if (percent >= 50) return 'C';
    return 'D';
}

int main(void)
{
    const char grades[] = {'A', 'A', 'B'};
    int checks[4] = {
        fingerprint_points(18, 2, 4), /* 8  */
        password_points(4, 1),        /* 8  (breach floor) */
        headers_points(grades, 3),    /* 18 */
        breach_points(0),             /* 25 */
    };
    int total = 0, max = 4 * 25;
    for (int i = 0; i < 4; i++) total += checks[i];
    int percent = (int)((double)total / max * 100.0 + 0.5);
    printf("points: %d %d %d %d\n", checks[0], checks[1], checks[2], checks[3]);
    printf("total %d/%d = %d%% -> %c\n", total, max, percent, letter_for(percent, max));
    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 →