Conor's answer is a good starting point, but if you dig into Chromium's source the situation starts to look a little bleaker (but still better than not using a password manager at all).
Chrome 68 (current version as of August 1st, 2018)
Up through version 68 Chrome follows FIPS 181 to generate a 15 character pronounceable password allowing uppercase letters, lowercase letters, and numbers. If the result doesn't contain both an uppercase letter and a number, it changes the first lowercase letter to uppercase, and changes the last lowercase character to a random digit.
Unfortunately the entropy of a FIPS 181 password is pretty hard to calculate, as it generates variable length syllables rather than characters, and there are a bunch of rules dictating whether or not a syllable is allowed.
The non-uniformity has severe implications. A 1994 paper (page 192) estimated that to break into 1 out of 100 accounts with 8 character passwords, an attacker would only have to try 1.6 million passwords. Even if increasing the length from 8 to 15 doubles the entropy, that's still probably under 60 bits of entropy on average1, though this is improved slightly due to capitalization.
The original standard doesn't appear to support uppercase letters or numbers, and the implementation2 only capitalizes the first letter of a syllable with a 50% chance (interestingly y
is replaced with w
in the array of characters checked, so y
will never be capitalized). This means that rather than adding about 1 bit of entropy per letter, capitalization only adds 1 bit per syllable. The number of syllables isn't constant, so it's hard to determine how much entropy this actually adds, but given the scarcity of single letter syllables it almost certainly adds less than 8 bits on average.
Numbers and symbols are supported by turning each single letter syllable alternately into a digit or symbol with 50% chance (though the symbol feature isn't used). Unfortunately, as you have noticed, single letter syllables are uncommon3, so ForceFixPassword
usually ends up swapping out the last lowercase letter for a digit.
There may be more issues, but I'm getting a bit tired of looking at it. In short, this isn't a very good method of generating passwords, and the entropy is significantly less than one would expect for the length. In practice this is still probably ok for the average user, as it means they won't be using their favorite low entropy password in 20 different places, but breaking it is definitely possible for a determined and funded attacker with a fast hash (ie not a good password hash) of the password.
Chrome 69 (scheduled for release in September)
Things are looking much better in Chrome 69. The character set is upper and lowercase letters, numbers, and the symbols -_.:!
with the following removed for readability:
l
(lowercase letter L)
I
(capital letter i)
1
(digit one)
O
(capital letter o)
0
(digit zero)
o
(lowercase letter O)
The generation works by adding a random character from each class until the minimum count for said class is met. By default and as currently used this is one lowercase character, one uppercase character, and one digit.
Then the rest of the password is filled with random characters evenly chosen from all character classes (respecting a maximum count for each class, currently unused).
Finally, since characters were added to the beginning of the password from predictable classes in order to satisfy requirements, the string is randomly shuffled. The shuffling happens up to 5 times if two dashes or underscores are adjacent in order to improve readability, so this will very slightly reduce the entropy, but the reduction is so slight as to be unnoticeable (and removing dash or underscore from the allowed symbols would be worse).
With 61 possible characters a fully random password would have log2(6115) = 88.96 bits of entropy. Using inclusion-exclusion to account for the required characters, I come up with 88.77 bits of entropy:
61^15 all possible passwords
-53^15 passwords without digits 2-9 (0 and 1 are excluded)
-37^15 passwords without lowercase letters (l and o excluded)
-37^15 passwords without uppercase letters (I and O excluded)
+29^15 add back passwords excluded twice for lack of digit and lowercase
+29^15 add back passwords excluded twice for lack of digit and uppercase
+13^15 add back passwords excluded twice for lack of lowercase and uppercase
-5^15 remove all-symbol passwords that were excluded then added back
The extra shuffling will shave off a fraction of a bit as well, but I don't have time to calculate it right now. In the end, the password should have over 88 bits of entropy, which is pretty good.
The old generator still exists in version 69, but when I tested the dev build it was using the new one. Whether or not there's any way to use the old generator I don't know.
1. Average entropy isn't necessarily useful with non-uniform distributions, the original 1975 paper gives an example (pages 29-30) of a generator that produces a single password (e.g. "password") with a 50% chance, and a high entropy password otherwise. The average entropy may be high, but there's still a 50% chance the password will be guessed immediately. Even so, extrapolating from the 1994 analysis, I believe it should still have well over 40 bits in the worst case.
2. The implementation isn't actually Chrome's, but is taken from the APG program, with minor modifications for compatibility
3. Testing with apg
reveals that single letter syllables actually occur in about 33% of passwords, but 70-75% of those only have a single letter syllable at the end.