Usage of MD5 Encryption and Decryption Technology in Java Application Development
MD5 (Message Digest Algorithm 5) is a widely used hash function that generates a 128-bit (16-byte) hash value. It is important to note that MD5 is a one-way encryption algorithm, meaning it cannot theoretically be decrypted (it can only be cracked through collision attacks or rainbow tables).
1. Core Characteristics of MD5
One-way: Irreversible operation; the original data cannot be recovered from the hash value.
Fixed Length: Regardless of the input length, the output is always 128 bits.
Avalanche Effect: A tiny change in the input will cause a large difference in the output.
Collision Resistance (No Longer Valid): In theory, different inputs should not produce the same output, but collisions have been proven to be artificially created.
2. Algorithm Processing Steps
Data Padding: Padding the data so that its length = 448 mod 512.
Appending Length: After padding, appending a 64-bit representation of the original data length.
Initializing Variables: Initializing four 32-bit registers (A, B, C, D) with fixed values.
Block Processing: Processing data in 512-bit blocks, each undergoing 4 rounds of main loops (a total of 64 operations).
Output: Concatenating A, B, C, and D to form the 128-bit hash value.
3. Java Implementation of MD5 Encryption
Basic Implementation (Using Native JDK):
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Core {
/**
* Standard MD5 encryption
* @param input Original string
* @return 32-character hexadecimal MD5 value
*/
public static String md5(String input) {
try {
// 1. Get an instance of MessageDigest
MessageDigest md = MessageDigest.getInstance("MD5");
// 2. Compute the hash value (byte array)
byte[] hashBytes = md.digest(input.getBytes());
// 3. Convert byte array to hexadecimal string
return bytesToHex(hashBytes);
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("MD5 algorithm not available", e);
}
}
// Convert byte array to hexadecimal string
private static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
public static void main(String[] args) {
String[] testCases = {"", "hello321", "Hello12345", "Hello World"};
for (String str : testCases) {
System.out.printf("Original: %-10s → MD5: %s%n",
str, md5(str));
}
}
}
Enhanced Implementation (Salted Encryption):
import java.security.SecureRandom;
import java.util.Base64;
public class SaltedMD5 {
// Generate a random salt
public static String generateSalt() {
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
return Base64.getEncoder().encodeToString(salt);
}
// MD5 encryption with salt
public static String md5WithSalt(String input, String salt) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(salt.getBytes());
byte[] hashed = md.digest(input.getBytes());
return bytesToHex(hashed);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// Test example
public static void main(String[] args) {
String password = "myPassword310";
String salt = generateSalt();
System.out.println("Original password: " + password);
System.out.println("Salt: " + salt);
System.out.println("Salted MD5: " + md5WithSalt(password, salt));
}
// Convert byte array to hexadecimal string
private static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
}
import java.util.HashMap;
import java.util.Map;
public class SimpleMD5Cracker {
// Simulated small rainbow table
private static final Map<String, String> RAINBOW_TABLE = new HashMap<>();
static {
// Prestore some common string-to-MD5 mappings
RAINBOW_TABLE.put("d41d8cd98f00b204e9800998ecf8427e", ""); // empty string
RAINBOW_TABLE.put("5d41402abc4b2a76b9719d911017c592", "hello");
RAINBOW_TABLE.put("7d793037a0760186574b0282f2f435e7", "world");
RAINBOW_TABLE.put("e10adc3949ba59abbe56e057f20f883e", "123456");
}
/**
* Simulated MD5 decryption (only works for pre-mapped hashes)
* @param md5Hash The MD5 hash value
* @return The original string or null if not found
*/
public static String crackMD5(String md5Hash) {
return RAINBOW_TABLE.get(md5Hash.toLowerCase());
}
// Brute-force cracking demo (for educational purposes only, very inefficient)
public static String bruteForce(String md5Hash, int maxLength) {
// In practice, a more efficient implementation should be used
for (int len = 1; len <= maxLength; len++) {
String result = bruteForceRecursive(md5Hash, "", len);
if (result != null) return result;
}
return null;
}
private static String bruteForceRecursive(String targetHash, String current, int length) {
if (current.length() == length) {
if (MD5Core.md5(current).equals(targetHash)) {
return current;
}
return null;
}
for (char c = 'a'; c <= 'z'; c++) {
String result = bruteForceRecursive(targetHash, current + c, length);
if (result != null) return result;
}
return null;
}
public static void main(String[] args) {
String md5 = "5d41402abc4b2a76b9719d911017c592";
// Rainbow table lookup
System.out.println("Rainbow table result: " + crackMD5(md5));
// Brute-force (demonstration for short strings)
System.out.println("Brute-force 3-letter lowercase string: " +
bruteForce("900150983cd24fb0d6963f7d28e17f72", 3));
}
}
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
public class FileChecksum {
// Calculate the MD5 checksum of a file
public static String getFileMD5(String filePath) throws IOException {
MessageDigest md = MessageDigest.getInstance("MD5");
try (FileInputStream fis = new FileInputStream(filePath)) {
byte[] buffer = new byte[8192];
int length;
while ((length = fis.read(buffer)) != -1) {
md.update(buffer, 0, length);
}
}
return bytesToHex(md.digest());
}
// Main method to test file checksum calculation
public static void main(String[] args) throws Exception {
String filePath = "md5.txt";
String checksum = getFileMD5(filePath);
System.out.println("File MD5 checksum: " + checksum);
}
// Convert byte array to hexadecimal string
private static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1)
hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
}
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import java.util.Base64;
public class ModernCrypto {
public static String secureHash(String password) throws Exception {
// Generate random salt
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
// PBKDF2 parameters
KeySpec spec = new PBEKeySpec(
password.toCharArray(),
salt,
100000, // Iteration count
256 // Key length
);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] hash = factory.generateSecret(spec).getEncoded();
// Format: algorithm$iterations$salt$hash
return "pbkdf2_sha256$100000$" +
Base64.getEncoder().encodeToString(salt) + "$" +
Base64.getEncoder().encodeToString(hash);
}
public static void main(String[] args) throws Exception {
String password = "mySecretPassword321";
String hashed = secureHash(password);
System.out.println("Secure hash result: " + hashed);
}
}

Comments
Post a Comment