Edit
I'm bumping this one since I still haven't got a conclusive answer (one or two are close though). What I'm looking for is basically a yes or no answer with some info to back it up.
We've got a system storing user passwords encrypted by a generic system key in the database. That could be catastrophic (obviously) if someone with DB access got a hold of that system key.
The correct way we now know (according to most(?)) is to store the salted hash of of the PW in the DB, but being relatively close to a release we'd like to minimize the code change and therefore thought a very simple way to prevent someone reading out PW's from the DB would be to simply reverse the process and switch the parameters.
That is, we'll encrypt a per system (hundreds of them) unique salted string (with a per encryption added random tail) using the users password as a key, storing the result in the DB. At PW verification we'll de-crypt the string stored in the DB with the entered PW and match with the system key for verification.
System key+random
encrypt withpassword
store in DBencrypted key
.
I.e. the users passwords are never stored, and in our simple minds are irretrievable.
But being noobs in the encryption sector we wonder if someone with more experience in the area could answer the simple question -
Is it possible to figure out the key from the original and the encrypted string?
We think this a brilliant ;) way to ensure user passwords from being compromised, but can't find anything on the method online. This makes us unsure about it, hence asking this great community.
(And brute force is not a adequate answer, since that (under the circumstances) is impossible to protect from.)
Edit:
I'll paste one of my comments here to (hopefully) make some things clearer:
@zaph Thanks for your input, but I think most are missing the point here. We have a code-freeze in a few days for an upcoming release, and I've already implemented the method I've mentioned in the question. Until next release, I'll read up on the subject and implement a third party library like scrypt or similar. I really just need to know if there are existing viable algorithms for reverse the process and thus making my new implementation worse than the old encrypted password approach.
With AES, or any serious encryption algorithm, even if you have the encrypted data (the ciphertext) and the original message (the plaintext), you are no closer to finding the encryption key. This is known as a known-plaintext attack, and AES is resistant to known-plaintext attacks as it should be.
It's that simple — without your key, you might as well not own any cryptocurrency or be part of any blockchain. As you can imagine, then, losing a key is a pretty big deal. Worse still is the possibility of having your key stolen, allowing a hacker access to your private information and possibly large amounts of money.
Sorry for jumping into the bounty in the last hours, but I have some important thoughts to contribute.
First of all, I didn't see any reference to OWASP here. They are probably the biggest software security community and you should always check their recommendations, not only for password protection but any other security subject. Every year they release a document called "OWASP Top 10", listing the most common web application vulnerabilities.
Based on last year's OWASP Top 10, the risk you are trying to mitigate is the number #3 in the list, called "Sensitive Data Exposure". It applies not only to passwords, but sensitive data like credit card number, for instance. For the problem described in your question, I would like to highlight the third attack scenario example:
Scenario #3: The password database uses unsalted or simple hashes to store everyone's passwords. A file upload flaw allows an attacker to retrieve the password database. All the unsalted hashes can be exposed with a rainbow table of pre-calculated hashes. Hashes generated by simple or fast hash functions may be cracked by GPUs, even if they were salted.
To prevent this kind of attack (sometimes called "rainbow attack"), these are OWASP's suggestions:
- Classify data processed, stored, or transmitted by an application. Identify which data is sensitive according to privacy laws, regulatory requirements, or business needs.
- Apply controls as per the classification.
- Don’t store sensitive data unnecessarily. Discard it as soon as possible or use PCI DSS compliant tokenization or even truncation. Data that is not retained cannot be stolen.
- Make sure to encrypt all sensitive data at rest.
- Ensure up-to-date and strong standard algorithms, protocols, and keys are in place; use proper key management.
- Encrypt all data in transit with secure protocols such as TLS with perfect forward secrecy (PFS) ciphers, cipher prioritization by the server, and secure parameters. Enforce encryption using directives like HTTP Strict Transport Security (HSTS).
- Disable caching for responses that contain sensitive data.
- Store passwords using strong adaptive and salted hashing functions with a work factor (delay factor), such as Argon2, scrypt, bcrypt, or PBKDF2.
- Verify independently the effectiveness of configuration and settings.
They are all equality important, but for your use case, take a special look at #8 and the links I included up there. In summary, you need a strong adaptive and salted hashing function with a work factor.
Also, don't forget to periodically run penetration tests (pen tests) against your production environment. This is VERY important.
If you want to start testing/validating your rainbow attack defenses, OWASP provides a tool called "OWASP Rainbow Maker".
OWASP Rainbow Maker is a tool aimed to break hash signatures. It allows testers to insert a hash value and possible keywords and values that might used by the application to create it, then it tried multiple combinations to find the format used to generate the hash value.
I hope it helps and if you have any question, shoot at the comments.
We've got a system storing user passwords encrypted by a generic system key in the database.
That's a VERY bad practice, as the password is potentially reversible. According to my experience - it is only matter of time until data are leaked and .. your potentially catastrophic scenario will come true.
The correct way we now know (according to most(?)) is to store the salted hash of of the PW in the DB,
The best option today is using "slow hashing", see https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords/31846#31846
At PW verification we'll de-crypt the string stored in the DB with the entered PW and match with the system key for verification.
And there's the problem. Once the system key is leaked (or used by an insider), all the passwords are potentially compromised. Using hash is much more safe (and the difference in code should not be so big).
Is it possible to figure out the key from the original and the encrypted string?
Using any current modern cipher it is currently not possible to compute / guess the encryption key based on knowledge of the plain and encrypted value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With