Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change the way how you calculate passphrase entropy #782

Open
MooseExplorer637 opened this issue May 19, 2024 · 5 comments
Open

Change the way how you calculate passphrase entropy #782

MooseExplorer637 opened this issue May 19, 2024 · 5 comments

Comments

@MooseExplorer637
Copy link

You should fix the way how you calculate passphrase entropy since the current model calculates it wrong and could make the user choose an extremely weak passphrase since even a two-word passphrase such as headrest-vagabond has a calculated entropy of 99.6 bits (calculated without Zxcvbn, which is a separate issue and I won't go into that here) which is highly incorrect. The correct number would be 25.8, which is nowhere near secure enough. You cannot calculate passphrase entropy in an identical way to password entropy, where the relevant information is the length and all the possible characters. Instead, the relevant information should be the wordlist and the number of words used. From other KeePass clients, at least KeePassXC has done this right.

So, here is an example of how to calculate this:
4-word passphrase using EFF Large wordlist containing 7776 words has an entropy of Log₂(7776⁴) = 51.7 bits.

@strongbox-mark
Copy link
Member

KeePassXC uses the zxcvbn algorithm which you can also choose to use in Strongbox. It is the default. Using zxcvbn Strongbox calculates the password entropy as 39.1 bits the same as KeePassXC.

If you switch the algorithm in Strongbox to "Basic (Pooled Entropy)" you will get the higher entropy.

We offer both modes, but default to zxcvbn because it does better at recognizing passphrases, but it's not the easiest thing in the world to do this. So let's look into that for second:

You mention that the correct way to do this is:

  1. Determine the wordlist used
  2. Determine the number of words used from the word list

Some problems:

  • Our input is a random string, we have no idea where it came from or what it is. Is it a password or passphrase, how can we tell?
  • What's the separator? Dash or dot, or space, or perhaps none? Could it be 2 or 3 dashes? or a random character?
  • What about numbers interspersed? or "hackified"? What about a prefix or suffix?
  • Now, say we are able to somehow break the string up into "Words" we have to find out a list that this comes from...
  • What is the list? What are the possible lists? Should we just consider well known Diceware ones? Or perhaps a dictionary? Only in English? How about simple number substitutions, like 1 for i or 0 for O?

If you have a nice easy algorithm you can point me at, that does 1 or 2, or addresses the above problems, I'll be super happy to consider it. Zxcvbn is the algo that I know that tries to tackle some of these problems and give us a realistic estimate. By default Strongbox uses the Zxcvbn algo.

There's an exception here in that if Strongbox is generating a passphrase based on a known wordlist we could offer a better than zxcvbn estimation at the time of generation (not afterwards because the context is lost). That's an interesting feature request you could make, if you wanted.

But I'd ask you to request something like that in a much more polite/respectful way than what you've posted above. Thanks.

@MooseExplorer637
Copy link
Author

MooseExplorer637 commented May 23, 2024

First, I would like to apologize if my post offended you in any way. That wasn’t my intention, and now I realize I could have given this feedback more constructively.

The problem with zxcvbn is that it tries to estimate the entropy after the password or passphrase has been generated, based on certain characteristics of that password. Now, if we know all the characters or the wordlist that we use for generating the password or passphrase, and we know how many characters/words it uses, then the entropy will always remain the same, which is why I prefer the ”Pooled Entropy” option. However, in its current form, this has some issues when calculating the entropy for passphrases, as I mentioned in my previous post.

If I could decide, I would choose the Pooled Entropy as your default option when generating passwords and then find a way to calculate the entropy correctly for passphrases. The last time I checked with KeePassXC, it indeed used zxcvbn for estimating password entropy, but passphrases it calculated correctly, so the entropy didn’t change for each passphrase even though the words were different. To specify, I was using its password generator here, so not calculating entropy for passwords/passphrases that have been generated outside of KeePass and just imported there. I think this could also be possible for Strongbox because you can choose the wordlist for your passphrases, so we should know which wordlist has been used. The simple separator shouldn’t affect the entropy. However, adding all the other changes makes the calculation more complex and is beyond my knowledge. 

I also think Strongbox shouldn’t try to calculate the password entropy for passwords that haven’t been generated by Strongbox because we don’t know the process of how they were generated. We don’t even know if it was a machine-generated or a human-generated password, which makes a big difference because human-generated passwords are inherently weak. As an example, Strongbox estimates with a zxcvbn that a password this-is-a-very-strong-password is strong with 70.6 bits of entropy when, in reality, the words used are very common and form a simple sentence that would probably be cracked rather quickly. This is why I think you could add a warning or state that calculating the entropy for already existing passwords is not possible since Strongbox doesn’t know the process of how they were generated.

@strongbox-mark
Copy link
Member

First, I would like to apologize if my post offended you in any way. That wasn’t my intention, and now I realize I could have given this feedback more constructively.

Cheers, appreciate that. :)

The problem with zxcvbn is that it tries to estimate the entropy after the password or passphrase has been generated, based on certain characteristics of that password.

Yes, that's what it's designed to do and it's pretty good at what it does.

However, in its current form, this has some issues when calculating the entropy for passphrases, as I mentioned in my previous post.

Right, pooled entropy is a simpler algo not designed to know if a string is a passphrase or a password. Neither pooled entropy nor zxcvbn are designed to take the set of {passphrase, wordlist used, number of words, separator, salt, etc} and provide entropy. I don't think there are many password managers that do this? Do you know of any?

The current algos are designed to take a single param, the string (passphrase or password).

The last time I checked with KeePassXC, it indeed used zxcvbn for estimating password entropy, but passphrases it calculated correctly, so the entropy didn’t change for each passphrase even though the words were different.

We're both using the same zxcvbn algo, so you should see the same entropy, if that's not the case though it might be interesting.

I also think Strongbox shouldn’t try to calculate the password entropy for passwords that haven’t been generated by Strongbox because we don’t know the process of how they were generated.

I think most people expect this, and I don't know of any password manager that doesn't calculate an entropy score for passwords not generated by it's generator. I believe all of them operate on a simple string of characters using pooled entropy or zxcvbn. Another issue is that we don't store the wordlist used or the algorithm used in the database, so once it's generated and saved, that's it, that info is lost.

We don’t even know if it was a machine-generated or a human-generated password, which makes a big difference because human-generated passwords are inherently weak.

That's not necessarily so though right, some sophisticated users will generate fairly decent passwords using phrases that they know, with 6 or 7 random words, and then tack on a numeric salt or whatever. You don't need a machine to do this for you.

As an example, Strongbox estimates with a zxcvbn that a password this-is-a-very-strong-password is strong with 70.6 bits of entropy when, in reality, the words used are very common and form a simple sentence that would probably be cracked rather quickly.

This is the correct entropy coming out of zxcvbn, any password manager using zxcvbn will give you this result, I'm sure you've checked it in KeePassXC.

So... I'm not sure what you would calculate here for the entropy? Like what algorithm would you use? What do you think and why, is a good measure for this passphrase? Diceware uses around 7000 common words, and as far as I know the correct entropy [1] for a 6 word passphrase using a standard Diceware dictionary is:

6 x log2(7776) = 6 x 12.9 bits = 77.4 bits

So, in fact zxcvbn has done an even better job here than a straightforward dedicated passphrase entropy calculator would.

Now I agree with you that there's a weakness in this password, because it is structured as a common english sentence, it has the grammar of a valid english sentence. So, if your attacker new this or had a cracking program that tried to format it's guesses as english sentences then they would have an edge.

But I think we're getting into a fairly sophisticated threat model here, and we would need a very sophisticated method/algo for determining actual password strength. You'd need to define that method/algo, I think probably a phd project in itself, and probably outside the scope of what we'd be capable of working on here.

Should you come up with that algo though, you'll have made a nice contribution to computer science and cryptography and I'd be happy to add that to our backlog for consideration and implementation.

Lastly, I do think we should mark 70 bits as weak to match KeePassXC's categorization, and I'll add that to our list to improve on in the next release or so.

[1] https://theworld.com/~reinhold/dicewarefaq.html#calculatingentropy

@MooseExplorer637
Copy link
Author

That's not necessarily so though right, some sophisticated users will generate fairly decent passwords using phrases that they know, with 6 or 7 random words, and then tack on a numeric salt or whatever. You don't need a machine to do this for you.

The problem with this is that most people who would pick the words they will use are gonna choose words that are part of their active vocabulary, which would be significantly fewer words than 7776 that a password manager could choose from.

This is the correct entropy coming out of zxcvbn, any password manager using zxcvbn will give you this result, I'm sure you've checked it in KeePassXC.

So... I'm not sure what you would calculate here for the entropy? Like what algorithm would you use? What do you think and why, is a good measure for this passphrase? Diceware uses around 7000 common words, and as far as I know the correct entropy [1] for a 6 word passphrase using a standard Diceware dictionary is:

6 x log2(7776) = 6 x 12.9 bits = 77.4 bits

So, in fact zxcvbn has done an even better job here than a straightforward dedicated passphrase entropy calculator would.

With this example, I was trying to demonstrate how zxcvbn can declare a human-generated password strong even though it isn't. And because it was human-generated, you can't calculate the correct entropy. People's active vocabulary would contain significantly fewer words, and therefore, the calculation doesn't work.

Also, just because zxcvbn usually gives a lower entropy score compared to pooled entropy doesn't mean that the entropy calculation is accurate. For example, if we are calculating entropy for passwords that Strongbox is generating, then the entropy estimation by zxcvbn will always be inaccurate.

But I think we're getting into a fairly sophisticated threat model here, and we would need a very sophisticated method/algo for determining actual password strength. You'd need to define that method/algo, I think probably a phd project in itself, and probably outside the scope of what we'd be capable of working on here.

I agree, and think that this is probably also outside the scope of my knowledge and therefore something that someone else could work with in the future.

Lastly, I do think we should mark 70 bits as weak to match KeePassXC's categorization, and I'll add that to our list to improve on in the next release or so.

I have to disagree here. A 70-bit entropy password is not weak if it's generated properly by a machine. 80 bits would be enough for practically anything, and 70 bits is not that much weaker. For example, Apple's default password entropy is 71, so calling 70 bits weak would be an inaccurate statement.

I would read the following sources about password strength that should demonstrate this point further. The 1Password blog post is very informative, and since their former Principal Security Architect wrote it, it has its facts straight.

https://blog.1password.com/how-long-should-my-passwords-be/
https://infosec.exchange/@epixoip/110309336934641249
https://fosstodon.org/@atoponce/111494995720555692

@acuteaangle
Copy link

acuteaangle commented Jun 5, 2024

I would like to add to this discussion. I came here to suggest the same feature, as I also use KeePassXC, which does display the theoretical entropy of the current generator settings for passphrases (but not character-based passwords).

For my use-case, like being able to quickly check the theoretical entropy of different length diceware passwords without using a separate calculator.

The KeePassXC passphrase generator takes only a wordlist, word count, fixed separator, and fixed case as input.
This allows it to compute theoretical passphrase entropy very easily, as $\log_2\mathopen{}\left(\text{wordlist size}^{\text{word count}}\right)\mathclose{} \text{bits}$.

The StrongBox case is much more complicated, however, as StrongBox supports automatically adding various types of salt to generated passphrases, which would technically need to be included in the calculation for it to be perfectly accurate.

KeePassXC also does not fallback to an estimated entropy or change it's entropy display in any way if the generated passphrase is manually edited. They discuss this decision in keepassxreboot/keepassxc#10176, with significant points for and against it.
They also discussed the decision to use zxcvbn over theoretical entropy for the character-based password generator in keepassxreboot/keepassxc#8011.

If StrongBox implemented this feature, my personal ideal implementation would be a toggle in Advanced settings that switched the entropy calculation to be based only on the generator settings, to avoid the UX issues of supporting and distinguishing between multiple methods at the same time, but I realize this is probably not going to happen.

I doubt it would be important enough to construct a formula that worked correctly with every option $$\log_2\mathopen{}\left(\text{wordlist size}^{\text{word count}}\right)\mathclose{} + (\text{random casing bool} * \text{word count}) +\ . . .$$, especially since l33tspeak would depend on the actual contents of the wordlist, the formula would take significant time doing maths to create, and it would restrict adding other features to the generator in the future.

The functionality only working with all the 'advanced' generator features turned off, or even ignoring them, using a simple $\log_2\mathopen{}\left(\text{wordlist size}^{\text{word count}}\right)\mathclose{} \text{bits}$, would work for my use case (and I'm assuming OP's too), but I don't know that StrongBox would want to add a feature that only works while using the bare minimum of the generator's functionality, especially considering that the simple case is also covered by opening the iOS calculator in landscape and typing [7][7][7][6] [xʸ] word_count [=] [ln] [÷] [2] [ln] [=], assuming you're using the default EFF Large wordlist with 7776 words. Or writing down the entropy of 5-12 EFF Long words in a note somewhere; here's a list generated with SageMath.

sage: for word_count in range(4, 21): print(f'{word_count:2} words: {log(7776**word_count, 2).n(digits=5)} b')
 4 words: 51.699 b
 5 words: 64.624 b
 6 words: 77.549 b
 7 words: 90.474 b
 8 words: 103.40 b
 9 words: 116.32 b
10 words: 129.25 b
11 words: 142.17 b
12 words: 155.10 b
13 words: 168.02 b
14 words: 180.95 b
15 words: 193.87 b
16 words: 206.80 b
17 words: 219.72 b
18 words: 232.65 b
19 words: 245.57 b
20 words: 258.50 b

P.S: A tool I love for this: https://passwordbits.com/passphrase-cracking-calculator/ and https://passwordbits.com/password-cracking-calculator/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants