摘要:在Java开发中,加密解密技术是保护数据安全的重要手段。无论是存储敏感信息(如用户密码、个人信息)还是传输加密数据,都需要用到加密算法。不同的加密算法运用的场景也不同,因此选择合适的加密解密算法也是至关重要。
一、加密算法分类
加密算法的种类繁多,主要可以归纳为以下几大类:
一、对称加密算法
- 定义:加密和解密使用相同密钥的加密算法。
- 特点:加密强度高,效率高,但密钥分发和管理较为复杂。
- 常见算法:
- DES:一种使用对称密钥加密的块算法,由IBM公司于1975年研发,是广泛应用的早期对称加密算法之一,但由于密钥长度较短(56位),安全性已逐渐降低。
- 3DES:DES算法的一个更安全的变形,使用3条56位的密钥对数据进行三次加密,提高了安全性,是DES算法向AES算法过渡的算法。
- AES:高级加密标准(Advanced Encryption Standard),是一种分块加密算法,用于替代原先的DES算法。AES算法由三种不同的算法组成,分别使用128、192或256位加密密钥,具有高强度、高速度和易于实现的特点。
- RC4:一种流密码算法,由Ron Rivest于1987年创建,通过生成一个伪随机数流与明文进行异或运算来实现加密,具有速度快、简单易用、灵活性高以及适用范围广的特点。
- 其他还包括Blowfish、IDEA、RC5、RC6等算法。
二、非对称加密算法
- 定义:非对称加密算法是指加密和解密使用不同密钥的加密算法,通常包含公钥和私钥。公钥用于加密,私钥用于解密(或反之用于验签)。
- 特点:加密速度慢,但强度高,适用于密钥交换和数字签名等场景。
- 常见算法:
- RSA:一种基于公钥加密的算法,广泛应用于SSL证书中的密钥交换和数字签名过程,助力网站实现HTTPS加密,确保网络通信安全。
- ECC:基于椭圆曲线密码学的加密算法,相比于RSA算法,ECC算法提供了更高的安全性和更短的密钥长度。
- 其他还包括Diffie-Hellman、El Gamal、DSA(数字签名用)等算法。
三、哈希算法
- 定义:也叫安全散列算法、消息摘要算法、杂凑算法,是一种将任意长度的输入数据输出为固定长度数据的算法,具有单向性,即不能通过输出数据反推出输入数据。
- 特点:可实现数据签名、数据完整性校验等功能。
- 常见算法:
- MD5:一种加密散列函数算法,将任意长度的信息作为输入,并转换为128位(16字节)的固定长度信息,主要用于验证文件是否被篡改。但近年来,由于其哈希值长度较短,安全性逐渐受到质疑。
- SHA系列:包括SHA-1、SHA-2(SHA-224、SHA-256、SHA-384、SHA-512)等算法,其中SHA-1算法可以生成160位(20字节)散列值,而SHA-2算法则是SHA-1算法的继承者,提供了更高的安全性。SHA系列算法广泛应用于文件传输校验、代码签名证书等领域。
- 其他还包括MD2、MD4、HAVAL等算法,但部分算法由于安全性问题已逐渐被淘汰。
二、加密算法实现
本文将介绍几种Java中常用的加密解密算法,并提供相应的使用示例。
对称加密算法
DES算法
DES(Data Encryption Standard)是一种古老的对称加密算法,它以64位为分组长度,密钥长度为56位,8位用于奇偶校验。
在Java中,可以使用javax.crypto.Cipher类来执行DES加密和解密。
import com.alibaba.fastjson.JSON;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
/**
* DES算法加解密工具类
*/
public class DESUtil {
/**
* 生成DES密钥
*
* @return SecretKey DES密钥
* @throws NoSuchAlgorithmException 当DES算法不可用时抛出
*/
public static SecretKey generateDESKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
keyGenerator.init(56); // DES算法密钥长度为56位,这里每次调用随机都会生成新的密钥。
return keyGenerator.generateKey();
}
/**
* 生成固定DES密钥
*
* @return SecretKey DES密钥
*/
public static SecretKey generateFixDESKey() throws UnsupportedEncodingException {
// 定义一个8字节字符串key
String fixedKey = "qwerasdf";
// 使用固定的字节数组(64位)创建DES密钥
return new SecretKeySpec(fixedKey.getBytes(StandardCharsets.UTF_8), "DES");
}
/**
* 使用DES算法加密
*
* @param data 待加密的数据
* @param secretKey DES密钥
* @return 加密后的数据(Base64编码)
* @throws Exception 加密过程中的异常
*/
public static String encrypt(String data, SecretKey secretKey) throws Exception {
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedData = cipher.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(encryptedData);
}
/**
* 使用DES算法解密
*
* @param data 加密的数据(Base64编码)
* @param secretKey DES密钥
* @return 解密后的数据
* @throws Exception 解密过程中的异常
*/
public static String decrypt(String data, SecretKey secretKey) throws Exception {
byte[] encryptedData = Base64.getDecoder().decode(data);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedData = cipher.doFinal(encryptedData);
return new String(decryptedData);
}
// 工具类不应该有公共构造器
private DESUtil() {
}
// 主方法用于测试工具类
public static void main(String[] args) {
try {
// 生成DES密钥
SecretKey secretKey = generateFixDESKey();
System.out.println(JSON.toJSONString(secretKey));
// 加密数据
String originalString = "Hello, World!";
String encryptedString = encrypt(originalString, secretKey);
System.out.println("Encrypted: " + encryptedString);
// 解密数据
String decryptedString = decrypt(encryptedString, secretKey);
System.out.println("Decrypted: " + decryptedString);
} catch (Exception e) {
e.printStackTrace();
}
}
}
AES算法
AES(Advanced Encryption Standard)是一种高级加密标准,是目前广泛使用的加密算法之一,提供多种密钥长度(如128位、192位、256位)。
在Java中,可以使用javax.crypto.Cipher类来执行AES加密和解密。
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class AESUtil {
// AES算法名称
private static final String AES_ALGORITHM = "AES";
/**
* 生成AES密钥
*
* @return SecretKey AES密钥
* @throws NoSuchAlgorithmException 当AES算法不可用时抛出
*/
public static SecretKey generateAESKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
keyGenerator.init(128); // 设置密钥长度为128位
return keyGenerator.generateKey();
}
/**
* 生成AES特定密钥
*
* @return SecretKey AES密钥
* @throws NoSuchAlgorithmException 当AES算法不可用时抛出
*/
public static SecretKey generateFixAESKey() throws NoSuchAlgorithmException {
// 定义一个16字节字符串key
String fixedKey = "qwerasdfzxcvbnml";
// 使用固定的字节数组(128位)创建DES密钥
return new SecretKeySpec(fixedKey.getBytes(StandardCharsets.UTF_8), "AES");
}
/**
* 使用AES算法加密
*
* @param data 待加密的数据
* @param secretKey AES密钥
* @return 加密后的数据(Base64编码)
* @throws Exception 加密过程中的异常
*/
public static String encrypt(String data, SecretKey secretKey) throws Exception {
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedData = cipher.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(encryptedData);
}
/**
* 使用AES算法解密
*
* @param data 加密的数据(Base64编码)
* @param secretKey AES密钥
* @return 解密后的数据
* @throws Exception 解密过程中的异常
*/
public static String decrypt(String data, SecretKey secretKey) throws Exception {
byte[] encryptedData = Base64.getDecoder().decode(data);
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedData = cipher.doFinal(encryptedData);
return new String(decryptedData);
}
// 工具类不应该有公共构造器
private AESUtil() {
}
// 主方法用于测试工具类
public static void main(String[] args) {
try {
// 生成AES密钥
SecretKey secretKey = generateFixAESKey();
// 加密数据
String originalString = "Hello, World!";
String encryptedString = encrypt(originalString, secretKey);
System.out.println("Encrypted: " + encryptedString);
// 解密数据
String decryptedString = decrypt(encryptedString, secretKey);
System.out.println("Decrypted: " + decryptedString);
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们也可以使用组合算法来进行进一步的加密
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;
public class AESUtil {
// AES密钥的key,用来生成密钥。长度可以为128,192,256
private static final String AES_KEY = "qwerasdfzxcvbnml";
// AES算法名称
private static final String AES_ALGORITHM = "AES";
/**
* 组合算法,它由三个部分组成:
* AES:这是一个对称加密算法,用于加密和解密数据。
* CBC:这是块密码的密码块链模式(Cipher Block Chaining),它使用一个初始化向量(IV)来混淆加密的数据。在CBC模式下,每个加密块都是基于前一个块的密文,这意味着如果加密了多个块,每个块的加密都会依赖于之前的加密结果。
* PKCS5Padding:这是一种填充模式,用于将明文填充到下一个加密块的大小。在AES中,每个块的大小是128位(16字节),因此PKCS5Padding会根据块的大小来填充明文,以确保明文大小总是块大小的整数倍。
* */
private static final String AES_CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";
/**
* 生成特定AES密钥
*
* @return SecretKey AES密钥
*/
public static SecretKey generateAESKey() {
// 使用固定的字节数组(128位)创建DES密钥
return new SecretKeySpec(AES_KEY.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
}
/**
* 生成CBC初始化向量
*
* @return AlgorithmParameterSpec CBC初始化向量
*/
public static AlgorithmParameterSpec generateIvParam() {
return new IvParameterSpec(AES_KEY.getBytes());
}
/**
* 使用AES算法加密
*
* @param data 待加密的数据
* @param secretKey AES密钥
* @return 加密后的数据(Base64编码)
* @throws Exception 加密过程中的异常
*/
public static String encrypt(String data, SecretKey secretKey, AlgorithmParameterSpec parameterSpec) throws Exception {
Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
byte[] encryptedData = cipher.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(encryptedData);
}
/**
* 使用AES算法解密
*
* @param data 加密的数据(Base64编码)
* @param secretKey AES密钥
* @return 解密后的数据
* @throws Exception 解密过程中的异常
*/
public static String decrypt(String data, SecretKey secretKey, AlgorithmParameterSpec parameterSpec) throws Exception {
byte[] encryptedData = Base64.getDecoder().decode(data);
Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5_PADDING);
cipher.init(Cipher.DECRYPT_MODE, secretKey, parameterSpec);
byte[] decryptedData = cipher.doFinal(encryptedData);
return new String(decryptedData);
}
// 工具类不应该有公共构造器
private AESUtil2() {
}
// 主方法用于测试工具类
public static void main(String[] args) {
try {
// 生成AES密钥
SecretKey secretKey = generateAESKey();
// 生成CBC初始化向量
AlgorithmParameterSpec ivParam = generateIvParam();
// 加密数据
String originalString = "Hello, World!";
String encryptedString = encrypt(originalString, secretKey, ivParam);
System.out.println("Encrypted: " + encryptedString);
// 解密数据
String decryptedString = decrypt(encryptedString, secretKey, ivParam);
System.out.println("Decrypted: " + decryptedString);
} catch (Exception e) {
e.printStackTrace();
}
}
}
非对称加密算法
RSA算法
RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,它包含公钥和私钥。公钥用于加密,私钥用于解密。
Java的KeyPairGenerator和Cipher类可以用来生成密钥对和执行加密解密操作。
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* Rsa算法工具类
* */
public class RSAUtil {
//签名算法名称
private static final String RSA_KEY_ALGORITHM = "RSA";
//标准签名算法名称
private static final String RSA_SIGNATURE_ALGORITHM = "SHA1withRSA";
private static final String RSA2_SIGNATURE_ALGORITHM = "SHA256withRSA";
//RSA密钥长度,默认密钥长度是1024,密钥长度必须是64的倍数,在512到65536位之间,不管是RSA还是RSA2长度推荐使用2048
private static final int KEY_SIZE = 2048;
/**
* 生成密钥对
*
* @return 返回包含公私钥的map
*/
public static Map<String, String> generateKey() {
KeyPairGenerator keygen;
try {
keygen = KeyPairGenerator.getInstance(RSA_KEY_ALGORITHM);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("RSA初始化密钥出现错误,算法异常");
}
SecureRandom secrand = new SecureRandom();
//初始化随机产生器
secrand.setSeed("Alian".getBytes());
//初始化密钥生成器
keygen.initialize(KEY_SIZE, secrand);
KeyPair keyPair = keygen.genKeyPair();
//获取公钥并转成base64编码
byte[] pub_key = keyPair.getPublic().getEncoded();
String publicKeyStr = Base64.getEncoder().encodeToString(pub_key);
//获取私钥并转成base64编码
byte[] pri_key = keyPair.getPrivate().getEncoded();
String privateKeyStr = Base64.getEncoder().encodeToString(pri_key);
//创建一个Map返回结果
Map<String, String> keyPairMap = new HashMap<>();
keyPairMap.put("publicKeyStr", publicKeyStr);
keyPairMap.put("privateKeyStr", privateKeyStr);
return keyPairMap;
}
/**
* 公钥加密(用于数据加密)
*
* @param data 加密前的字符串
* @param publicKeyStr base64编码后的公钥
* @return base64编码后的字符串
* @throws Exception
*/
public static String encryptByPublicKey(String data, String publicKeyStr) throws Exception {
//Java原生base64解码
byte[] pubKey = Base64.getDecoder().decode(publicKeyStr);
//创建X509编码密钥规范
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
//返回转换指定算法的KeyFactory对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
//根据X509编码密钥规范产生公钥对象
PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
//根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
//用公钥初始化此Cipher对象(加密模式)
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
//对数据加密
byte[] encrypt = cipher.doFinal(data.getBytes());
//返回base64编码后的字符串
return Base64.getEncoder().encodeToString(encrypt);
}
/**
* 私钥解密(用于数据解密)
*
* @param data 解密前的字符串
* @param privateKeyStr 私钥
* @return 解密后的字符串
* @throws Exception
*/
public static String decryptByPrivateKey(String data, String privateKeyStr) throws Exception {
//Java原生base64解码
byte[] priKey = Base64.getDecoder().decode(privateKeyStr);
//创建PKCS8编码密钥规范
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
//返回转换指定算法的KeyFactory对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
//根据PKCS8编码密钥规范产生私钥对象
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
//根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
//用私钥初始化此Cipher对象(解密模式)
cipher.init(Cipher.DECRYPT_MODE, privateKey);
//对数据解密
byte[] decrypt = cipher.doFinal(Base64.getDecoder().decode(data));
//返回字符串
return new String(decrypt);
}
/**
* 私钥加密(用于数据签名)
*
* @param data 加密前的字符串
* @param privateKeyStr base64编码后的私钥
* @return base64编码后后的字符串
* @throws Exception
*/
public static String encryptByPrivateKey(String data, String privateKeyStr) throws Exception {
//Java原生base64解码
byte[] priKey = Base64.getDecoder().decode(privateKeyStr);
//创建PKCS8编码密钥规范
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
//返回转换指定算法的KeyFactory对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
//根据PKCS8编码密钥规范产生私钥对象
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
//根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
//用私钥初始化此Cipher对象(加密模式)
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
//对数据加密
byte[] encrypt = cipher.doFinal(data.getBytes());
//返回base64编码后的字符串
return Base64.getEncoder().encodeToString(encrypt);
}
/**
* 公钥解密(用于数据验签)
*
* @param data 解密前的字符串
* @param publicKeyStr base64编码后的公钥
* @return 解密后的字符串
* @throws Exception
*/
public static String decryptByPublicKey(String data, String publicKeyStr) throws Exception {
//Java原生base64解码
byte[] pubKey = Base64.getDecoder().decode(publicKeyStr);
//创建X509编码密钥规范
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
//返回转换指定算法的KeyFactory对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
//根据X509编码密钥规范产生公钥对象
PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
//根据转换的名称获取密码对象Cipher(转换的名称:算法/工作模式/填充模式)
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
//用公钥初始化此Cipher对象(解密模式)
cipher.init(Cipher.DECRYPT_MODE, publicKey);
//对数据解密
byte[] decrypt = cipher.doFinal(Base64.getDecoder().decode(data));
//返回字符串
return new String(decrypt);
}
/**
* RSA签名
*
* @param data 待签名数据
* @param priKey 私钥
* @param signType RSA或RSA2
* @return 签名
* @throws Exception
*/
public static String sign(byte[] data, byte[] priKey, String signType) throws Exception {
//创建PKCS8编码密钥规范
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
//返回转换指定算法的KeyFactory对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
//根据PKCS8编码密钥规范产生私钥对象
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
//标准签名算法名称(RSA还是RSA2)
String algorithm = RSA_KEY_ALGORITHM.equals(signType) ? RSA_SIGNATURE_ALGORITHM : RSA2_SIGNATURE_ALGORITHM;
//用指定算法产生签名对象Signature
Signature signature = Signature.getInstance(algorithm);
//用私钥初始化签名对象Signature
signature.initSign(privateKey);
//将待签名的数据传送给签名对象(须在初始化之后)
signature.update(data);
//返回签名结果字节数组
byte[] sign = signature.sign();
//返回Base64编码后的字符串
return Base64.getEncoder().encodeToString(sign);
}
/**
* RSA校验数字签名
*
* @param data 待校验数据
* @param sign 数字签名
* @param pubKey 公钥
* @param signType RSA或RSA2
* @return boolean 校验成功返回true,失败返回false
*/
public static boolean verify(byte[] data, byte[] sign, byte[] pubKey, String signType) throws Exception {
//返回转换指定算法的KeyFactory对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
//创建X509编码密钥规范
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
//根据X509编码密钥规范产生公钥对象
PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
//标准签名算法名称(RSA还是RSA2)
String algorithm = RSA_KEY_ALGORITHM.equals(signType) ? RSA_SIGNATURE_ALGORITHM : RSA2_SIGNATURE_ALGORITHM;
//用指定算法产生签名对象Signature
Signature signature = Signature.getInstance(algorithm);
//用公钥初始化签名对象,用于验证签名
signature.initVerify(publicKey);
//更新签名内容
signature.update(data);
//得到验证结果
return signature.verify(sign);
}
public static void main(String[] args) throws Exception {
Map<String, String> keyMap = RSAUtil2.generateKey();
String publicKeyStr = keyMap.get("publicKeyStr");
String privateKeyStr = keyMap.get("privateKeyStr");
System.out.println("-----------------生成的公钥和私钥------------------------------");
System.out.println("获取到的公钥:" + publicKeyStr);
System.out.println("获取到的私钥:" + privateKeyStr);
// 待加密数据
String data = "tranSeq=1920542585&amount=100&payType=wechat";
// 公钥加密
System.out.println("-----------------加密和解密------------------------------");
System.out.println("待加密的数据:" + data);
String encrypt = RSAUtil2.encryptByPublicKey(data, publicKeyStr);
System.out.println("加密后数据:" + encrypt);
// 私钥解密
String decrypt = RSAUtil2.decryptByPrivateKey(encrypt, privateKeyStr);
System.out.println("解密后数据:" + decrypt);
// 数字签名
System.out.println("待签名的数据:" + data);
String sign = RSAUtil2.sign(data.getBytes(), Base64.getDecoder().decode(privateKeyStr), "RSA");
System.out.println("数字签名结果:" + sign);
boolean verify = RSAUtil2.verify(data.getBytes(), Base64.getDecoder().decode(sign), Base64.getDecoder().decode(publicKeyStr), "RSA");
System.out.println("数字签名验证结果:" + verify);
}
}
使用RSA进行加密和解密时,由于RSA算法的性能问题,通常不直接用于加密大量数据,而是用于加密对称加密算法的密钥(如AES密钥),然后使用该对称密钥加密实际数据。
注意事项:
- 密钥对的生成、存储和传输需要特别小心,以避免私钥泄露。
- 在实际应用中,密钥对可能需要持久化存储到文件系统或数据库中,但应确保存储的安全性。
- 加密和解密过程中,数据编码(如getBytes())应使用统一的字符集(如UTF-8),以避免乱码问题。
哈希算法
MD5算法
MD5(Message-Digest Algorithm 5)是一种常用的哈希算法,它可以接受任意长度的输入(信息),并输出一个128位的哈希值,通常以32位十六进制数表示。
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Util {
/**
* 获取字符串的MD5哈希值
*
* @param data 输入字符串
* @return 32位十六进制MD5哈希值
* @throws NoSuchAlgorithmException 当MD5算法不可用时抛出
*/
public static String getMD5(String data) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(data.getBytes());
byte[] digest = md.digest();
return bytesToHex(digest);
}
/**
* 将字节数组转换为十六进制字符串
*
* @param bytes 字节数组
* @return 十六进制字符串
*/
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
// 工具类不应该有公共构造器
private MD5Util() {
}
// 主方法用于测试工具类
public static void main(String[] args) {
try {
String originalString = "Hello, World!";
String md5String = MD5Util.getMD5(originalString);
System.out.println("Original: " + originalString);
System.out.println("MD5 Hash: " + md5String);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
SHA-1算法
SHA-1(Secure Hash Algorithm 1)是一种加密哈希函数,它接收一个输入(信息)并输出一个160位的哈希值,通常以40位十六进制数表示。
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SHA1Util {
/**
* 获取字符串的SHA-1哈希值
*
* @param data 输入字符串
* @return 40位十六进制SHA-1哈希值
* @throws NoSuchAlgorithmException 当SHA-1算法不可用时抛出
*/
public static String getSHA1(String data) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(data.getBytes());
byte[] digest = md.digest();
return bytesToHex(digest);
}
/**
* 将字节数组转换为十六进制字符串
*
* @param bytes 字节数组
* @return 十六进制字符串
*/
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
// 工具类不应该有公共构造器
private SHA1Util() {
}
// 主方法用于测试工具类
public static void main(String[] args) {
try {
String originalString = "Hello, World!";
String sha1String = SHA1Util.getSHA1(originalString);
System.out.println("Original: " + originalString);
System.out.println("SHA-1 Hash: " + sha1String);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
SHA-256算法
它生成数据的固定长度(如256位)摘要,用于验证数据的完整性。
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SHA256Util {
/**
* 获取字符串的SHA-256哈希值
*
* @param data 输入字符串
* @return 64位十六进制SHA-256哈希值
* @throws NoSuchAlgorithmException 当SHA-256算法不可用时抛出
*/
public static String getSHA256(String data) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(data.getBytes());
byte[] digest = md.digest();
return bytesToHex(digest);
}
/**
* 将字节数组转换为十六进制字符串
*
* @param bytes 字节数组
* @return 十六进制字符串
*/
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
// 工具类不应该有公共构造器
private SHA256Util() {
}
// 主方法用于测试工具类
public static void main(String[] args) {
try {
String originalString = "Hello, World!";
String sha256String = SHA256Util.getSHA256(originalString);
System.out.println("Original: " + originalString);
System.out.println("SHA-256 Hash: " + sha256String);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
参考文章: