How secure is this hash-based personal password scheme?
SHA-512
PROS:
- Due to the avalanche effect, every single modification to the suffix will change the SHA512 sum entirely. This means that from one N first letters of one hash you can't say anything about the N first letters of another hash, making your passwords quite independent.
- SHA512 is a one-way compression function, so you can't deduce the password from the hash; you could try brute-force passwords that will give the same SHA512 sum. As you only use part of the hash, there's more chances to find more than one password that will match.
CONS:
- You think you have a strong password as it is 12 characters long and contains both letters and numbers, but it actually has a very limited character set of
0-9
+a-f
(it's a hexadecimal number). This gives only16^12
i.e.log2(16^12)=48
bits of entropy, which is less than 10 characters ofa-z
+0-9
and close to 8 characters ofa-z
+A-Z
+0-9
. - Online services could save the hashes you create. Use a local tool for the hashing, instead.
- It's possible you can't recall your seed in all cases, which may lead you to lose your password.
- What happens if you want or are required to change a password? Does the seed become
my_p4SSWord!Sitename2
or something else? How you keep track of the count? - The site/service name is not always unambiguous. Was your Gmail password suffix
Google
orGmail
or did you first useYouTube
? Was your Microsoft accountMicrosoft
orLive
orOffice365
? - Combinations of these makes things even uglier.
- What happens if you want or are required to change a password? Does the seed become
- If the site has password complexity requirements, you'd had to add characters and/or convert some of the characters uppercase manually after the hashing. How to keep track of these modifications?
- Someone could still find out your procedure e.g. by seeing you create/use a single password. That would compromise all your passwords at once.
bcrypt
While bcrypt would
- give more entropy usings Radix-64 encoding with 64 characters;
ASCII 32(space) through 95
_
(!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
) - be slower to calculate
- use a user defined iteration count you could utilize to make it as slow as you wish
...it's incompatible with your current procedure, as it has incorporated salting and would give you a different hash every time:
$ htpasswd -nbBC 12 Elling my_p4SSWord\!Sitename
Elling:$2y$12$jTkZQqYzWueA5EwKU1lLT.jbLLXUX.7BemHol.Q4SXhoJyeCVhcri
Elling:$2y$12$c1lDwR3W3e7xlt6P0yCe/OzmZ.ocKct3A6Fmpl8FynfA.fDS16bAa
Elling:$2y$12$eAciSW6iGxw/RJ7foywZgeAb0OcnH9a.2IOPglGGk.wL9RkEl/Gwm
Elling:$2y$12$EU/UDJaZYvBy6Weze..6RuwIjc4lOHYL5BZa4RoD9P77qwZljUp22
...unless you exclusively specify a static salt (possible on some implementations like PyPI bcrypt).
Password managers
All the cons are solved in a password manager creating passwords that are
- random
- completely unrelated
- can have different requirements (different character sets and minimum/maximum lengths).
From a usability standpoint, it's awful. You need to generate a hash each time you want to log in. Even using a password manager to look up truly random strings would be less work.
From a security perspective, you have combined the problems of hashing client-side and using a password pattern:
Yes, using a password hash on the client-side means that your plaintext password is protected from function weaknesses on the server-side. But if you have a compromise on the client-side, this does no good.
It does not survive Kerckhoffs's principle. If an attacker knows that this is your process, then your password for any given service is only
my_p4SSWord!
. Once I know that, I can log into every one of your accounts. Re-using the pattern exposes all your passwords once one is known.
One of the main purposes of your scheme is to prevent access to all of your accounts if one password is compromised. While it's better than simple password reuse, it is still easily bypassed by an attacker and imho doesn't add enough value to justify the added complexity.
As you mention that you want to focus on the cryptographic properties:
sha512 is an awfully quick function and not suitible as a cryptographic hash function for password storage.
Truncating the hash has no relevance when trying to gain your key from a leaked password[*]. It increases collisions, but an attacker would want the correct key (my_p4SSWord!
), not just any input that produces the hash.
So if we assume that your approach is known to an attacker[**], and that they were able to compromise a plaintext password on just one website[***], they can now likely crack sha512([key_guess]compromisedwebsite)
in a reasonable amount of time and gain access to all your accounts on other websites.
the tool I was linking to is JavaScript only, and thus client-side only
Have you verified this? Do you verify every time that no changes have been made (either by the owner, or because the site or one of the JS dependencies have been compromised)?
Personally, if you need a third-party dependency for your password scheme anyways, I would rather trust an online password manager (or it it's feasible usability-wise, an offline password manager) which was specifically designed to keep passwords secure.
[*] it does have relevance when an attacker only has access to a hashed version of the password and needs to crack that first, so I would skip the truncating as it seems unnecessary.
[**] Which it now is :)
[***] Maybe they set up a fake website you registered on, maybe you registered on a site that stores/logs/sends passwords in plaintext, maybe the attacker has an RCE on a site you registered and logs all passwords as they are entered