When the PRNG is not CSPRNG
Why is this Security meme funny?
Level 1: That’s Not Random!
Imagine you and your friend are playing a game where you flip a coin to decide who gets the last cookie. It’s supposed to be a fair, random choice. But then you notice something: your friend’s coin has heads on both sides! 😮 Every time they flip it, it’s going to land on heads. That’s not a real, unpredictable coin toss at all — it’s totally one-sided. You’d probably shout, “Hey, that’s not random!” because your friend isn’t actually leaving it up to chance. It’s the same kind of feeling in this meme.
In the picture, a character is screaming and holding their head because they saw something unfair or wrong with how randomness was being used. It’s like watching someone draw names out of a hat for a prize, but they never actually mix up the papers, so the same name keeps coming up. You’d be upset, right? You might not know all the details about computer code, but you can understand if something that’s supposed to be unpredictable is done in a way that anyone can guess the outcome. It ruins the whole point of being “random.”
So the meme is basically a big, funny way of saying: “This isn’t a fair way to do it!” The character’s over-the-top reaction — eyes wide, mouth open yelling “OH MY GOD!” — is how we feel inside when we see someone doing something obviously wrong. It’s both silly and truthful. Even a kid can get it: if you play a game and someone is secretly using a trick or not following the rules of chance, you’d call them out. You’d say, “That’s not how you do it!” In the meme, the person is saying “That’s not how you random!” meaning “you’re doing this random thing completely wrong!”. It’s funny because we don’t normally use “random” as an action like that, but it gets the point across in a simple way.
In short, the meme is showing a huge freak-out over someone messing up something that should be done fairly. Just like you’d be upset at a rigged coin toss, the developer in the picture is upset about a “rigged” or badly done random situation in code. It’s a relatable “not fair, not right!” moment, blown up large for comic effect. Even without knowing coding, you can relate to that feeling when you see something that’s just not done properly.
Level 2: Rigged Randomness
Stepping down to a more introductory view, let’s explain what’s going on in simpler terms. Computers can generate numbers that seem random using functions like rand() (in C/C++ and many languages) or Math.random() (in JavaScript, etc.). These functions produce a sequence of numbers based on an initial seed. Think of a seed as a starting point — give the same start, and you get the same sequence every time. That’s why we call them pseudo-random; they’re not truly random because they ultimately follow a predictable pattern defined by an algorithm.
Now, if you want a random number in a smaller range (say 0 to N-1), a common approach taught early is to use the modulo operator (%). For example, rand() % 10 gives you a number from 0 to 9. It’s easy and it works in a basic sense, but here’s the catch: it can introduce a slight bias. Bias means some numbers might come up more often than others, which isn’t a fair random spread. Why would that happen? Imagine rand() can originally produce numbers from 0 to 32767 (that’s a typical RAND_MAX in C). That’s 32768 possible values. If you ask for rand() % 10, there are 32768 possible outputs being squeezed into 10 buckets (0 through 9). Some buckets will end up with one more value than others because 32768 isn’t perfectly divisible by 10. Most of the time, this bias is tiny (and many programmers initially don’t notice it), but it’s there. It’s like having a slightly loaded die – maybe the number 6 has a 16.7% chance but 5 has 16.6%. Small difference, but it means it’s not perfectly random. This issue is called rand_modulo_bias (the bias introduced by using modulo on a random range that doesn’t fit evenly).
Another big issue in the meme’s scenario is how the random number generator is being used. Typically, you set the seed once (for example, with srand(time(NULL)) in C, which uses the current time to make the sequence different each run). But you should do that seeding only one time at the start of your program. In the horror story here, someone is seeding the PRNG repeatedly, maybe even every time they want a random number. In code, that’s like:
srand(time(NULL)); // seeding with current time
int number1 = rand(); // first random number
srand(time(NULL)); // seeding AGAIN immediately
int number2 = rand(); // second "random" number
If these calls happen quickly (within the same second), time(NULL) returns the same value each time (it only changes once per second). That means number1 and number2 might end up the same, because the sequence was reset to the same start! Even if it’s not the same second, constantly resetting (re-seeding) breaks the flow of randomness. It’s like starting a board game over from the beginning every turn — you’ll never get to the interesting unpredictable parts. This is what the tag bad_rng_seed is hinting at: using a poor strategy for seeding the random generator. A bad seed (like a constant number, or reusing the seed unnecessarily) leads to poor randomness.
So why are the developers in the meme so upset? Because using random numbers incorrectly can lead to bugs that are hard to find. For example, imagine you wrote a function to randomly choose a winner from a list of users. If your random isn’t truly random (let’s say it’s biased or repeats a lot), some users might never get chosen, and that’s a big problem (unfair and possibly really bad if it’s a lottery!). Or consider a game where an enemy is supposed to appear at random times. If someone messed up the random logic, maybe the enemy appears at very predictable intervals or not at all. These are CodeQuality issues — the code might run, but it doesn’t do its job reliably or fairly. It’s the kind of mistake a junior dev might make when first learning about random numbers, and a more experienced dev will catch it and go “Oh no, we need to fix that!”
Now, the meme text specifically says “THAT’S NOT HOW YOU RANDOM!” which is a funny way to say “you’re doing random number generation wrong.” We normally don’t use “random” as a verb. This phrasing is part of the humor. It exaggerates the frustration: the character in the meme is so shocked that proper grammar goes out the window. It’s like seeing someone use a hammer backwards and yelling, “That’s not how you hammer!” The top text “OH MY GOOOOOD!” with all those extra O’s? That’s pure DeveloperFrustration on display — a dramatic reaction. The stick-figure character is drawn with bulging eyes and hands on its head, which visually screams “What are you doing?!”
This meme uses the rage comic format, which was a popular way to depict hilarious (or horrific) moments with simple drawings. Even if you haven’t seen that exact face before, you can clearly tell he’s freaking out. In real-world terms, that’s the face a developer might make (at least internally) during a code review upon encountering such a mistake. Maybe you’ve had a teacher or mentor who looked absolutely alarmed when you tried something obviously wrong — that’s the vibe here. The categories like CS_Fundamentals come in because understanding random numbers is a basic computer science concept. The senior dev is upset presumably because this is something one learns in “Randomness 101”: how to properly generate random numbers and why it matters. It’s as fundamental as knowing how to avoid dividing by zero or why you shouldn’t hardcode passwords.
Let’s also touch on why using a simple PRNG (like rand()) for a public/private keypair is a huge deal. Public/private keys are used in encryption (like the locks for secure websites, or securing messages). For such keys to be secure, they must be generated with lots of true randomness. If they’re not, attackers can guess them. A normal PRNG like rand() is predictable if you know the seed. If someone suggests “just use rand() to pick prime numbers for keys” and seeds it poorly, a hacker could potentially recreate the same “random” numbers and figure out the key. It’s similar to using a non_cryptographic_rng (one not designed for security) for something that really needs to be unpredictable. In simpler words: it’s like using a see-through combination lock on a safe — anyone can watch how it’s set. That’s why the meme character is basically having a meltdown.
Overall, at this level, we can see the meme is about a common mistake: not understanding how to properly use random number functions. It frustrates experienced people because it’s known to cause problems. The image is exaggerating that frustration for comedic effect. Even if you’re new to programming, you can imagine the scenario: someone did something the wrong way, and their teammate is dramatically freaking out about it. It’s both funny and educational — pointing out that there is a right way and wrong way to “do random” in code.
Level 3: Biased Reaction
Now let’s step down to a senior developer’s perspective. The humor (and trauma) here comes from a very relatable dev experience: reviewing a teammate’s code and discovering they are misusing the random number generator. Picture a code review where you stumble on something like:
// Oh no, a wild bad practice appears:
for (int i = 0; i < 5; ++i) {
srand(time(NULL)); // Reseeding in each iteration (bad!)
int r = rand() % 100; // Using rand() modulo 100 (biased output)
printf("Value: %d\n", r);
}
A seasoned engineer’s reaction to this might well be the meme’s screaming stick figure! Why the rage? Because this code is practically a checklist of CodingMistakes we’ve been warning against for years:
- Re-seeding the PRNG inside a loop: This is a classic rookie move that severely hurts randomness. By doing
srand(time(NULL))every iteration, the developer is restarting the random sequence over and over. If this loop runs quickly,time(NULL)(which gives the current time in seconds) might be the same for many iterations — leading to the samerand()output repeating, or at best a very shallow pool of sequences. Even if it changes, you’re throwing away the PRNG’s internal state that normally produces a long sequence of varied numbers. A senior dev knows you should callsrand()once (usually at program start), not continuously. - Using
rand() % 100: The intent is to get a number from 0–99, but as discussed, this introduces rng_bias. The term “THAT'S NOT HOW YOU RANDOM!” directly calls out that this approach is not how you generate unbiased random numbers. The code will slightly favor some results over others. In a casual script, that might not be obvious, but in a large scale or long-running system, these biases can lead to weird, subtle bugs. Imagine a game where enemies drop loot “randomly” from 100 possibilities—ifrand()%100is biased, some loot items might almost never drop and players will sense something’s off. In critical systems (like load balancing servers or picking a random winner in a contest), such bias can even be unfair or dangerous. For a CodeQuality stickler, this is sloppy. It’s as if the code is saying it’s random, but lying about it.
Now, the meme specifically hints at an even more serious context: “When someone suggests using a PRNG to generate a public/private keypair.” This is where every senior engineer, especially those with a security background, collectively scream “OH MY GOD!” 😱. Generating cryptographic keys isn’t just any use of random numbers—it’s the foundation of security protocols. Poor randomness here can break encryption. A senior knows that if you use a predictable PRNG for keys, you might as well hand your house keys to a burglar. It’s that bad. This falls under both Bugs (it’s a vulnerability bug) and CodeQuality (utter lack of best practice). It’s the kind of thing that keeps security engineers up at night.
Let’s unpack the emotional charge: as developers gain experience, they accumulate some battle scars and unwritten rules. One of those rules is “Never use a simple PRNG for cryptography.” Another is “Seed once, and seed well.” We also learn about libraries and functions that do randomness right. So when a teammate, perhaps less experienced, says “Oh, just use random() to generate the RSA keypair,” the experienced folks immediately imagine all the worst-case scenarios. It’s not just theoretical—there have been real exploits and BugsInSoftware caused by such mistakes. For instance, there have been incidents where crypto keys were cracked because the random numbers weren’t truly random. Seasoned devs might recall those stories and think, “No, no, no, we are not repeating that disaster!” The dramatic rage comic format of the meme— with the wide-eyed character clutching its head — perfectly encapsulates that internal scream of horror. It’s the DeveloperFrustration equivalent of watching someone light a stick of dynamite thinking it’s a candle.
The top caption “OH MY GOOOOOD!” conveys that visceral reaction. It’s elongated, almost a wail. You can almost hear the voice in your head, right? This is exactly how it feels in the moment: you want to yell out loud (or maybe you actually do in a meeting) because the misuse is so glaring. The bottom caption, “THAT'S NOT HOW YOU RANDOM!”, is phrased in a comically exaggerated way — turning the word random into a verb. This phrasing is a nod to internet humor (the “That’s not how you [verb]” meme format) and it amplifies the absurdity. It’s like telling someone, “That’s not how you pizza!” if they tried to bake a pizza in a microwave still in the box. Here, it’s “That’s not how you random!” — meaning “You’re doing random number generation completely wrong.” The drama of the rage face and the all-caps text makes it clear this isn’t a minor nitpick; it’s an epic facepalm moment.
From a senior standpoint, several cringe-worthy scenarios are being referenced at once:
- Using a non_cryptographic RNG for a cryptographic purpose (keys) – a huge no-no.
- Developing code with a lack of understanding of RNG bias and seeding – implying maybe the teammate skipped some essential CS fundamentals.
- The prospect of subtle bugs or security holes that won’t be obvious until it’s too late. Senior devs fear those “lurking bugs” the most, because they’re hard to catch in testing but catastrophic in production.
This kind of code is the type that passes initial QA (it “works” on the surface), but later causes an incident at 3 AM on a weekend or, worse, a data breach. That’s why experienced engineers get passionate (and yes, a bit dramatic) about CodeQuality on such fundamentals. They know the cost of leaving it wrong. The meme’s humor is in exaggeration, but also in truth: everyone who’s been around the block has either made this mistake early on or had to fix someone else’s. The dramatic reaction is almost a rite of passage. Today it’s a meme; yesterday it was your senior engineer literally yelling “Nooooo!” across the room when spotting that rand() misuse.
The rage comic style itself is a bit of an in-joke for the developer community. Rage comics were popular in the early 2010s to depict common frustrations and absurdities in a crudely drawn, over-the-top way. By using that format, the meme taps into a kind of collective memory among internet veterans: “Remember when we’d use these faces to react to everything?” It’s retro, but it perfectly fits this DeveloperHumor scenario. The white Impact-font text with black outline — classic meme styling — makes the punchline loud and clear. The contrast of the silly cartoon with a very real technical gripe is what gives it punch.
In summary, at this senior level we’re laughing (and crying a little) because we’ve been there. The meme blends CodingHumor with a cautionary tale. It’s saying: Look, we all know someone might innocently write bad random code, but oh boy, it hurts to see. It’s funny because it’s true, and it’s only funny after you’ve learned why it’s true. Until then, one might wonder why everyone’s screaming — and that’s where the education begins. The rage-face engineer is essentially every senior developer internally screaming: “Please, for the love of binaries, do NOT do it that way!”
Level 4: Rand() Considered Harmful
At the most theoretical level, this meme highlights fundamental issues in random number generation. In computer science terms, rand() is a classic Pseudo-Random Number Generator (PRNG)—an algorithm that deterministically produces a sequence of numbers that appear random. Under the hood, many PRNGs (like the typical C rand()) use a linear congruential generator (LCG):
$$
X_{n+1} = (a \cdot X_n + c) \bmod m
$$
Here $X_0$ is the seed (an initial value), and $a$, $c`, and $m$ are carefully chosen constants. The sequence $X_1, X_2, \dots$ looks irregular, but given $X_0$ and the parameters, it's entirely predictable. That’s fine for simulations or simple games, but it’s a nightmare for security. When someone exclaims “THAT'S NOT HOW YOU RANDOM!”, they are pointing out a deep CS_Fundamentals concern: using a predictable algorithm in a context that demands unpredictability (like generating a cryptographic key) is fundamentally flawed.
One technical issue screamed at by the meme is rand modulo bias. When developers write code like value = rand() % N, they intend to get a random integer from 0 to N-1. In theory that seems uniform, but if the range of rand() (let’s call it $M$ possible values) isn’t exactly divisible by $N$, the distribution of remainders is uneven. If $M + 1$ (the total number of possible outputs of rand()) equals $q \cdot N + r$ (with some remainder $r$), then the smallest numbers (0 through $r-1$) occur one extra time in the output range. In plain math: if $r = (M+1) \bmod N$ and $r \neq 0$, some results pop out more often than others. For example, if RAND_MAX + 1 = 10 and N = 6:
- Remainders 0,1,2,3 come from 2 different outputs each (e.g. 0 from {0,6}, 1 from {1,7}, ...).
- Remainders 4 and 5 come from only 1 output each (4 from {4}, 5 from {5}).
So 0–3 have a 20% chance, while 4–5 have 10% each. That’s a bias. In large $N$ this bias might be subtle, but it’s real. For a CodeQuality purist or anyone working on sensitive simulations, this is a hidden bug in software waiting to bite.
Another glaring issue is seeding. PRNGs require an initial seed with enough unpredictability. A common newbie mistake (and part of the meme’s scenario) is calling srand(time(NULL)) repeatedly or at the wrong place. The time in seconds may not change between rapid calls, effectively reusing the same seed or a very predictable sequence. Mathematically, re-seeding resets the PRNG state—often leading to repetitions or correlated outputs rather than more randomness. It’s like pressing a reset button over and over; you never let the generator actually produce a varied sequence. A bad RNG seed (like a constant, or low-entropy value such as the current second) drastically shrinks the set of possible sequences. In fact, historically, serious vulnerabilities have arisen from poor seeding: early versions of Netscape’s SSL in the 90s seeded its RNG with just time and process ID, resulting in only about 2^15 possible seeds—attackers could brute-force all possibilities! Similarly, the infamous Debian OpenSSL bug (circa 2008) accidentally limited entropy, making millions of generated keys guessable. These real-world incidents back the meme’s dramatic horror: bad randomness can be catastrophic.
Crucially, this meme scenario crosses into the realm of cryptographic primitives. Generating a public/private keypair requires cryptographically secure random numbers. A cryptographically secure PRNG (CSPRNG) must pass stringent tests: its output should be unpredictable even if an attacker knows everything about the system except the current secret seed. Standard library rand() (or typical Math.random() in many languages) fails this standard — they’re not designed for security, just speed and basic distribution. They’re non-cryptographic RNGs. Use them for simulations or casual randomness in software, but never for secrets. For crypto, one should use specialized functions (like SecureRandom in Java, os.urandom() or Python’s secrets module, or hardware RNGs). These draw from true entropy sources or carefully vetted algorithms so the results can’t be predicted. It’s all about entropy: the measure of uncertainty. If you use a low-entropy source or a predictable algorithm, you’re effectively shouting your secret to the world.
So at this deep-dive level, the meme isn’t just a joke — it’s referencing the theoretical bedrock that randomness is hard. The horror on the stick figure’s face is mathematically justified. They recognize the code is committing a cardinal sin by using a shortcut where rigorous randomness is required. It’s a collision of deterministic chaos (pseudo-randomness) with a need for true unpredictability. And as any cryptographer will tell you: “Don’t roll your own random!” or you'll end up with random predictable keys and a dramatic meltdown meme to show for it.
Description
A classic rage comic meme expressing horror at a fundamental security mistake. The image features a crudely drawn, black-and-white stick figure character with bulging, bloodshot eyes, screaming with hands on its face in a gesture of pure shock and disbelief. Above the character, white text with a black outline reads, 'OH MY GOOOOD!'. Below, the text continues, 'THAT'S NOT HOW YOU RANDOM!'. The original post caption provides the context: 'When someone suggests using a PRNG to generate a public/private keypair'. For senior developers, this is a relatable moment of witnessing a junior or uninformed colleague propose a catastrophic security flaw. Using a standard Pseudorandom Number Generator (PRNG), which can be predictable, for cryptographic key generation is a cardinal sin. Cryptography requires a Cryptographically Secure PRNG (CSPRNG) that provides sufficient entropy and unpredictability to ensure keys cannot be guessed or reverse-engineered
Comments
19Comment deleted
Suggesting a standard PRNG for key generation is the fastest way to get your pull request comments to look like a CVE report
Sure, seed rand() with time(NULL) and loop until you’ve built a 2048-bit RSA key - because 86 400 possible outcomes per day totally counts as entropy, right?
After 15 years in the industry, you've seen developers seed Math.random() with the current timestamp, use it for cryptographic keys, and my personal favorite - calling it in a loop expecting different results without understanding the underlying PRNG state. The real horror is when they defend it in the PR comments with 'but it works on my machine!'
Every senior engineer has witnessed the horror: a junior dev using `new Random(DateTime.Now.Ticks)` inside a loop, or seeding with `time(NULL)` in a tight iteration, generating the same 'random' number thousands of times per second. Even worse is seeing `Math.random()` used for security tokens or session IDs. The real nightmare? Finding out your production system's 'shuffle' algorithm has been deterministically returning the same sequence for three years because someone thought `Random(42)` made for 'reproducible randomness' in prod. Cryptographically secure randomness isn't just pedantry - it's the difference between a secure system and a $4.2M breach settlement
srand(time(NULL)) in prod: 86,400 'unique' seeds a day, zero surprises
If your “random” is sort(() => Math.random() - 0.5), the distribution is just “who gets paged”; use Fisher - Yates with a CSPRNG
rand()%N + time-based reseeding: the only algorithm that guarantees both non-uniform distribution and reproducible breaches
int rand() { return 4; // chosen by a fair dice roll } Comment deleted
i see ps3 security right here Comment deleted
That was my tought too but is this really from the PS3? Or is that just a meme? Comment deleted
took from xkcd Comment deleted
I see thanks Comment deleted
on some talk explaining how someone broke into ps3, there was a slide with exactly this code Comment deleted
Just a meme Comment deleted
What I tought 😂 Comment deleted
But this have almost nothing to do with ps3! Except the fact the signature scheme were hacked thanks to breaking underlaying alghotithm which were providing random numbers for signatures Comment deleted
well, yeah Comment deleted
That's why we have Ed25519 scheme now and we are not using EdDSA anymore Comment deleted
I think you've meant DSA/ECDSA as Ed25519 is an implementation of EdDSA Comment deleted