Technical Details

This page lists more technical details of the implementation of the site and exactly how it generates passwords.

What Platform and Environment is the Site Based On?

I'm a Windows .NET developer, so my platform choice reflects that:

Most of the site could be quite easily run on the Mono platform. However there are some quite windows centric calls when deriving entropy for the random number generator. Appropriate alternatives should be available on other platforms.

Where Can I Get the Source Code?

From BitBucket. Under the Apache License.

What Developer Tools do I need to Build the Site?

I'm developing using Visual Studio. Dependencies are referenced by nuget or included as binary assets. There is no database behind the scenes.

What Random Number Generator are you Using?

The fundamental building block of any password generator is a cryptographic random number generator. The key requirements of which are:

  1. You can't determine the next result based on the current one (or after observing many results).
  2. You can't determine previous results based on the current one (or after observing many results).

The standard option on Windows .NET is to use RNGCryptoServiceProvider. But I don't want to put all my eggs in one basket, so I'm using a random number generator which derives its data from many sources. This is called Terninger, which is my own implementation of Fortuna, a CRNG designed by Bruce Schneier.

Prior to May 2018, I was using a random number generator of my own design. I don't believe this had any serious flaws, but Terninger is of much higher quality.

What Random Tests Have you Subjected Your RNG to?

The core PRNG (AES in counter mode) was put through 4 separate random number test suites. These were: PractRand, RaBiGeTe, TestU01 and Dieharder. It even passed them all!

The pooled generator uses the same core PRNG (as specifed in Fortuna). As long as the pool accumulates entropy and reseeds the internal PRNG (and yes, I've checked it does), the above results apply to every random number used by Make Me a Password.

What Sources of Entropy do you use?

No matter what randomisation algorithms are used, without a good source of entropy you'll get the same numbers out the other end. The following sources are used by Terninger:

See here for further details of the base sources used. Over time, I expect to add other sources, as time allows me to implement them.

What Algorithms do you use to Generate Passwords?

Each algorithm is implemented in MVC controller classes named (for example) ApiPassphraseV1Controller. Generally, they are table lookups. Where the table varies from style to style. By convention, a method SelectPhrases() / SelectPasswords() / SelectPINs() returns one or more passwords based on the parameters supplied.

More details can be found in the API documentation.

Hex Style

The hex passwords are taken directly from the random number generator without any modification. No lookups, tables or hash functions here. Just raw, unadulterated bytes.

Passphrase Style

Each word is chosen from the dictionary as a giant lookup. After the phrase is constructed, it may be rejected if it does not meet the length requirements. After 100 attempts without meeting length requirements, a null passphrase will be returned.

Pronouncable Style

Uses a lookup into vowel and consonant sounds. Some very basic logic is used to alternate between vowels and consonants, but I could do much better cleaning up double letters and so on.

Readable Passphrase Style

This calls out to a 3rd party library to generate passwords. Source code is available. After the phrase is constructed, it may be rejected if it does not meet the length requirements. After 100 attempts without meeting length requirements, a null passphrase will be returned.

PIN Style

PINs are constructed as a lookup into the digits 0..9. After a PIN is constructed, it may be rejected if it is on the blacklist.

Unicode Style

There are too many code points to do lookups into a full table of known characters. So generating Unicode passwords uses a different algorithm.

  1. A random Int32 is generated to select a candidate code point.
  2. High bits from the int is masked depending on if only code points from the basic multilingual plane are selected (or not)
  3. The candidate code point may be rejected if it lies in certain ranges (surrogate points, control codes, etc)
  4. The candidate code point must be classed as a particular Unicode category (this is how East Asian characters are excluded)