SHA algorithm generates each time unique hash string for a same key

陌路散爱 提交于 2021-02-18 03:34:26

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!