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; 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.
- 2SHA2 is not an encryption technique either. It is a family of cryptographical secure hash functions, it can be used for message digest, not encryption (at least no in normal mode). You need to describe a bit more what you want to do. Other than that yur MD5 code should work with other hash algrithms as well, just exchange the algorithm name. The output of all of them is a binary byte[] array, so you might want to use base64 or binhex to make the result ascii only.eckes– eckes2015-10-12 16:09:17 +00:00Commented Oct 12, 2015 at 16:09
- 3SHA-512 is not an encryption algorithm either. Actually, it's designed specifically to make it impossible to "decrypt" the digest produced by this hashing algorithm. What do you want to achieve?JB Nizet– JB Nizet2015-10-12 16:09:36 +00:00Commented Oct 12, 2015 at 16:09
- 1A java String contains valid Unicode. Getting the bytes in some charset (like UTF-8) and then encrypting them yields bytes that cannot be correctly translated to a String (for decrypting), certainly not with UTF-8 which requires correct sequences. Hence often Base64 is added to translate encrypted bytes into ASCII.Joop Eggen– Joop Eggen2015-10-12 16:11:06 +00:00Commented Oct 12, 2015 at 16:11
- 3There is no cryptographic algorithm that allows doing what you want. Either you want encryption (but you shouldn't if the goal is to store passwords), and you need a key to encrypt/decrypt. Or you want a salt and a digest function (and a hashing function is what you want, although SHA-512 is considered too weak for that usage). The principle of salt + digest is that you can check if a submitted password is correct by resalting and redigesting it, and then check that the result is identical to the one stored in database. But it's impossible to reverse the result and get the original password.JB Nizet– JB Nizet2015-10-12 16:18:03 +00:00Commented Oct 12, 2015 at 16:18
- 3Use PBKDF2WithHmacSHA1 (which comes with the JDK) or BCrypt. But first, learn the principles of crypto.JB Nizet– JB Nizet2015-10-12 16:19:45 +00:00Commented Oct 12, 2015 at 16:19
7 Answers
you can use this for SHA-512 (Not a good choice for password hashing).
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; } 13 Comments
Please stop using hash functions to encode passwords! They do not provide the protection you need. Instead, you should be using an algorithm like PBKDF2, bcrypt, or scrypt.
References:
- http://blog.tjll.net/please-stop-hashing-passwords/
- http://security.blogoverflow.com/2011/11/why-passwords-should-be-hashed/
- https://crackstation.net/hashing-security.htm
- http://www.sitepoint.com/risks-challenges-password-hashing/
- http://security.blogoverflow.com/2013/09/about-secure-password-hashing/
7 Comments
SHA-512 Java code examples (regardless of WHY they need this) find a non-solution. Perhaps in the future you could 1. Offer a solution. 2. Offer the BETTER solution as a side-note.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.
Comments
you could use this to hash a password in java if you want to.
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; } Comments
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
Comments
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). Align the for loop amount of the secure hash to your needs. 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); }