Password hashing inquiry [closed] - security

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
I saw this https://youtu.be/8ZtInClXe1Q video today and it got me thinking.
If salted hashing implementation looks like this:
To Store a Password
Generate a long random salt using a CSPRNG.
Prepend the salt to the password and hash it with a standard password hashing function like Argon2, bcrypt, scrypt, or PBKDF2.
Save both the salt and the hash in the user's database record.
To Validate a Password
Retrieve the user's salt and hash from the database.
Prepend the salt to the given password and hash it using the same hash function.
Compare the hash of the given password with the hash from the database. If they match, the password is correct. Otherwise, the password is incorrect.
Basically u are storing the salt right there with a hashed password. If someone has inside access to this data table cant they reverse engineer the password the same way that it is validated?

No. Hash functions are designed to be one-way. You can't use the salt to reverse a hash.
Using different salts for different entries is a defence against rainbow tables.

Related

What's the format of this password value? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
What is the format/hash type that is used, to generate a value for a password, like this:
1000:Z7yApDhypjU88p8cTU3SLRGqW6cZXtbv:oThRlVGlTNMggciquvhXn6jjvnaoRfFM
I only know that runs behing an asp.net webapi app on Azure.
(If this is a real hash, please consider obfuscating/"generic-alizing" them in the future)
Do you have more than one sample, such that you can tell if the format and length:
([integer (user id? rounds?)]:[32 bytes]:[32 bytes])
... is exact and consistent?
If so, it doesn't directly match (including length) any of the example hashes on the hashcat wiki:
https://hashcat.net/wiki/doku.php?id=example_hashes
I tentatively conclude that it's either a custom format, or indirectly related somehow to the Azure AD password hash sync format:
The password hash synchronization agent expands the 16-byte binary password hash to 64 bytes by first converting the hash to a 32-byte
hexadecimal string, then converting this string back into binary with
UTF-16 encoding.
The password hash synchronization agent adds a salt, consisting of a 10-byte length salt, to the 64-byte binary to further protect the
original hash.
The password hash synchronization agent then combines the MD4 hash plus salt, and inputs it into the PBKDF2 function. 1000 iterations of
the HMAC-SHA256 keyed hashing algorithm is used.
The password hash synchronization agent takes the resulting 32-byte hash, concatenates both the salt and the number of SHA256 iterations
to it (for use by Azure AD), then transmits the string from Azure AD
Connect to Azure AD over SSL.
So the '1000' at the beginning might be the number of rounds. It's a wild guess, though.

Does a salt have to be random? [duplicate]

This question already has answers here:
Non-random salt for password hashes
(9 answers)
Salt Generation and open source software
(6 answers)
Closed 9 years ago.
I dont understand why the salt has to be randomly generated instead of just unique. For example, if you have a table with a user_id column (which is unique) couldnt you just tack that on to the password for the salt?
Jean-Bernard Pellerin is correct and this is a duplicate of https://stackoverflow.com/a/536756/516813 . I couldnt find that in the search and I am closing the question. FYI, that answer shows that the main requirement IS uniqueness.
User IDs are unlikely to be long enough to stop good rainbow tables
The salt should change whenever the password changes.
(to prevent attackers from knowing whether a user changed the password back to an earlier password)
Yes, you could, but that would weaken the power of the salt. Good salts are long and difficult to guess. Good random numbers meet these criteria, which is why they are used.

Double MD5 hash as SALT? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Secure hash and salt for PHP passwords
Alright so im thinking of double hashing passwords with md5 (example hashing the password and then hashing the hash of the password). I want to know if anyone ever experienced any problems with this method and if you think its a good way to salt something. Thanks
I disrecommend hashing twice.
You might lose some password hashes, making your code even more insecure. It won't help with security.
The best way is to add salt to password and hash once!
The purpose of the salt is to make it more difficult to brute-force short passwords with pre-computed tables. You can make the salt user dependent.
MD5 is cracked. No matter how many times you rehash the hash, it adds absolutely no more security.
No it is not a good way to salt something.
Salting a password means adding extra data to the original password and then hashing the result.
You should generate a salt of at least 256 bits with a cryptographic random number generator, add that to your original password and then use a hash that has not been cracked, aka SHA-512.
MD5 is broken - so go far a SHA2 hashing. Hashing can be improved with salting and hashing in an iteration - which will secure you from dictionary and rainbow table attacks.
First, MD5 is significantly broken - Do Not Use, consider something like SHA-256 instead.
Second, salting is something quite different - having a hash(hash(password)) will not give you any security increase. See this for a further discussion: Secure hash and salt for PHP passwords

