Motivation
A few years ago I wrote a shell script for generating random passwords. I was pretty proud of it and I still use it to this day. I always wanted to make a UI for it. But I also know that if I try and design it myself, I'm going to get all caught up in the weeds for way too long obsessing about things that don't matter. So it remained a shell script.
Then, recently I was looking at some website designs on Frontend Mentor. One of the first designs that caught my eye was the design for a password generator. So I downloaded the design files and got to work.
Planning
Having a design file to work from really simplified things and allowed me to focus entirely on building rather than creating. I spent a few minutes jotting down the typography and color values so I'd have them on hand when needed. Then a few minutes looking at the design in Figma determining the different individual components of the app.
Before moving on to writing any actual code, I like to take a few minutes and diagram the interactions between components and make sure I have a solid mental model for managing the application state under various conditions. It may seem like overkill for an app this size but, I've found that taking the extra time to be thorough, more often than not, reveals at least one thing I had previously overlooked. And it's much easier to make adjustments at this stage.
Research
To make a good password generator, a few basic questions needed to be answered.
- What makes a good/bad password?
- How is the strength of a password determined?
- Which is more important complexity or length?
In order to answer those questions, we need to understand the concept of entropy.
What is entropy?
A good analogy for entropy is melting ice. When the ice is frozen solid, there is very little entropy. The molecules within the ice are fixed in space with very little movement. As the ice melts, the molecules have more freedom to move through space. As heat continues to raise the temperature, the ice turns into water, before finally turning into a gas. Each of these stages is an increase in entropy. The solid ice is stable and predictable. The liquid water is less predictable than the ice. The steam from evaporated water is less predictable than both.
We want our passwords to be like steam.
But how do we calculate a value for entropy? First we need to determine which character sets the password is using. Character sets typically fall into these categories:
- Lowercase letters: 26
- Uppercase letters: 26
- Numbers: 10
- Symbols: 33 (if all symbols allowed)
Once we've determined the length of the character set, we use the formula
1const entropy = password.length * Math.log(charSet.length) / Math.log(2)
A password 8 characters long using all four character sets has 52.5 bits of entropy. By current standards, this is not a lot. A password with 52 bits of entropy wouldn't necessarily be easy to crack. But it wouldn't necessarily be difficult either. It really all depends on the attacker and their capabilities. That is assuming your password isn't something like P@s5w0Rd
Generally speaking, the longer your password the more secure it is. Complexity helps but length is more important for adding bits of entropy. A 10 character password consisting of lowercase and uppercase characters will generate 57 bits of entropy. This might be ok but adding an additional 4 characters will generate nearly 80 bits of entropy, which is more than enough by current standards.
Roadmap forward
The original design didn't have any mention an entropy meter. But I thought it would be a nice feature so I added it. I'd also like to add the ability for users to enter their own password and gauge their entropy levels. Another cool thing would be the ability to generate random pass phrases instead of passwords. Something like fried:okra is:gross
will generate over 111 bits of entropy. And it's much easier to remember.