A
...
pseudorandom
...
number
...
generator
...
(PRNG)
...
is
...
a
...
deterministic
...
algorithm
...
capable
...
of
...
generating
...
sequences
...
of
...
numbers
...
that
...
approximate
...
the
...
properties
...
of
...
random
...
numbers.
...
Each
...
sequence
...
is
...
completely
...
determined
...
by
...
the
...
initial
...
state
...
of
...
the
...
PRNG
...
and
...
the
...
algorithm
...
for
...
changing
...
the
...
state.
...
Most
...
PRNGs
...
make
...
it
...
possible
...
to
...
set
...
the
...
initial
...
state,
...
also called
...
the
...
seed
...
state. Setting
...
the
...
initial
...
state
...
is
...
called seeding
...
the
...
PRNG.
Calling a PRNG in the same initial state, either without seeding it explicitly or by seeding it with the same value, results in generating the same sequence of random numbers in different runs of the program.
...
This noncompliant code example generates a sequence of 10 pseudorandom numbers using the rand()
function. When rand()
is not seeded, it uses uses 1
as a default seed. No matter how many times this code is executed, it always produces the same sequence.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <stdlib.h> void func(void) { for (int i = 0; i < 10; ++i) { printf("%d, ", rand()); /* Always generates the same sequence */ printf("%d, ", rand()); } } |
output: 1st run: 41, 18467, 6334, 26500, 19169, 15724, 11478, 29358, 26962, 24464, 2nd run: 41, 18467, 6334, 26500, 19169, 15724, 11478, 29358, 26962, 24464, ... nth run: 41, 18467, 6334, 26500, 19169, 15724, 11478, 29358, 26962, 24464,
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <stdlib.h> #include <time.h> void func(void) { srand(time(NULL)); /* Create seed based on current time */ for (int i = 0; i < 10; ++i) { printf("%d, ", rand()); /* Generates different sequences at different runs */ printf("%d, ", rand()); } } |
output: 1st run: 25121, 15571, 29839, 2454, 6844, 10186, 27534, 6693, 12456, 5756, 2nd run: 25134, 25796, 2992, 403, 15334, 25893, 7216, 27752, 12966, 13931, 3rd run: 25503, 27950, 22795, 32582, 1233, 10862, 31243, 24650, 11000, 7328,
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <stdlib.h> void func(void) { for (int i = 0; i < 10; ++i) { printf("%ld, ", random()); /* Always generates the same sequence */ printf("%ld, ", random()); } } |
output: 1st run: 1804289383, 846930886, 1681692777, 1714636915, 1957747793, 424238335, 719885386, 1649760492, 596516649, 1189641421, 2nd run: 1804289383, 846930886, 1681692777, 1714636915, 1957747793, 424238335, 719885386, 1649760492, 596516649, 1189641421, ... nth run: 1804289383, 846930886, 1681692777, 1714636915, 1957747793, 424238335, 719885386, 1649760492, 596516649, 1189641421,
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <stdlib.h> #include <time.h> void func(void) { srandom(time(NULL)); /* Create seed based on current time counted as seconds from 01/01/1970 */ srandom(time(NULL)); for (int i = 0; i < 10; ++i) { printf("%ld, ", random()); /* Generates different sequences at different runs */ printf("%ld, ", random()); } } |
output: 1st run: 198682410, 2076262355, 910374899, 428635843, 2084827500, 1558698420, 4459146, 733695321, 2044378618, 1649046624, 2nd run: 1127071427, 252907983, 1358798372, 2101446505, 1514711759, 229790273, 954268511, 1116446419, 368192457, 1297948050, 3rd run: 2052868434, 1645663878, 731874735, 1624006793, 938447420, 1046134947, 1901136083, 418123888, 836428296, 2017467418,
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <Windows.h>
#include <wincrypt.h>
#include <stdio.h>
void func(void) {
HCRYPTPROV hCryptProv;
long rand_buf;
/* An example of instantiating the CSP */
if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
printf("CryptAcquireContext succeeded.\n");
} else {
printf("Error during CryptAcquireContext!\n");
}
for (int i = 0; i < 10; ++i) {
if (!CryptGenRandom(hCryptProv, sizeof(rand_buf), (BYTE *)&rand_buf)) {
printf("Error\n");
} else {
printf("%ld, ", rand_buf.li);
}
}
}
|
output: 1st run: -1597837311, 906130682, -1308031886, 1048837407, -931041900, -658114613, -1709220953, -1019697289, 1802206541, 406505841, 2nd run: 885904119, -687379556, -1782296854, 1443701916, -624291047, 2049692692, -990451563, -142307804, 1257079211, 897185104, 3rd run: 190598304, -1537409464, 1594174739, -424401916, -1975153474, 826912927, 1705549595, -1515331215, 474951399, 1982500583,
...
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
MSC32-C | mediumMedium | likelyLikely | lowLow | P18 | L1 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
CERT C Secure Coding Standard | MSC30-C. Do not use the rand() function for generating pseudorandom numbers |
CERT C++ Secure Coding Standard | MSC32-CPP. Ensure your random number generator is properly seeded |
MITRE CWE | CWE-327, Use of a broken or risky cryptographic algorithm CWE-330, Use of insufficiently random values |
...