Skip to content

Conversation

@laura240406
Copy link
Contributor

My proposal implementation for #2808. The WIN32 version is untested as it seems to be impossible for me to obtain the Windows SDK as it's buried in layers of MSIs that Wine can't deal with.

@laura240406
Copy link
Contributor Author

you can test this with

import std::io;
import std::crypto::random;

fn void main()
{
    char [64] key;
    random::crypto_secure_random(&key)!!;

    io::printn(key);
}

@ManuLinares
Copy link
Contributor

fopen, fread, fclose is not a good way to get a random. Have you taken a look at my example in #2808, syscall is much faster.

👎

@laura240406
Copy link
Contributor Author

It's much more portable as it also works on the BSDs and Darwin and the syscall number of getrandom() depends on the architecture.

@laura240406 laura240406 reopened this Jan 23, 2026
@laura240406
Copy link
Contributor Author

idk why it just closed the PR but I've added the getrandom() call for Linux/x86_64

@laura240406
Copy link
Contributor Author

It makes sense to add OS/Architecture specific cases to use the syscall but the file method should remain as a fallback.

@laura240406
Copy link
Contributor Author

The current implementations are:

Linux/Android x86_64/Aarch64: syscall
Linux x86: syscall
Win32: call RtlGenRandom (basically like a syscall)
Android/Linux/*BSD/Darwin: read /dev/random or /dev/urandom if the first two didn't work

@laura240406
Copy link
Contributor Author

I'm also currently installing Windows 10 in a VM to test the Win32 implementation.

@Book-reader
Copy link
Member

The stdlib has a random interface that can be used through functions like random::next_float(&my_rand):

c3c/lib/std/math/random.c3

Lines 165 to 174 in 396263f

interface Random
{
fn void set_seed(char[] input);
fn char next_byte();
fn ushort next_short();
fn uint next_int();
fn ulong next_long();
fn uint128 next_int128();
fn void next_bytes(char[] buffer);
}

Maybe this could be added under https://github.com/c3lang/c3c/tree/master/lib/std/math/random as a type that implements this interface? Though I don't know if this form of random would be able to fulfil the expectations of the Random interface (specifically setting the random seed) so it's up to you if you want to do that.

@laura240406
Copy link
Contributor Author

laura240406 commented Jan 24, 2026

No the idea is to use this to derive cryptographically strong keys.
We could, however, add some helper that initializes such a Random instance from a strong seed.
I could think of something like RSA key generation where we read a cryptographically strong seed, put it into some Random implementation and use that to then sample primes until we have 2.

I originally started this since I wanted to implement RSA for the stdlib but then I realized there is no way to generate those random primes safely.

@laura240406
Copy link
Contributor Author

I wonder if we should add an option to use RDRAND on x86 platforms that support it since it should be faster than getrandom() and still produce adequate randomness.

@laura240406
Copy link
Contributor Author

Okay from my tests, the Win32 version works on Windows 10 and under Wine.

@ManuLinares
Copy link
Contributor

@laura240406 Pull requests aren't meant for ongoing experimentation. Please keep PRs focused on a specific requested change, or a complete implementation. For discussion or exploration, let's use issues, discussions or discord chat instead.

@laura240406
Copy link
Contributor Author

laura240406 commented Jan 24, 2026

okay but this PR as it currently stands should be done

it has syscall implementations for the main platforms of Linux/Android (x86_64/x86/Aarch64) and the library implementation of Win32 and the fallback of /dev/urandom

a later PR could add *BSD specific getrandom() implementations and x86 RDRAND implementations but that's out of scope rn

@laura240406
Copy link
Contributor Author

I've also tested it on OpenBSD (uses /dev/urandom) and it works

alias RtlGenRandom = fn CInt(void *, ulong);
RtlGenRandom rtlgenrandom @if(env::WIN32) @local;

fn void crypto_init_win32_random() @if(env::WIN32) @init
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably not be @init, since that will make ALL win32 apps do this. Instead, the correct way is to run this once. You can use OnceFlag.call_once in std::thread to ensure it's done once across all threads.

@lerno
Copy link
Collaborator

lerno commented Jan 30, 2026

Can you add a test for this to the unit tests, and then add a note in the releasenotes as well please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants