简体   繁体   English

如何在Java中使用SHA-512散列密码?

[英]How to hash a password with SHA-512 in Java?

I've been investigating a bit about Java String encryption techniques and unfortunately I haven't find any good tutorial how to hash String with SHA-512 in Java; 我一直在研究Java String加密技术,遗憾的是我还没有找到任何关于如何在Java中使用SHA-512散列String的好教程。 I read a few blogs about MD5 and Base64, but they are not as secure as I'd like to (actually, Base64 is not an encryption technique), so I prefer SHA-512. 我读了一些关于MD5和Base64的博客,但它们并不像我想的那样安全(实际上,Base64不是加密技术),所以我更喜欢SHA-512。

you can use this for SHA-512 您可以将它用于SHA-512

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public String get_SHA_512_SecurePassword(String passwordToHash, String   salt){
String generatedPassword = null;
    try {
         MessageDigest md = MessageDigest.getInstance("SHA-512");
         md.update(salt.getBytes(StandardCharsets.UTF_8));
         byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
         StringBuilder sb = new StringBuilder();
         for(int i=0; i< bytes.length ;i++){
            sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
         }
         generatedPassword = sb.toString();
        } 
       catch (NoSuchAlgorithmException e){
        e.printStackTrace();
       }
    return generatedPassword;
}

使用番石榴

Hashing.sha512().hashString(s, StandardCharsets.UTF_8).toString()

Use Apache Commons Crypt, it features SHA-512 based crypt() functions that generate salted hashes that are even compatible to libc's crypt and thus usable in PHP/Perl/Python/C and most databases, too. 使用Apache Commons Crypt,它具有基于SHA-512的crypt()函数,可生成与libc的crypt兼容的salted哈希,因此也可用于PHP / Perl / Python / C和大多数数据库。

https://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/digest/Crypt.html#Crypt%28%29 https://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/digest/Crypt.html#Crypt%28%29

you could use this to hash a password in java if you want to. 如果你愿意,可以使用它来在java中哈希密码。

public static boolean isHashMatch(String password, // the password you want to check.
                                  String saltedHash, // the salted hash you want to check your password against.
                                  String hashAlgorithm, // the algorithm you want to use.
                                  String delimiter) throws NoSuchAlgorithmException // the delimiter that has been used to delimit the salt and the hash.
{
    // get the salt from the salted hash and decode it into a byte[].
    byte[] salt = Base64.getDecoder()
                        .decode(saltedHash.split(delimiter)[0]);
    // compute a new salted hash based on the provided password and salt.
    String pw_saltedHash = computeSaltedBase64Hash(password, 
                                                   salt,
                                                   hashAlgorithm,
                                                   delimiter);
    // check if the provided salted hash matches the salted hash we computed from the password and salt.
    return saltedHash.equals(pw_saltedHash);
}

public static String computeSaltedBase64Hash(String password, // the password you want to hash
                                             String hashAlgorithm, // the algorithm you want to use.
                                             String delimiter) throws NoSuchAlgorithmException // the delimiter that will be used to delimit the salt and the hash.
{
    // compute the salted hash with a random salt.
    return computeSaltedBase64Hash(password, null, hashAlgorithm, delimiter);
}

public static String computeSaltedBase64Hash(String password, // the password you want to hash
                                             byte[] salt, // the salt you want to use (uses random salt if null).
                                             String hashAlgorithm, // the algorithm you want to use.
                                             String delimiter) throws NoSuchAlgorithmException // the delimiter that will be used to delimit the salt and the hash.
{
    // transform the password string into a byte[]. we have to do this to work with it later.
    byte[] passwordBytes = password.getBytes();
    byte[] saltBytes;

    if(salt != null)
    {
        saltBytes = salt;
    }
        else
        {
            // if null has been provided as salt parameter create a new random salt.
            saltBytes = new byte[64];
            SecureRandom secureRandom = new SecureRandom();
            secureRandom.nextBytes(saltBytes);              
        }

    // MessageDigest converts our password and salt into a hash. 
    MessageDigest messageDigest = MessageDigest.getInstance(hashAlgorithm);
    // concatenate the salt byte[] and the password byte[].
    byte[] saltAndPassword = concatArrays(saltBytes, passwordBytes);
    // create the hash from our concatenated byte[].
    byte[] saltedHash = messageDigest.digest(saltAndPassword);
    // get java's base64 encoder for encoding.
    Encoder base64Encoder = Base64.getEncoder();
    // create a StringBuilder to build the result.
    StringBuilder result = new StringBuilder();

    result.append(base64Encoder.encodeToString(saltBytes)) // base64-encode the salt and append it.
          .append(delimiter) // append the delimiter (watch out! don't use regex expressions as delimiter if you plan to use String.split() to isolate the salt!)
          .append(base64Encoder.encodeToString(saltedHash)); // base64-encode the salted hash and append it.

    // return a salt and salted hash combo.
    return result.toString();
}

