How to Secure Passwords with Salt in Java: MD5 Salting Explained
This article explains the concept of password salting, its security benefits, and provides a complete Java implementation using MD5, including salt generation, hashing with and without salt, storing salt within the hash, and verification procedures for registration and login.
What is Salting?
Many companies store user passwords as hash values (the article uses MD5 as an example, though bcrypt is more common). Because hash functions can collide, if a database is compromised attackers can obtain the hash values and potentially recover passwords using methods such as rainbow‑table attacks.
Example: http://www.cmd5.com/
These hashes can be cracked.
Salting Principle
Simply put, the original hash H(p) becomes H(p+salt). Each hash operation uses a random salt, effectively changing the hash function each time.
If H changes, existing rainbow‑table data becomes useless; new tables must be generated for the specific H, greatly increasing cracking difficulty.
How to Salt?
1. Generate Salt
private static char[] hex = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
/**
* Custom simple salt generator: a random 16‑character string where each character is a random hexadecimal digit.
*/
public static String salt(){
Random random = new Random();
StringBuilder sb = new StringBuilder(16);
for(int i=0;i<sb.capacity();i++){
sb.append(hex[random.nextInt(16)]);
}
return sb.toString();
}2. Input with Salt
String inputWithSalt = inputStr + salt; // add salt to the inputSalting is that simple.
3. Output with Salt
The resulting hash can optionally embed the salt. In practice the salt used for the hash is stored together with the hash value so that during login the same salt can be retrieved.
/**
* @params: [inputStr, type] inputStr is the plaintext; type 0 means registration (store hash), 1 means login verification
* @Descrption: MD5 with salt. Salt is obtained in two ways; input plaintext with salt; output ciphertext with salt (store salt in the hash).
*/
public static String MD5WithSalt(String inputStr, int type){
try{
MessageDigest md = MessageDigest.getInstance("MD5");
String salt = null;
if(type == 0){ // registration
salt = salt();
}else if(type == 1){ // login verification
String queriedHash = null; // hash retrieved from DB
salt = getSaltFromHash(queriedHash);
}
String inputWithSalt = inputStr + salt; // add salt
String hashResult = byte2HexStr(md.digest(inputWithSalt.getBytes()));
System.out.println("Salted ciphertext:" + hashResult);
// Store salt in the hash for later verification
char[] cs = new char[48];
for(int i=0;i<48;i+=3){
cs[i] = hashResult.charAt(i/3*2);
cs[i+1] = salt.charAt(i/3);
cs[i+2] = hashResult.charAt(i/3*2+1);
}
hashResult = new String(cs);
return hashResult;
}catch(Exception e){
e.printStackTrace();
return e.toString();
}
}The operation of inserting the salt into the hash is straightforward: assuming the hash is 32 characters long and the salt is 16 characters, a salt character is inserted after every two hash characters.
Backend Password Storage and Verification Process
1. Store Password on Registration
User registers and sends account and password p1 from the front end to the back end.
The back end randomly generates a salt.
Compute H(p1+salt) and store the resulting salted hash (hash1) in the database.
2. Verify Password on Login
User logs in and sends account and password p2 from the front end.
Retrieve the stored hash (hash2) for the given account from the database.
Extract the salt from hash2.
Compute H(p2+salt) to obtain hash3 and compare hash2 with hash3; if equal, login succeeds, otherwise it fails.
Java Implementation
MD5 is used as the hash function. The JDK does not provide a built‑in salting process, so we implement it ourselves. (Bcrypt salting is simpler; see the author's other blog for that source.)
package EncryptAndDecrypt;
import java.security.MessageDigest;
import java.util.Random;
/**
* 32‑bit MD5 hash implementation. Note: hashing is one‑way and cannot be decrypted.
*/
public class MyMD5 {
private static char[] hex = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
public static void main(String[] args) throws Exception {
String input = "123456";
System.out.println("MD5 encryption
Plaintext:" + input + "
No‑salt ciphertext:" + MD5WithoutSalt(input));
System.out.println("Salted ciphertext:" + MD5WithSalt(input,0));
}
public static String MD5WithoutSalt(String inputStr){
try{
MessageDigest md = MessageDigest.getInstance("MD5");
return byte2HexStr(md.digest(inputStr.getBytes()));
}catch(Exception e){
e.printStackTrace();
return e.toString();
}
}
// MD5WithSalt method as shown earlier
// ... (other helper methods: salt(), byte2HexStr(), getSaltFromHash())
public static String salt(){
Random random = new Random();
StringBuilder sb = new StringBuilder(16);
for(int i=0;i<sb.capacity();i++){
sb.append(hex[random.nextInt(16)]);
}
return sb.toString();
}
private static String byte2HexStr(byte[] bytes){
StringBuffer result = new StringBuffer();
for(byte b : bytes){
result.append(hex[(b>>>4) & 0xf]);
result.append(hex[b & 0xf]);
}
return result.toString();
}
public static String getSaltFromHash(String hash){
StringBuilder sb = new StringBuilder();
char[] h = hash.toCharArray();
for(int i=0;i<hash.length();i+=3){
sb.append(h[i+1]);
}
return sb.toString();
}
}Sample output (first run):
MD5加密
明文:123456
无盐密文:E10ADC3949BA59ABBE56E057F20F883E
加盐密文:80D05C08F8879B2C84BA0C40143D224F
带盐密文:8D0D8053C0F8F6887791B2BC804B7A0EC4901543DD2B241FSample output (second run):
MD5加密
明文:123456
无盐密文:E10ADC3949BA59ABBE56E057F20F883E
加盐密文:2CFFE57B054378D926A6FF14A1985F22
带盐密文:21CF7FE957CB0354C37B8DC9256AD6F0F174A719785AF222Because the same plaintext produces identical unsalted hashes but different salted hashes, salting significantly improves password security.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
21CTO
21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
