在软件开发中,数据加密是一个非常重要的环节,它能够帮助我们保护数据的安全性和隐私性。Java作为一门广泛使用的编程语言,提供了多种加密算法来满足不同的加密需求。本文将详细介绍Java中常用的几种加密算法,包括对称加密、非对称加密、散列算法以及一些特殊的加密算法,并提供相应的代码示例。
对称加密算法
对称加密算法是指加密和解密使用相同密钥的加密算法。常见的对称加密算法有AES、DES等。
AES(高级加密标准)
AES是一种广泛使用的对称加密算法,它支持128、192和256位的密钥长度。
代码示例:
java
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;public class AESUtil {private static final String AES = "AES";// 加密方法,data为明文,key为密钥public static byte[] encrypt(byte[] data, byte[] key) throws Exception {SecretKeySpec skeySpec = new SecretKeySpec(key, AES);Cipher cipher = Cipher.getInstance(AES);cipher.init(Cipher.ENCRYPT_MODE, skeySpec);return cipher.doFinal(data);}// 解密方法,data为密文,key为密钥public static byte[] decrypt(byte[] data, byte[] key) throws Exception {SecretKeySpec skeySpec = new SecretKeySpec(key, AES);Cipher cipher = Cipher.getInstance(AES);cipher.init(Cipher.DECRYPT_MODE, skeySpec);return cipher.doFinal(data);}public static void main(String[] args) throws Exception {KeyGenerator keyGen = KeyGenerator.getInstance(AES);keyGen.init(128); // 初始化密钥长度为128位SecretKey secretKey = keyGen.generateKey(); // 生成密钥byte[] key = secretKey.getEncoded(); // 获取密钥的字节数组String originalString = "Hello, World!"; // 原始字符串byte[] originalBytes = originalString.getBytes(); // 将字符串转换为字节数组byte[] encryptedBytes = encrypt(originalBytes, key); // 加密byte[] decryptedBytes = decrypt(encryptedBytes, key); // 解密System.out.println("原始字符串: " + originalString);System.out.println("加密后: " + new String(encryptedBytes));System.out.println("解密后: " + new String(decryptedBytes));}
}
非对称加密算法
非对称加密算法使用一对密钥,即公钥和私钥。常见的非对称加密算法有RSA、DSA等。
RSA(Rivest-Shamir-Adleman)
RSA是一种广泛使用的非对称加密算法,它能够提供良好的安全性。
代码示例:
java
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import javax.crypto.Cipher;public class RSAUtil {private static final String RSA = "RSA";// 获取KeyPairGenerator对象public static KeyPairGenerator getKeyPairGenerator() throws Exception {KeyPairGenerator keyGen = KeyPairGenerator.getInstance(RSA);keyGen.initialize(2048, SecureRandom.getInstanceStrong()); // 初始化密钥长度为2048位return keyGen;}// 加密方法,data为明文,publicKey为公钥public static byte[] encrypt(byte[] data, PublicKey publicKey) throws Exception {Cipher cipher = Cipher.getInstance(RSA);cipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.doFinal(data);}// 解密方法,data为密文,privateKey为私钥public static byte[] decrypt(byte[] data, PrivateKey privateKey) throws Exception {Cipher cipher = Cipher.getInstance(RSA);cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(data);}public static void main(String[] args) throws Exception {KeyPairGenerator keyPairGen = getKeyPairGenerator(); // 获取KeyPairGenerator对象KeyPair keyPair = keyPairGen.generateKeyPair(); // 生成密钥对PublicKey publicKey = keyPair.getPublic(); // 获取公钥PrivateKey privateKey = keyPair.getPrivate(); // 获取私钥String originalString = "Hello, World!"; // 原始字符串byte[] originalBytes = originalString.getBytes(); // 将字符串转换为字节数组byte[] encryptedBytes = encrypt(originalBytes, publicKey); // 加密byte[] decryptedBytes = decrypt(encryptedBytes, privateKey); // 解密System.out.println("原始字符串: " + originalString);System.out.println("加密后: " + new String(encryptedBytes));System.out.println("解密后: " + new String(decryptedBytes));}
}
散列算法
散列算法是一种单向加密算法,它将任意长度的数据映射到固定长度的值。常见的散列算法有MD5、SHA-1、SHA-256等。
SHA-256
SHA-256是一种安全散列算法,它产生256位(32字节)的散列值。
代码示例:
java
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class SHA256Util {// 计算字符串的SHA-256散列值public static String hash(String data) throws NoSuchAlgorithmException {MessageDigest digest = MessageDigest.getInstance("SHA-256");byte[] hash = digest.digest(data.getBytes());StringBuilder hexString = new StringBuilder();for (byte b : hash) {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) throws NoSuchAlgorithmException {String originalString = "Hello, World!"; // 原始字符串System.out.println("原始字符串: " + originalString);System.out.println("SHA-256 散列值: " + hash(originalString));}
}
特殊加密算法
UUID(Universally Unique Identifier)
UUID是一种生成唯一标识符的算法,常用于生成不重复的ID。
代码示例:
java
import java.util.UUID;public class UUIDUtil {// 生成UUIDpublic static String generateUUID() {return UUID.randomUUID().toString();}public static void main(String[] args) {System.out.println("UUID: " + generateUUID());}
}
雪花算法(Snowflake)
雪花算法是一种用于生成唯一ID的算法,由Twitter开发。
代码示例:
java复制
public class SnowflakeIdWorker {// 省略了部分实现细节,这里只提供核心逻辑的示例private final long twepoch = 1288834974657L; // 起始时间戳private final long workerIdBits = 5L; // 机器ID所占位数private final long datacenterIdBits = 5L; // 数据中心ID所占位数private final long maxWorkerId = -1L ^ (-1L << workerIdBits); // 最大机器IDprivate final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); // 最大数据中心IDprivate final long sequenceBits = 12L; // 序列号所占位数private final long workerIdShift = sequenceBits; // 机器ID左移位数private final long datacenterIdShift = sequenceBits + workerIdBits; // 数据中心ID左移位数private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; // 时间戳左移位数private final long sequenceMask = -1L ^ (-1L << sequenceBits); // 序列号掩码private long workerId;private long datacenterId;private long sequence = 0L; // 0,并发控制private long lastTimestamp = -1L; // 上次生成ID的时间戳public SnowflakeIdWorker(long workerId, long datacenterId) {if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}this.workerId = workerId;this.datacenterId = datacenterId;}// 生成IDpublic synchronized long nextId() {long timestamp = timeGen();if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}if (lastTimestamp == timestamp) {sequence = (sequence + 1) & sequenceMask; // 通过&运算计算sequence的循环if (sequence == 0) {timestamp = tilNextMillis(lastTimestamp); // 计算下一个时间戳}} else {sequence = 0L; // 时间戳改变,重置sequence}lastTimestamp = timestamp; // 更新上次生成ID的时间戳// 时间戳部分 | 数据中心部分 | 机器ID部分 | 序列号部分的组合return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;}// 阻塞到下一个时间戳protected long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}// 返回当前时间戳protected long timeGen() {return System.currentTimeMillis();}public static void main(String[] args) {SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0); // 0和0是示例值,实际使用 时需要替换for (int i = 0; i < 1000; i++) {long id = idWorker.nextId(); // 生成IDSystem.out.println(Long.toBinaryString(id)); // 打印二进制形式的IDSystem.out.println(id); // 打印ID}
}