问题
I know there are lots lots of articles available about hashing and encryption algorithm.
I have figure it out from them that use hashing function instead of encryption to store password in the database.
So I decided to use SHA-256 algorithm to generate hash key and I am storing that hash key into my server database instead of plain password.
Now I am really not able to understand how I should use it, because each time I am passing the same password to generate SHA key it gives me different than previous one, than how could I compare it with stored hash key in my database?
I am using java so my java code is
public class Test {
public static void main(String...arg) throws IOException{
System.out.println("First time");
String string64 = getEncryptedPassword("FenilShah");
System.out.println(string64);
System.out.println(StringUtils.newStringUtf8(Base64.decodeBase64(string64)));
System.out.println("\nSecond time");
string64 = getEncryptedPassword("FenilShah");
System.out.println(string64);
System.out.println(StringUtils.newStringUtf8(Base64.decodeBase64(string64)));
System.out.println("\nThird time");
string64 = getEncryptedPassword("FenilShah");
System.out.println(string64);
System.out.println(StringUtils.newStringUtf8(Base64.decodeBase64(string64)));
}
public static String getEncryptedPassword(String clearTextPassword) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(clearTextPassword.getBytes());
byte pass[] = md.digest();
System.out.println(pass.toString());
return Base64.encodeBase64String(StringUtils.getBytesUtf8(pass.toString()));
} catch (NoSuchAlgorithmException e) {
//_log.error("Failed to encrypt password.", e);
}
return "";
}
}
so the output is something like this
First time
[B@5bf825cc
W0JANWJmODI1Y2M=
[B@5bf825cc
Second time
[B@1abfb235
W0JAMWFiZmIyMzU=
[B@1abfb235
Third time
[B@1f4cc34b
W0JAMWY0Y2MzNGI=
[B@1f4cc34b
回答1:
This is your most immediate problem:
byte pass[] = md.digest();
System.out.println(pass.toString());
You're not returning the hash of the string. You're returning the result of calling toString()
on a byte[]
. Arrays in Java don't override toString()
, so you get the default implementation, which has everything to do with the identity of the object and nothing to do with the data in the byte array:
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object.
(Arrays don't override hashCode()
either, so that's obtained from the default implementation in Object
too...)
Basically, you need a different way of converting a byte[]
to a String
... or store the byte array directly in the database, of course. If you do want to convert to a string, I suggest you use either hex or base64. For base64, I'd suggest the iharder.net public domain library... or if you're using Java 8, you can use java.util.Base64. (It's astonishing that it took so long to get a base64 class into the standard libraries in a context other than XML etc, but there we go.)
return Base64.getEncoder().encodeToString(md.digest());
Your code has an additional problem though:
md.update(clearTextPassword.getBytes());
This uses the platform default encoding to convert the password into a byte array. That's not a good idea - it means you could end up getting different hashes based on what system your code is running on. It's better to specify the encoding explicitly:
md.update(clearTextPassword.getBytes(StandardCharsets.UTF_8));
Additionally, catching an exception if SHA-256 is missing, logging and continuing with a blank string is almost certainly the wrong approach. Do you really want to populate your database with empty strings, allowing anyone to log in with any password? If your system is in that state, the best thing you can do is almost certainly to fail any request to do anything with passwords. You probably want to convert the NoSuchAlgorithmException
into some sort of RuntimeException
and rethrow.
Finally, storing a simple SHA-256 hash probably isn't a good idea anyway.
- You probably want an HMAC instead
- You should at least use a random salt to avoid the same passwords having the same values in the database. (Otherwise, an attacker can use that information to their advantage.)
I'm far from an expert on security, so I won't advise you much further on the right way to do things - but I would actually suggest trying to find a well-respected library written by security experts rather than trying to implement this yourself. Security it very hard to do right.
来源:https://stackoverflow.com/questions/26838341/sha-algorithm-generates-each-time-unique-hash-string-for-a-same-key