Randomness plays a crucial role in many aspects of computing, particularly in cryptography, security, and data analysis. A key generator’s ability to produce truly random keys can significantly impact the security and integrity of an application. In this article, I’ll compare the randomness of keys generated using Django’s built-in method and a custom JavaScript method. I’ll delve into various statistical tests, their results, and what they mean in the context of randomness.

### Methodology

To conduct this comparison, I randomly generated 50,000 unique keys using Django’s built-in key generator and my custom JavaScript key generator. I then applied several statistical tests to evaluate the randomness of these keys. The tests I used include the Chi-square test, Kolmogorov-Smirnov (KS) test, runs test, serial correlation test, and entropy calculation.

### Key Generation

#### Django Key Generator

Django’s key generator is known for its reliability and security. Here are excerpts from Django’s source code to show how they generate secret keys. First, here is get_random_secret_key():

```
def get_random_secret_key():
"""
Return a 50 character random string usable as a SECRET_KEY setting value.
"""
chars = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)"
return get_random_string(50, chars)
```

And here is get_random_string():

```
def get_random_string(length, allowed_chars=RANDOM_STRING_CHARS):
"""
Return a securely generated random string.
The bit length of the returned value can be calculated with the formula:
log_2(len(allowed_chars)^length)
For example, with default `allowed_chars` (26+26+10), this gives:
* length: 12, bit length =~ 71 bits
* length: 22, bit length =~ 131 bits
"""
return "".join(secrets.choice(allowed_chars) for i in range(length))
```

#### JavaScript Key Generator

My custom JavaScript key generator is designed to produce unique keys with a similar length and format to those generated by Django:

```
function getRandomSecretKey() {
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)';
const randomSecretKey = getRandomString(50, chars);
return randomSecretKey;
}
function getRandomString(length, characters) {
let result = '';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
```

So, it’s fairly close using Math.random() instead of Python’s secrets.

When I released it, I knew it wasn’t quite as random as Django’s built in method but I wasn’t sure how big the difference was. So I decided to conduct a test.

### Statistical Tests and Results

#### Chi-square Test

The Chi-square test checks if the distribution of generated keys deviates significantly from a uniform distribution. A low statistic value and a high p-value indicate no significant deviation.

Django: Statistic = 1.72562879999999e-05, p-value = 1.0 JavaScript: Statistic = 1.445518399999996e-05, p-value = 1.0

Both generators show no significant deviation from uniform distribution, indicating good randomness.

#### Kolmogorov-Smirnov (KS) Test

The KS test compares the generated keys’ distribution to a uniform distribution. A lower statistic value suggests less deviation.

Django: Statistic = 0.54, p-value ≈ 4.93e-07 JavaScript: Statistic = 0.56, p-value ≈ 1.45e-07

Both results indicate significant deviation from a uniform distribution. Django’s keys show a slightly lower deviation, suggesting they might be marginally more random.

#### Runs Test

The runs test assesses the sequence’s randomness by counting the runs (consecutive identical bits) in the key sequence.

Django: Result = 39164.377562610505 JavaScript: Result = 39365.55671662353

Both generators have high runs test values, indicating a high degree of randomness in the sequence.

#### Serial Correlation Test

This test measures the correlation between successive keys. Lower correlation means higher randomness.

Django: Statistic = 0.6812142552311041, p-value = 0.40916891308007064 JavaScript: Statistic = 0.5588039129017677, p-value = 0.4547425660213563

Both tests show no significant serial correlation, indicating that successive keys are not related.

#### Entropy

Entropy measures the unpredictability of the generated keys. Higher entropy indicates more randomness.

Django: Entropy = 5.643843740642531 JavaScript: Entropy = 5.643845763351637

Both generators exhibit high entropy, suggesting high unpredictability and randomness.

#### Frequency Distribution

The frequency distribution shows how often each key appears. A uniform distribution indicates good randomness.

Django:

```
0.0199324, 0.0199468, 0.020004, 0.0200408, 0.0199268, 0.0200336, 0.0201292, 0.0200284, 0.0200128, 0.0199392,
0.0200096, 0.0199636, 0.0199616, 0.0200544, 0.01981, 0.0200448, 0.020038, 0.0199224, 0.019978, 0.020092,
0.0200248, 0.0200152, 0.0200208, 0.0201392, 0.019978, 0.0200404, 0.0199528, 0.0199332, 0.020026, 0.0199484,
0.0200372, 0.0199844, 0.0198648, 0.0200084, 0.0199772, 0.0198332, 0.019932, 0.0200152, 0.01981, 0.020104,
0.0201188, 0.0200844, 0.0199556, 0.0199432, 0.0201696, 0.0201848, 0.0201056, 0.0199344, 0.020066, 0.019924
```

Javascript:

```
0.0201124, 0.0201272, 0.0201552, 0.0200472, 0.0200464, 0.0199264, 0.0199172, 0.0199452, 0.0199556, 0.0199392,
0.0199468, 0.019908, 0.020034, 0.0199076, 0.0199008, 0.0200292, 0.019916, 0.0199028, 0.0200292, 0.0199788,
0.0200252, 0.0199932, 0.0200668, 0.0199152, 0.0199408, 0.02013, 0.0201432, 0.0199188, 0.0198592, 0.02005,
0.0200112, 0.0200036, 0.019872, 0.020028, 0.0199584, 0.0200704, 0.0200308, 0.0200052, 0.0199728, 0.0200604,
0.0200172, 0.0201264, 0.02005, 0.0200048, 0.0199832, 0.0198552, 0.0200636, 0.0200288, 0.0200244, 0.020066
```

### Conclusion

Based on my analysis, both the Django and JavaScript key generators produce highly random keys. However, the KS test results suggest that Django’s keys might be marginally more random. Here’s a summary of my findings:

Django: Slightly lower KS test statistic, high entropy, no significant serial correlation, and high randomness based on the runs test.

JavaScript: Very similar performance, with slightly higher KS test statistic but equally high entropy and no significant serial correlation. In practical terms, both generators are robust and capable of producing secure, random keys. For applications where the utmost randomness is critical, Django might have a slight edge, but the difference is minimal.

I’ll be releasing my code and data in the coming days. Watch this space for updates.