Storing Passwords Hashed in Database [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
Today I came up with a question about the web application conventions.
For the sake of security, if we store passwords of our users, most probably we are encrypting it (with MD5, SHA-1 etc.) and storing digested-hash in order to make them difficult or impossible to reverse.
Today there are many Rainbow Tables that are lookup tables of usual A-Za-z0-9 sequences up to 6 chars or widely used passwords. Let's say you are MD5-ing the user password once and storing the hash as password in database and someday hackers pwned your database and now they have many md5 hashes and e-mail addresses. Surely they'll look up passwords and when they got a preindexed match, they will try to login to that user's e-mail account.
Here this can be easily solved by digesting the message twice or simply reversing it. However I am wondering about what is the convention about this problem and how (as far as you know) enterprise applications or giants (Facebook, Google) solve this?
You use what is called a salt. Prepend some string that you make up before hashing. Prepend it also when you are checking the password. This is an application-wide string. This makes it much harder to look up via a rainbow table.
So if your salt is "kdi37s!!" save this in the db md5(kdi37s!!P#$$w3rd) and do the same when checking.
Use a little bit of salt and make a hash using sha1 or so.
Check out PBKDF2, it is one of the correct way to do it.
If you use an algorithm like BCrypt and salt (which uses the blowfish block cipher), it makes your db pretty safe against brute force attacks. Naturally, you want to require that your users have a reasonable amount of complexity in their password, if a user's password is a its not going to take long to guess it.
If an attacker gets a copy of your db, only being able to try 10 or so passwords a second will mean it will take a real long time to gain any passwords. If you are worried about Moore's law and would like to future proof this, you can specify a cost and make the algorithm even slower.
The trouble with a pure SHA/X or MD5 password hash is that by-design these algorithms are very fast, this makes it very sensitive to brute force attacks. Of course if you don't salt your hashes there are tons of rainbow tables that make cracking all the passwords in your db trivial.

Encrypting/Hashing plain text passwords in database [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed last year.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
Improve this question
I've inherited a web app that I've just discovered stores over 300,000 usernames/passwords in plain text in a SQL Server database. I realize that this is a Very Bad Thing™.
Knowing that I'll have to update the login and password update processes to encrypt/decrypt, and with the smallest impact on the rest of the system, what would you recommend as the best way to remove the plain text passwords from the database?
Any help is appreciated.
Edit: Sorry if I was unclear, I meant to ask what would be your procedure to encrypt/hash the passwords, not specific encryption/hashing methods.
Should I just:
Make a backup of the DB
Update login/update password code
After hours, go through all records in the users table hashing the password and replacing each one
Test to ensure users can still login/update passwords
I guess my concern is more from the sheer number of users so I want to make sure I'm doing this correctly.
EDIT (2016): use Argon2, scrypt, bcrypt, or PBKDF2, in that order of preference. Use as large a slowdown factor as is feasible for your situation. Use a vetted existing implementation. Make sure you use a proper salt (although the libraries you're using should be making sure of this for you).
When you hash the passwords use DO NOT USE PLAIN MD5.
Use PBKDF2, which basically means using a random salt to prevent rainbow table attacks, and iterating (re-hashing) enough times to slow the hashing down - not so much that your application takes too long, but enough that an attacker brute-forcing a large number of different password will notice
From the document:
Iterate at least 1000 times, preferably more - time your implementation to see how many iterations are feasible for you.
8 bytes (64 bits) of salt are sufficient, and the random doesn't need to be secure (the salt is unencrypted, we're not worried someone will guess it).
A good way to apply the salt when hashing is to use HMAC with your favorite hash algorithm, using the password as the HMAC key and the salt as the text to hash (see this section of the document).
Example implementation in Python, using SHA-256 as the secure hash:
EDIT: as mentioned by Eli Collins this is not a PBKDF2 implementation. You should prefer implementations which stick to the standard, such as PassLib.
from hashlib import sha256
from hmac import HMAC
import random
def random_bytes(num_bytes):
return "".join(chr(random.randrange(256)) for i in xrange(num_bytes))
def pbkdf_sha256(password, salt, iterations):
result = password
for i in xrange(iterations):
result = HMAC(result, salt, sha256).digest() # use HMAC to apply the salt
return result
NUM_ITERATIONS = 5000
def hash_password(plain_password):
salt = random_bytes(8) # 64 bits
hashed_password = pbkdf_sha256(plain_password, salt, NUM_ITERATIONS)
# return the salt and hashed password, encoded in base64 and split with ","
return salt.encode("base64").strip() + "," + hashed_password.encode("base64").strip()
def check_password(saved_password_entry, plain_password):
salt, hashed_password = saved_password_entry.split(",")
salt = salt.decode("base64")
hashed_password = hashed_password.decode("base64")
return hashed_password == pbkdf_sha256(plain_password, salt, NUM_ITERATIONS)
password_entry = hash_password("mysecret")
print password_entry # will print, for example: 8Y1ZO8Y1pi4=,r7Acg5iRiZ/x4QwFLhPMjASESxesoIcdJRSDkqWYfaA=
check_password(password_entry, "mysecret") # returns True
The basic strategy is to use a key derivation function to "hash" the password with some salt. The salt and the hash result are stored in the database. When a user inputs a password, the salt and their input are hashed in the same way and compared to the stored value. If they match, the user is authenticated.
The devil is in the details. First, a lot depends on the hash algorithm that is chosen. A key derivation algorithm like PBKDF2, based on a hash-based message authentication code, makes it "computationally infeasible" to find an input (in this case, a password) that will produce a given output (what an attacker has found in the database).
A pre-computed dictionary attack uses pre-computed index, or dictionary, from hash outputs to passwords. Hashing is slow (or it's supposed to be, anyway), so the attacker hashes all of the likely passwords once, and stores the result indexed in such a way that given a hash, he can lookup a corresponding password. This is a classic tradeoff of space for time. Since password lists can be huge, there are ways to tune the tradeoff (like rainbow tables), so that an attacker can give up a little speed to save a lot of space.
Pre-computation attacks are thwarted by using "cryptographic salt". This is some data that is hashed with the password. It doesn't need to be a secret, it just needs to be unpredictable for a given password. For each value of salt, an attacker would need a new dictionary. If you use one byte of salt, an attacker needs 256 copies of their dictionary, each generated with a different salt. First, he'd use the salt to lookup the correct dictionary, then he'd use the hash output to look up a usable password. But what if you add 4 bytes? Now he needs 4 billion copies of the the dictionary. By using a large enough salt, a dictionary attack is precluded. In practice, 8 to 16 bytes of data from a cryptographic quality random number generator makes a good salt.
With pre-computation off the table, an attacker has compute the hash on each attempt. How long it takes to find a password now depends entirely on how long it takes to hash a candidate. This time is increased by iteration of the hash function. The number iterations is generally a parameter of the key derivation function; today, a lot of mobile devices use 10,000 to 20,000 iterations, while a server might use 100,000 or more. (The bcrypt algorithm uses the term "cost factor", which is a logarithmic measure of the time required.)
I would imagine you will have to add a column to the database for the encrypted password then run a batch job over all records which gets the current password, encrypts it (as others have mentiond a hash like md5 is pretty standard edit: but should not be used on its own - see other answers for good discussions), stores it in the new column and checks it all happened smoothly.
Then you will need to update your front-end to hash the user-entered password at login time and verify that vs the stored hash, rather than checking plaintext-vs-plaintext.
It would seem prudent to me to leave both columns in place for a little while to ensure that nothing hinky has gone on, before eventually removing the plaintext passwords all-together.
Don't forget also that anytime the password is acessed the code will have to change, such as password change / reminder requests. You will of course lose the ability to email out forgotten passwords, but this is no bad thing. You will have to use a password reset system instead.
Edit:
One final point, you might want to consider avoiding the error I made on my first attempt at a test-bed secure login website:
When processing the user password, consider where the hashing takes place. In my case the hash was calculated by the PHP code running on the webserver, but the password was transmitted to the page from the user's machine in plaintext! This was ok(ish) in the environment I was working in, as it was inside an https system anyway (uni network). But, in the real world I imagine you would want to hash the password before it leaves the user system, using javascript etc. and then transmit the hash to your site.
Follow Xan's advice of keeping the current password column around for a while so if things go bad, you can rollback quick-n-easy.
As far as encrypting your passwords:
use a salt
use a hash algorithm that's meant for passwords (ie., - it's slow)
See Thomas Ptacek's Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes for some details.
I think you should do the following:
Create a new column called HASHED_PASSWORD or something similar.
Modify your code so that it checks for both columns.
Gradually migrate passwords from the non-hashed table to the hashed one. For example, when a user logs in, migrate his or her password automatically to the hashed column and remove the unhashed version. All newly registered users will have hashed passwords.
After hours, you can run a script which migrates n users a time
When you have no more unhashed passwords left, you can remove your old password column (you may not be able to do so, depends on the database you are using). Also, you can remove the code to handle the old passwords.
You're done!
As the others mentioned, you don't want to decrypt if you can help it. Standard best practice is to encrypt using a one-way hash, and then when the user logs in hash their password to compare it.
Otherwise you'll have to use a strong encryption to encrypt and then decrypt. I'd only recommend this if the political reasons are strong (for example, your users are used to being able to call the help desk to retrieve their password, and you have strong pressure from the top not to change that). In that case, I'd start with encryption and then start building a business case to move to hashing.
For authentication purposes you should avoid storing the passwords using reversible encryption, i.e. you should only store the password hash and check the hash of the user-supplied password against the hash you have stored. However, that approach has a drawback: it's vulnerable to rainbow table attacks, should an attacker get hold of your password store database.
What you should do is store the hashes of a pre-chosen (and secret) salt value + the password. I.e., concatenate the salt and the password, hash the result, and store this hash. When authenticating, do the same - concatenate your salt value and the user-supplied password, hash, then check for equality. This makes rainbow table attacks unfeasible.
Of course, if the user send passwords across the network (for example, if you're working on a web or client-server application), then you should not send the password in clear text across, so instead of storing hash(salt + password) you should store and check against hash(salt + hash(password)), and have your client pre-hash the user-supplied password and send that one across the network. This protects your user's password as well, should the user (as many do) re-use the same password for multiple purposes.
Encrypt using something like MD5, encode it as a hex string
You need a salt; in your case, the username can be used as the salt (it has to be unique, the username should be the most unique value available ;-)
use the old password field to store the MD5, but tag the MD5 (i.e.g "MD5:687A878....") so that old (plain text) and new (MD5) passwords can co-exist
change the login procedure to verify against the MD5 if there is an MD5, and against the plain password otherwise
change the "change password" and "new user" functions to create MD5'ed passwords only
now you can run the conversion batch job, which might take as long as needed
after the conversion has been run, remove the legacy-support
Step 1: Add encrypted field to database
Step 2: Change code so that when password is changed, it updates both fields but logging in still uses old field.
Step 3: Run script to populate all the new fields.
Step 4: Change code so that logging in uses new field and changing passwords stops updating old field.
Step 5: Remove unencrypted passwords from database.
This should allow you to accomplish the changeover without interruption to the end user.
Also:
Something I would do is name the new database field something that is completely unrelated to password like "LastSessionID" or something similarly boring. Then instead of removing the password field, just populate with hashes of random data. Then, if your database ever gets compromised, they can spend all the time they want trying to decrypt the "password" field.
This may not actually accomplish anything, but it's fun thinking about someone sitting there trying to figure out worthless information
As with all security decisions, there are tradeoffs. If you hash the password, which is probably your easiest move, you can't offer a password retrieval function that returns the original password, nor can your staff look up a person's password in order to access their account.
You can use symmetric encryption, which has its own security drawbacks. (If your server is compromised, the symmetric encryption key may be compromised also).
You can use public-key encryption, and run password retrieval/customer service on a separate machine which stores the private key in isolation from the web application. This is the most secure, but requires a two-machine architecture, and probably a firewall in between.
MD5 and SHA1 have shown a bit of weakness (two words can result in the same hash) so using SHA256-SHA512 / iterative hashes is recommended to hash the password.
I would write a small program in the language that the application is written in that goes and generates a random salt that is unique for each user and a hash of the password. The reason I tend to use the same language as the verification is that different crypto libraries can do things slightly differently (i.e. padding) so using the same library to generate the hash and verify it eliminates that risk. This application could also then verify the login after the table has been updated if you want as it knows the plain text password still.
Don't use MD5/SHA1
Generate a good random salt (many crypto libraries have a salt generator)
An iterative hash algorithm as orip recommended
Ensure that the passwords are not transmitted in plain text over the wire
I would like to suggest one improvement to the great python example posted by Orip. I would redefine the random_bytes function to be:
def random_bytes(num_bytes):
return os.urandom(num_bytes)
Of course, you would have to import the os module. The os.urandom function provides a random sequence of bytes that can be safely used in cryptographic applications. See the reference help of this function for further details.
To hash the password you can use the HashBytes function. Returns a varbinary, so you'd have to create a new column and then delete the old varchar one.
Like
ALTER TABLE users ADD COLUMN hashedPassword varbinary(max);
ALTER TABLE users ADD COLUMN salt char(10);
--Generate random salts and update the column, after that
UPDATE users SET hashedPassword = HashBytes('SHA1',salt + '|' + password);
Then you modify the code to validate the password, using a query like
SELECT count(*) from users WHERE hashedPassword =
HashBytes('SHA1',salt + '|' + <password>)
where <password> is the value entered by the user.
I'm not a security expert, but i htink the current recommendation is to use bcrypt/blowfish or a SHA-2 variant, not MD5 / SHA1.
Probably you need to think in terms of a full security audit, too

Resources