> ## Content Index
> Fetch the complete content index at: https://securinglaravel.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Security Tip: Don't Generate Your Own Passwords!
- URL: https://securinglaravel.com/security-tip-dont-generate-your-own-passwords/
- Published: 2025-06-02T18:00:34.000Z
- Updated: 2025-06-02T18:00:40.000Z
- Description: [Tip #113] "Don't Roll Your Own Crypto" applies to password generators too! It's way too easy to unknowingly lower your entropy by trying to be clever... 😱
- Author: Stephen Rees-Carter
- Tags: Security Tips, Passwords, Cryptography

Following on from last week's [*Security Tip: Don't Use phpinfo()!*](https://securinglaravel.com/security-tip-dont-use-phpinfo/), we have another example of vulnerable code that I came across during a [security audit](https://valorinsecurity.com/?ref=securinglaravel.com).

Take a look:

```php
function generatePassword($length = 9): string
{
    $characters = str_split('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');

    $password = '';
    $password .= $characters[rand(10, 35)];
    $password .= $characters[rand(36, 61)];
    $password .= $characters[rand(0, 9)];

    while (strlen($password) < $length) {
        $password .= $characters[array_rand($characters)];
    }

    return $password;
}
```

There are a number of small problems here that combine together into two main issues:

### Terrible Entropy!

1. The function defaults to `9` character passwords, which is well short of the [recommended 15 characters by NIST](https://pages.nist.gov/800-63-4/sp800-63b.html?ref=securinglaravel.com#passwordver).
2. There is a limited character set with only 62 possible characters: `0-9`, `a-z`, and `A-Z`. Well short of the [95 standard ASCII characters](https://www.ascii-code.com/characters/printable-characters?ref=securinglaravel.com) that could be used.
3. The format is predictable: lower-case character, upper-case character, digit, then 6 random characters (`([a-z][A-Z][0-9][0-9a-zA-Z]{6}`). This is identifiable given a large enough set.

Combine all of these, and the resulting entropy is incredibly limited:

*log₂( 26 \[lower\] x 26 \[upper\] x 10 \[digit\] x (26 + 26 + 10)^6) =>* [*48 bits of entropy*](https://www.wolframalpha.com/input?i=log2%28+26+%2A+26+%2A+10+%2A+%28+%28+26+%2B+26+%2B+10+%29+%5E+6+%29+%29&ref=securinglaravel.com)

Compare that to the entropy of a 15 character password using a 95 character set:

*log₂( 95 ^ 15 ) =>* [*96 bits of entropy*](https://www.wolframalpha.com/input?i=log2%28+95+%5E+15+%29&ref=securinglaravel.com)

Yeah... it's bad.

🤓

***"Entropy"** *is basically just a fancy word for how random a password is, based on how many possible options there are.* 

### Insecure Randomness!

Not only does this password generator have terrible entropy, but it's also using PHP's `rand()` and `array_rand()` functions - which **do not generate cryptographically secure random values!** 

Instead, they generate a set of known outputs from a limited set of seed values, which makes them predictable under the right conditions. Therefore, it is [theoretically possible](https://paragonie.com/blog/2015/07/how-safely-generate-random-strings-and-integers-in-php?ref=securinglaravel.com) that an attacker could generate the list of all possible passwords this generator could produce - making brute-force or cracking attacks significantly easier.

### What Is The Solution?

If you have a password generator in your code, **go delete it.**

I'm being serious here, unless you're a cryptography nerd, **go delete your custom password generator!** 

It's way too easy to make a mistake trying to roll your own crypto, and end up with a weak password generator that produces terrible passwords. Instead, you want to use an existing password generator that's been properly tested and reviewed. 

**I'd suggest starting with Laravel's** [**Str::password()**](https://laravel.com/docs/strings?ref=securinglaravel.com#method-str-password) **helper** \- it's been in the framework since version 10 and has some basic configuration options for length and toggling character sets.

Alternatively, if you need something with more power, check out [Random::password()](https://github.com/valorin/random?ref=securinglaravel.com#random-string) from my `valorin/random` package. It gives you full control over the exact characters included, and I've had a couple of crypto-nerds review the code to make sure it's safe.

---

***If you found this security tip useful,*** [***subscribe***](#/portal/signup) ***to get weekly*** [***Security Tips***](https://securinglaravel.com/tag/tips/) **straight to your inbox.* Upgrade to a* [*premium subscription*](#/portal/signup) *for exclusive monthly* [*In Depth articles*](https://securinglaravel.com/tag/in-depth/)*, or drop a coin in the* [*tip jar*](#/portal/support) *to show your support.*

*When was the last time you had a penetration test? Book a* [*Laravel Security Audit and Penetration Test*](https://stephenreescarter.net/laravel-security-audits-and-pentesting/?utm%5Fsource=securinglaravel.com)*, or a budget-friendly* [*Security Review*](https://stephenreescarter.net/laravel-security-reviews/?utm%5Fsource=securinglaravel.com)*!* 

*You can also connect with me on* [*Bluesky*](https://bsky.app/profile/valorin.bsky.social?ref=securinglaravel.com)*, or* [*other socials*](https://pinkary.com/@valorin?ref=securinglaravel.com)*, and check out* [*Practical Laravel Security*](https://practicallaravelsecurity.com/?utm%5Fsource=securinglaravel.com)*, my interactive course designed to boost your Laravel security skills.*