Writing a CSPRNG in C: Entropy over External Tools

System.init()

With just a few lines of C, we can generate high-entropy, international-standard passwords. Yet, most users still prefer relying on external websites—essentially outsourcing their security to third-party nodes.

Why trust an external server's PRNG when you can compile your own generator and read directly from /dev/urandom?

Example Output

MTικ+Yilл月黄-ЙdΛ宇&洪日tπυ+玄-и0Щ来^]pe}χмsδι盈сidM)8@зΧ&В=isrΡΛπSJiΑΝg ρηh5%%O-Φ!-τΧ5Ы2μю昃地Ь盈*宿ΡδΨМiυzσf8Ι

Source_Code

This implementation uses setlocale for wide-character support and pulls raw bytes from the kernel's entropy pool.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <wchar.h>
#include <locale.h>

const wchar_t latin[] = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
const wchar_t cyrillic[] = L"бвгдёжзийклмнпрстуфхцчшщъыьэюяБВГДЕЁЖЗИЙКЛМНПРСТУФХЦЧШЩЪЫЬЭЮЯ";
const wchar_t greek[] = L"αβγδεζηθικλμνξοπρστυφχψωΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ";
const wchar_t chinese[] = L" dignified天地玄黄宇宙洪荒日月盈昃辰宿列张寒来暑往秋收冬藏";
const wchar_t symbols[] = L"!@#$%^&*()_+-=[]{}|";

const wchar_t* alphabets[] = {latin, cyrillic, greek, chinese, symbols};
const int counts[] = {62, 66, 48, 30, 19}; 

int main(int argc, char *argv[]) {
    setlocale(LC_ALL, "");

    if (argc < 2) {
        printf("Usage: %s <length>\n", argv[0]);
        return 1;
    }

    int length = atoi(argv[1]);
    int fd = open("/dev/urandom", O_RDONLY);

    if (fd == -1) {
        perror("Error opening /dev/urandom");
        return 1;
    }

    wprintf(L"Your international password: ");
    for (int i = 0; i < length; i++) {
        unsigned char r_base[2];
        read(fd, r_base, 2); 

        int alpha_idx = r_base[0] % 5; 
        int char_idx = r_base[1] % counts[alpha_idx]; 

        wprintf(L"%lc", alphabets[alpha_idx][char_idx]);
    }
    wprintf(L"\n");

    close(fd);
    return 0;
}

Compilation_Log

To build this on a Unix-like system (GNU/Linux, Guix, BSD):

gcc passgen.c -o passgen
./passgen 64

> Back to Articles