public static byte[] concatArrays(byte[]... arrays)
{   
    int concatLength = 0;
    // get the actual length of all arrays and add it so we know how long our concatenated array has to be.
    for(int i = 0; i< arrays.length; i++)
    {
        concatLength = concatLength + arrays[i].length;
    }
    // prepare our concatenated array which we're going to return later.
    byte[] concatArray = new byte[concatLength];
    // this index tells us where we write into our array.
    int index = 0;
    // concatenate the arrays.
    for(int i = 0; i < arrays.length; i++)
    {
        for(int j = 0; j < arrays[i].length; j++)
        {
            concatArray[index] = arrays[i][j];
            index++;
        }
    }
    // return the concatenated arrays.
    return concatArray;     
}
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Hex;

public String getHashSHA512(String StringToHash, String salt){
        String generatedPassword = null;
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-512");
            md.update(salt.getBytes(StandardCharsets.UTF_8));
            byte[] bytes = md.digest(StringToHash.getBytes(StandardCharsets.UTF_8));
            generatedPassword = Hex.encodeHexString(bytes);
        }
        catch (NoSuchAlgorithmException e){
            e.printStackTrace();
        }
        return generatedPassword;
    }

It's not recommended to use hash functions for passwords though, newer alogrithms like bcrypt, or scrypt exist 不推荐使用密码的哈希函数,比如bcrypt或scrypt这样的新算法

With secure hashing combine 3 salt components (of 150 random characters each) to a individual user salt (user salt from the user database table, general salt in a database table (monthly change with cron job) and hide some salt in the application library). 使用安全散列将3个盐组件(每个150个随机字符)组合到单个用户salt(用户数据库表中的用户salt,数据库表中的常规盐(使用cron作业每月更改)并在应用程序库中隐藏一些salt) 。 Align the for loop amount of the secure hash to your needs. 将安全散列的for循环量与您的需求对齐。 See answer above for hashing method. 有关散列方法,请参阅上面的答案。

private static String generateSalt(int lenght){
    String abcCapitals = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    String abcLowerCase = "abcdefghijklmnopqrstuvwxyz";
    String numbers = "01234567890123456789";
    String characters = "!@#$%^&*!@#$%%^^&*";

    String total = abcCapitals + abcLowerCase + numbers + characters;

    String response = "";

    char letters[] = new char[lenght];
    for (int i=0; i<lenght-1; i++){
        Random r = new Random();
        char letter = total.charAt(r.nextInt(total.length()));
        letters[i] = letter;
    }

    response = Arrays.toString(letters).replaceAll("\\s+","");
    response = response.replaceAll(",","");

    return response;
}

private static String getHash(String passwordToHash, String salt){
            String generatedPassword = null;
            try {
                 MessageDigest md = MessageDigest.getInstance("SHA-512");
                 md.update(salt.getBytes(StandardCharsets.UTF_8));
                 byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
                 StringBuilder sb = new StringBuilder();
                 for(int i=0; i< bytes.length ;i++){
                    sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
                 }
                 generatedPassword = sb.toString();
                } 
               catch (NoSuchAlgorithmException e){
                   System.out.println(e);
               }
            return generatedPassword;
        }

    public static String getSecureHash(String password, String salt){
        String hash = getHash(password, salt);
        for (int i=0; i<20000; i++){
            hash = getHash(password, hash);      
        }
        return hash;
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        String salt = generateSalt(150);
        String salt2 = generateSalt(150);
        String salt3 = generateSalt(150);
        String someString = "This is some string!";

        String hash = getSecureHash(someString, salt + salt2 + salt3);
        System.out.println(hash);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM