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++ (C++20, 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 <algorithm>
#include <cmath>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>

// Round to the nearest point and pin into the 0..25 window.
int clamp25(double points)
{
    return static_cast<int>(std::clamp(std::lround(points), 0L, 25L));
}

enum class Grade { A, B, C, F };
// 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.
int fingerprint_points(int signal_count, int high_risk, int medium_risk)
{
    const double surface = std::max(0, signal_count - 12) * 0.5;
    return clamp25(25.0 - high_risk * 4.0 - medium_risk * 1.5 - surface);
}

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

int headers_points(const std::vector<Grade>& grades)
{
    const auto has = [&](Grade g) { return std::find(grades.begin(), grades.end(), g) != grades.end(); };
    if (has(Grade::F)) return 0;
    if (has(Grade::C)) return 10;
    if (has(Grade::B)) return 18;
    return grades.empty() ? 0 : 25;
}

int breach_points(bool pwned) { return pwned ? 0 : 25; }

std::string letter_for(int percent, int max)
{
    return max == 0 ? "—" : percent >= 85 ? "A" : percent >= 70 ? "B" : percent >= 50 ? "C" : "D";
}

// Renormalize over the checks that ran and grade the overall letter.
struct Result { int total, max, percent; std::string letter; };

Result score_privacy(const std::vector<int>& points)
{
    const int total = std::accumulate(points.begin(), points.end(), 0);
    const int max = static_cast<int>(points.size()) * 25;
    const int percent = max == 0 ? 0 : static_cast<int>(std::lround(total * 100.0 / max));
    return {total, max, percent, letter_for(percent, max)};
}

int main()
{
    const std::vector<int> checks = {
        fingerprint_points(18, 2, 4),                    // 8
        password_points(4, true),                        // 8 (breach floor)
        headers_points({Grade::A, Grade::A, Grade::B}),  // 18
        breach_points(false),                            // 25
    };
    const Result r = score_privacy(checks);
    std::cout << "total " << r.total << '/' << r.max << " = " << r.percent
              << "% -> " << r.letter << '\n';
}

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 →