I'm developing simple software that does aes256-cbc encryption of a file. I'm using GNU/Linux and libgcrypt-1.5.0. The IV is randomly generated with the OpenSSL rand function and the IV is stored before the ciphertext in the output file. I'm using the PKCS#7 padding method.
Now I am in doubt about how to proceed:
It is better to use sha256 repeated 50,000 times of the inputed password to encrypt the file, or it is better to use the password given by the user?
If I want to check the correctness of the inputed password, I have to store it into the encrypted file (obviously encrypted). Is it correct to do this?
Use PBKDF2 to derive a key as indiv suggested.
Use PBKDF2 with a different salt to derive an authentication key and append a MAC to your encrypted data (after encryption is more secure than before encryption). Verify the MAC in order to check whether the password is correct or not, and that the data has not been tampered with. If you are unsure when choosing a MAC, use HMAC with SHA-512 (assuming you are using AES-256 as per your question).
Instead of using PBKDF2 twice with different paddings, you can use a single invocation of PBKDF2 to generate both the encryption and the authentication keys at the same time, by generating a key of the combined size of your encryption key and authentication key in one go.
Note that depending on the padding for deciding whether the key was good can result in CBC padding oracle attacks. For file encryption such attacks might not be applicable, depending on the exact circumstances, but it seems prudent practice to use a proper MAC for data authentication anyway, since you also want to prevent bit flipping attacks and other malicious modifications to your data.
Neither choice is correct. You need to use an algorithm made for deriving a key from a password, like PBKDF2. See the function gcry_kdf_derive.
1.It is better to use sha256 repeated 50,000 times of the inputed password to encrypt the file, or it is better to use the password given by the user?
You never use the "raw" password directly as a key. The key needs to be strectched in something hardened against brute forcing attacks. Look at the String-to-Key (S2K) stuff, or a Password Based Key Derivation Function (PBKDF) with a memory-hard hash like scrypt.
2.If I want to check the correctness of the inputed password, I have to store it into the encrypted file (obviously encrypted). Is it correct to do this?
No. You use an authenticated encryption mode like GCM. Authenticated encryption modes are specially built for the task and provide both confidentiality and authenticity.
Under the password, the encrypted file will verify or it won't. Don't concern yourself with the reason why. Otherwise, you're setting up an oracle which may undo everything from Step 1 (which may or may not be applicable here).
Related
I have problem in encrypting my plain text in C.
I am able to write and read the file in C
Inside the text:
ID Promo Points Password Name
1 NONE 0 awdawdawd daw
Which in this case it just print password in plain text, Is it possible to encrypt the data any method, which shows like this:
ID Promo Points Password Name
1 NONE 0 ENCRYPTEDDATA daw
Of course the password wont be "ENCRYPTEDDATA", I just want it avoid plain text which user can easily see the file.
The reason I create file cause I need to read it from the file and make a login function.
My program itself able to decrypt the password when in request of checking id and password.
It can use any method only the program can encrypt and decrypt the data
Any solution guys?
If possible I also need to limit the encrypted text
You should hash password with strong hash function like SHA2 and store the hash in your file rather than storing it in plain
Hashing might be better in this case than encryption, as for encryption you will have to worry about storing key somewhere securely.
When your login function needs to validate incoming password, you can just hash incoming password and match it against the hashed password from you file
If you want to protect your login then you should use a password hash, also known as a Password Based Key Derivation Function. These functions are often, but not always, based on a secure hash. You should not use a cryptographic hash such as SHA-2 for this purposes.
Common password hashes are PBKDF2, bcrypt, scrypt and Argon2. Argon2 is the most advanced one as winner of the password hashing competition. A password hash differs from a normal hash in two important aspects:
it uses key strengthening techniques to make it harder for adversaries to use a dictionary or brute force attack (in the form of an iteration count or work factor and possibly additional memory / threading related parameters);
it uses a salt - stored with the password hash - to avoid rainbow table attacks and to avoid duplicate hash values - which would show that an identical password is being used.
So although Pras is right about not using encryption I would not recommend a secure hash unless you are sure that the password is large enough and unique. In general those restrictions can nor should be enforced on password based authentication systems.
I'm working on a website (PHP + MySQL) that I've got to upgrade. Passwords are stored in the database in MD5, and I'd like it to be something more secure, like SHA-256.
I've already red this question about "converting" password hashes, but I got an other idea, and I'd like to know if it brings a security problem or not.
Currently, the passwords are checked in php by hashing (in MD5) the given password and compare it with the hash stored in database, ie: if(md5($password) == $hash)
Let's assume that I hash all the MD5 hashes in SHA-256. I'd have the sha-256 hash of a md5 hash.
Side note: I know it's not more secure to rehash a hash, that's not the point of my question
When a user wants to connect, I'd just have to change the md5($pass) in hash('sha256', md5($password), false) to make it match the value stored in database (assuming $password is the right one)
It seemed a good idea to me as I don't need to keep track of the md5 hash after conversion, ad this doesn't need me to create any new column in my table. I know that this is not going to give me the SHA-256 hash of the original password stored with md5 hash, but this is not my goal. It's just to change the encryption method. Moreover, brute-forcing it seems inefficient, as it is very unlikely that dictionary would have hashes of words...
Does this way of doing it is flawed?
Simple hashing of passwords is insufficient, it is subject to rainbow tables and is to fast.
Instead in PHP use Safe Password Hashing: password_hash() and password_verify() or a comparable function such as PBKDF2, Bcrypt or script. These function are more secure because of two additions: a repetition count and a random salt. It's all about raising the work factor the attacker must perform.
After all, the point is to have a secure system. Just making it more inconvenient for an attacker is not the answer, there are hacking programs out there to take advantage of poor password security.
So from what I have seen it is impossible to decrypt any hashing algorithm such as MD5 or SHA-1 without brute forcing it or using rainbow tables. This seemed to confuse me on a few aspects of using hashes. These confusing points are:
What would be the point of hashing in the first place if they cant be decrypted?
How would hashed passwords be able to be used in a database?
Also since people say it is like the modulo operation, what, if anything, is preventing multiple inputs to equate to the same hash?
If somebody simply does SHA1 or MD5 on a password, then they get almost no protection.
That's why it's important to understand the right way to handle "password hashing". Please read Our password hashing has no clothes
To answer your questions:
You can verify the user without "decrypting the hash": you simply "hash" the user entered password (along with salt and other parameters) upon login and verify that it matches the expected result that is stored in the database.
See 1 and the Troy Hunt link
People who say it is like a modulo operation are making a bad analogy: they are non-experts on this subject. Anyway, the properties of the "hash" function make it hard to find collisions, and the salt prevents two users with the same password from having the same password "hashes" in the database.
Other resources:
Salted password hashing - Doing it right
Method to Protect Passwords in Databases for Web Applications -- advanced reading: solves other problems with current solutions to protecting passwords. If you wonder why I put "hash" in quotes above, this will explain it.
It's not like a modulo. A hash is reasonably guaranteed to be unique based on the input. If you enter your passwords in a database as hashes, then all you need to do is to hash the password entry and check it against what you have stored in the database. This way, you are not storing readable passwords in the database which are openly visible to others. Normally, you would have a private key, some salt and something unique like a timestamp included in your hashing algorithm to ensure that it cannot be easily spoofed.
This may help you further:
http://searchsqlserver.techtarget.com/definition/hashing
Even if the process of hashing is basically non decryptable, the problem as pointed before is that each hash is nearly unique, so that means using websites like md5decrypt which contains a lot of different words and their encrypted hashes, one may find the password he is looking for.
That is if the password isn't strong enough in the first place. Obviously one shouldn't use the password "password" for instance because it will probably be found in most of the websites like md5decrypt.
What you should do to protect passwords on your website is actually simple. First, don't use old hashes like md5 or sha1. Use at least sha256, and if you've enough sql storage, sha384 or sha512. You should know that most of the online hashes database are only about the most commonly used hashes (let's say md5,sha1,sha256 in most cases). So you should find a hash type that isn't very represented on online database.
Then you should (you have actually to) use salt when encrypt users passwords, that is add some word, letters, whatever, to the password before you encrypt it, then store that salt somewhere so you can still allow people to log in. You could also add a pepper to the salt to make the all thing stronger.
While using the salt, try to find a way that hackers won't think about, for instance double the salt, or triple it, or try different ways to concat the salt and the actual password, etc. You could also make a double encryption with double salt, like sha512(sha384()), which would be almost impossible to find.
But, please, do not store unencrypted passwords !
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it possible to decrypt md5 hashes?
In my website, I'm using md5 encryption for the password. So it's saving in the encrypted form in the database. For doing the password recovery, how can I decrypt the encrypted password ??
Please Help :)
As others described quite well, you cannot easily 'decrypt' an MD5 hash.
I guess the best way to do your password recovery is like this:
A user can request password recovery
by providing his email address (it should be unique so users can be identified by email address).
an email is sent to his address with a
link containing a unique hash (which
you have generated when sending the
email and saved it to the db).
when the link is clicked by the user (and
of course the unique hash is checked
to be equal with the one in the db)
you can show a form which lets them
choose a different password.
Another route that some people use is to simply ask for the email address, generate a new password and send it to the user. The problem with this one is that someone who knows only your email address can request a password change. He won't know the new pass, and you will get it by email, but still it is very inconvenient for the user.
MD5 is a hash-based encryption. What that means, is that there is no way to get back the original value. You have created something that is a "checksum" of the original data. You can use the MD5 algorithm to encrypt something else, and then compare that to the MD5'd version of the data, but you can never get back the original.
It would be similar to me saying: 5 + 3 + 2 = 10. The original data is 5, 3, and 2. But the "hash" is 10. There is no way to get the original data from the hash, but if someone supplies the correct input ( 5, 3, 2 ), I can hash it, and confirm that it matches hash that I have on file, 10.
I think MD5 is a one way hashing algorithm. What that means is that once you encrypt it, the data cannot be decrypted. (I'm sure a good hacker will disagree though)
Anyways, for passwords you can save the encrypted version of the password in the database. When a user attempts to log in, encrypt the entered password using the same MD5 algorithm, and compare the encrypted version of the password against the encrypted password stored in the database.
Once you're comfortable with this approach, you can start looking at the concept of adding salt to the hashed password.
Also, there are other hashing algorithms than just MD5. If you're using .NET, there's a bunch in the framework, such as SHA512Managed. Each one has its trade offs, such as speed to hash, security, etc. Pick one that fixes your particular problem.
You can't decrypt a md5 password! The only way would be to brute force it!
If you want to do password recovery make a random string witch will be sent to the user by email (or any other way) and set as a md5'd password... Just an idea
EDIT:
Why would you encrypt a password to keep it safe if you can decrypt it? Makes no sense! -> You could the basically leave the password unencrypted!
It's not easy, but you're best bet would be to use a rainbow table as the MD5 has does have vulnerabilities.
There are several online versions, which you may or may not be able to trust (or work).
You can try to search in a MD5 hash database like:
http://www.md5-hash.com/
http://www.md5decrypter.com/
others....
Chances are small but you can try.
What is your preferred method/datatype for storing passwords in a database (preferably SQL Server 2005). The way I have been doing it in several of our applications is to first use the .NET encryption libraries and then store them in the database as binary(16). Is this the preferred method or should I be using a different datatype or allocating more space than 16?
I store the salted hash equivalent of the password in the database and never the password itself, then always compare the hash to the generated one of what the user passed in.
It's too dangerous to ever store the literal password data anywhere. This makes recovery impossible, but when someone forgets or loses a password you can run through some checks and create a new password.
THE preferred method: never store passwords in your DB. Only hashes thereof. Add salt to taste.
I do the same thing you've described, except it is stored as a String. I Base64 encode the encrypted binary value. The amount of space to allocate depends on the encryption algorithm/cipher strength.
I think you are doing it right (given that you use a Salt).
store the hash of the salted-password, such as bcrypt(nounce+pwd). You may prefer bcrypt over SHA1 or MD5 because it can be tuned to be CPU-intensive, therefore making a brute force attack way longer.
add a captcha to the login form after a few login errors (to avoid brute-force attacks)
if your application has a "forgot my password" link, make sure it does not send the new password by email, but instead it should send a link to a (secured) page allowing the user to define a new password (possibly only after confirmation of some personal information, such as the user's birth date, for example). Also, if your application allows the user to define a new password, make sure you require the user to confirm the current password.
and obviously, secure the login form (typically with HTTPS) and the servers themselves
With these measures, your user's passwords will be fairly well protected against:
=> offline dictionary attacks
=> live dictionary attacks
=> denial of service attacks
=> all sorts of attacks!
Since the result of a hash function is a series of byte in the range 0 to 255 (or -128 to 127, depending the signed-ness of your 8-bit data type), storing it as a raw binary field makes the most sense, as it is the most compact representation and requires no additional encoding and decoding steps.
Some databases or drivers don't have great support for binary data types, or sometimes developers just aren't familiar enough with them to feel comfortable. In that case, using a binary-to-text encoding like Base-64 or Base-85, and storing the resulting text in a character field is acceptable.
The size of the field necessary is determined by the hash function that you use. MD5 always outputs 16 bytes, SHA-1 always outputs 20 bytes. Once you select a hash function, you are usually stuck with it, as changing requires a reset of all existing passwords. So, using a variable-size field doesn't buy you anything.
Regarding the "best" way to perform the hashing, I've tried to provide many answers to other SO questions on that topic:
Encrypting passwords
Encrypting passwords
Encrypting passwords in .NET
Salt
Salt: Secret or public?
Hash iterations
I use the sha hash of the username, a guid in the web config, and the password, stored as a varchar(40). If they want to brute force / dictionary they'll need to hack the web server for the guid as well. The username breaks creating a rainbow table across the whole database if they do find the password. If a user wants to change their username, I just reset the password at the same time.
System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(
username.ToLower().Trim(),
ConfigurationManager.AppSettings("salt"),
password
);
A simple hash of the password, or even (salt + password) is not generally adequate.
see:
http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes/
and
http://gom-jabbar.org/articles/2008/12/03/why-you-should-use-bcrypt-to-store-your-passwords
Both recommend the bcrypt algorithms. Free implementations can be found online for most popular languages.
You can use multiple hashes in your database, it just requires a little bit of extra effort. It's well worth it though if you think there's the remotest chance you'll need to support additional formats in the future. I'll often use password entries like
{hashId}${salt}${hashed password}
where "hashId" is just some number I use internally to recognize that, e.g., I'm using SHA1 with a specific hash pattern; "salt" is a base64-encoded random salt; and "hashed password" is a base64-encoded hash. If you need to migrate hashes you can intercept people with an old password format and make them change their password the next time they log in.
As others have mentioned you want to be careful with your hashes since it's easy to do something that's not really secure, e.g., H(salt,password) is far weaker than H(password,salt), but at the same time you want to balance the effort put into this with the value of the site content. I'll often use H(H(password,salt),password).
Finally, the cost of using base64-encoded passwords is modest when compared to the benefits of being able to use various tools that expect text data. Yeah, they should be more flexible, but are you ready to tell your boss that he can't use his favorite third party tool because you want to save a few bytes per record? :-)
Edited to add one other comment: if I suggested deliberately using an algorithm that burned even a 1/10th of a second hashing each password I would be lucky to just be laughed out of my boss's office. (Not so lucky? He would jot something down to discuss at my next annual review.) Burning that time isn't a problem when you have dozens, or even hundreds, of users. If you're pushing 100k users you'll usually have multiple people logging in at the same time. You need something fast and strong, not slow and strong. The "but what about the credit card information?" is disingenuous at best since stored credit card information shouldn't be anywhere near your regular database, and would be encrypted by the application anyway, not individual users.
If you are working with ASP.Net you can use the built in membership API.
It supports many types of storage options, inlcuding; one way hash, two way encryption, md5 + salt. http://www.asp.net/learn/security for more info.
If you dont need anything too fancy, this is great for websites.
If you are not using ASP.Net here is a good link to a few articles from 4guys and codeproject
https://web.archive.org/web/20210519000117/http://aspnet.4guysfromrolla.com/articles/081705-1.aspx
https://web.archive.org/web/20210510025422/http://aspnet.4guysfromrolla.com/articles/103002-1.aspx
http://www.codeproject.com/KB/security/SimpleEncryption.aspx
Since your question is about storage method & size I will address that.
Storage type can be either binary or text representation (base64 is the most common). Binary is smaller but I find working with text easier. If you are doing per user salting (different salt per password) then it is easier to store salt+hash as a single combined string.
The size is hash algorithm dependent. The output of MD5 is always 16 bytes, SHA1 is always 20 bytes. SHA-256 & SHA-512 are 32 & 64 bytes respectively. If you are using text encoding you will need slightly more storage depending on the encoding method. I tend to use Base64 because storage is relatively cheap. Base64 is going to require roughly 33% larger field.
If you have per user salting you will need space for the hash also. Putting it all together 64bit salt + SHA1 hash (160 bit) base64 encoded takes 40 characters so I store it as char(40).
Lastly if you want to do it right you shouldn't be using a single hash but a key derivation function like RBKDF2. SHA1 and MD5 hashes are insanely fast. Even a single threaded application can hash about 30K to 50K passwords per second thats up to 200K passwords per second on quad core machine. GPUs can hash 100x to 1000x as many passwords per second.With speeds like that brute force attacking becomes an acceptable intrusion method. RBKDF2 allows you to specify the number of iterations to fine tune how "slow" your hashing is. The point isn' to bring the system to its knees but to pick a number of iterations so that you cap upper limit on hash throughput (say 500 hashes per second). A future proof method would be to include the number of iterations in the password field (iterations + salt + hash). This would allow increasing iterations in the future to keep pace with more powerful processors. To be even more flexible use varchar to allow potentially larger/alternative hashes in the future.
The .Net implementation is RFC2892DeriveBytes
http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx