Skip to content

Secure Token Generator — C++ source

Generate cryptographically-secure random tokens in your browser. Pick the entropy size and format - hex, base32, base64, base62, or alphanumeric - and see the real strength in bits. Runs entirely client-side.

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

// token-generator — cryptographically-secure random tokens in hex/base32/base64/base62/... alphabets, with unbiased symbol selection and entropy/strength estimates. C++ (C++17) port of src/lib/token-generator.ts — same logic as this dir's javascript.js; the full 8-entry alphabet table, custom alphabets and injectable RNG omitted for the 80-line budget (see javascript.js / python.py). std::random_device is implementation-defined, but libc++/libstdc++ back it with the kernel CSPRNG on the major platforms.
#include <cmath>
#include <cstdint>
#include <iostream>
#include <random>
#include <string>
#include <unordered_map>
#include <vector>

// The fixed alphabets (subset).
const std::unordered_map<std::string, std::string> ALPHABETS{
    {"hex", "0123456789abcdef"},
    {"base32", "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"},                // RFC 4648
    {"base64url", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"},
    {"base62", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"},
};

// Resolve an alphabet name to its symbol string; unknown -> hex (the default).
std::string resolveAlphabet(const std::string &name) {
    auto it = ALPHABETS.find(name);
    return it != ALPHABETS.end() ? it->second : ALPHABETS.at("hex");
}

// Characters needed to carry `bytes` bytes of entropy through `size` symbols.
int outputLength(double bytes, int size) {
    if (bytes < 1 || size < 2) return 0;
    return static_cast<int>(std::ceil(bytes * 8.0 / std::log2(size)));
}

// Pick alphabet[n] WITHOUT modulo bias: naive draw % size favors trailing
// symbols whenever size does not divide the draw range (base62 etc.), so any
// draw at or above the largest multiple of size fitting in 32 bits is
// rejected and redrawn. The 64-redraw cap stops a broken RNG from looping
// forever — same guard as the TS/Python reference.
std::string selectUnbiased(const std::string &alphabet, int n) {
    static std::random_device rd;  // one secure 32-bit draw per operator()
    uint32_t size = static_cast<uint32_t>(alphabet.size());
    uint32_t limit = 0xFFFFFFFFu / size * size;
    std::string out;
    out.reserve(n);
    for (int i = 0; i < n; ++i) {
        uint32_t x = rd();
        for (int guard = 0; x >= limit && guard < 64; ++guard) x = rd();
        out += alphabet[x % size];
    }
    return out;
}

// Generate a token carrying `bytes` bytes of entropy through `alphaName`.
std::string generateToken(double bytes, const std::string &alphaName) {
    std::string alphabet = resolveAlphabet(alphaName);
    if (alphabet.size() < 2) return "";
    return selectUnbiased(alphabet, outputLength(bytes, static_cast<int>(alphabet.size())));
}

// Bucket an entropy estimate (bits) into the tool's strength tiers:
// weak <64 · fair 64-127 · strong 128-255 · very strong >=256.
const char *strengthLabel(double bits) {
    if (bits < 64) return "weak";
    if (bits < 128) return "fair";
    if (bits < 256) return "strong";
    return "very strong";
}

// Demo: the island's three showcase rows — 16-byte hex, 20-byte base62,
// 32-byte base32 — each labeled with its real strength in bits.
int main() {
    for (auto &[name, bytes] : std::vector<std::pair<std::string, double>>{
             {"hex", 16}, {"base62", 20}, {"base32", 32}}) {
        std::string token = generateToken(bytes, name);
        int size = static_cast<int>(resolveAlphabet(name).size());
        double bits = static_cast<double>(token.size()) * std::log2(size);
        std::cout << name << ' ' << bytes << " bytes -> " << token
                  << "  (" << bits << " bits, " << strengthLabel(bits) << ")\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 →