当前位置: 首页 > news >正文

对称加密详解

对称加密详解

对称加密是一种使用​​相同密钥​​进行加密和解密的加密方法。下面我将从原理、算法、应用场景到代码实现全面介绍对称加密。

基本概念

核心特征

  • ​单一密钥​​:加密和解密使用同一个密钥

  • ​加解密速度快​​:相比非对称加密快几个数量级

  • ​适合大数据量加密​​:常用于文件加密、网络通信加密等场景

加密过程

明文 + 密钥 → [加密算法] → 密文

解密过程

密文 + 密钥 → [解密算法] → 明文

主要对称加密算法

1. DES (Data Encryption Standard)

  • ​密钥长度​​:56位(已不安全)

  • ​分组大小​​:64位

  • ​现状​​:已被破解,不推荐使用

2. 3DES (Triple DES)

  • ​原理​​:对每个数据块应用三次DES加密

  • ​密钥长度​​:112位或168位

  • ​现状​​:仍在使用但逐渐被淘汰

3. AES (Advanced Encryption Standard)

  • ​密钥长度​​:128位、192位、256位

  • ​分组大小​​:128位

  • ​现状​​:目前最常用的对称加密算法,安全高效

4. ChaCha20

  • ​流密码算法​​:特别适合移动设备

  • ​性能优秀​​:在缺乏AES硬件加速的设备上表现更好

 

AES加密解密完整示例

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;/*** AES对称加密工具类* 支持GCM模式(推荐,提供完整性验证)*/
public class AESEncryption {// AES密钥长度private static final int AES_KEY_SIZE = 256;// GCM认证标签长度private static final int GCM_TAG_LENGTH = 128;// GCM IV长度private static final int GCM_IV_LENGTH = 12; // 推荐12字节/*** 生成AES密钥*/public static SecretKey generateKey() throws Exception {KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");keyGenerator.init(AES_KEY_SIZE);return keyGenerator.generateKey();}/*** 从Base64字符串恢复密钥*/public static SecretKey loadKey(String base64Key) {byte[] decodedKey = Base64.getDecoder().decode(base64Key);return new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");}/*** AES-GCM加密(推荐使用)* GCM模式提供机密性和完整性验证*/public static String encryptGCM(String plaintext, SecretKey key) throws Exception {// 生成随机IVbyte[] iv = new byte[GCM_IV_LENGTH];SecureRandom random = new SecureRandom();random.nextBytes(iv);// 初始化加密器Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");GCMParameterSpec parameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);// 执行加密byte[] ciphertext = cipher.doFinal(plaintext.getBytes("UTF-8"));// 组合IV和密文:IV + 密文byte[] encryptedData = new byte[iv.length + ciphertext.length];System.arraycopy(iv, 0, encryptedData, 0, iv.length);System.arraycopy(ciphertext, 0, encryptedData, iv.length, ciphertext.length);return Base64.getEncoder().encodeToString(encryptedData);}/*** AES-GCM解密*/public static String decryptGCM(String encryptedData, SecretKey key) throws Exception {byte[] decodedData = Base64.getDecoder().decode(encryptedData);// 分离IV和密文byte[] iv = new byte[GCM_IV_LENGTH];byte[] ciphertext = new byte[decodedData.length - GCM_IV_LENGTH];System.arraycopy(decodedData, 0, iv, 0, iv.length);System.arraycopy(decodedData, iv.length, ciphertext, 0, ciphertext.length);// 初始化解密器Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");GCMParameterSpec parameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);// 执行解密byte[] plaintext = cipher.doFinal(ciphertext);return new String(plaintext, "UTF-8");}/*** AES-CBC加密(兼容性更好)*/public static String encryptCBC(String plaintext, SecretKey key) throws Exception {// 生成随机IVbyte[] iv = new byte[16]; // AES块大小是16字节SecureRandom random = new SecureRandom();random.nextBytes(iv);Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, key, new javax.crypto.spec.IvParameterSpec(iv));byte[] ciphertext = cipher.doFinal(plaintext.getBytes("UTF-8"));// 组合IV和密文byte[] encryptedData = new byte[iv.length + ciphertext.length];System.arraycopy(iv, 0, encryptedData, 0, iv.length);System.arraycopy(ciphertext, 0, encryptedData, iv.length, ciphertext.length);return Base64.getEncoder().encodeToString(encryptedData);}/*** AES-CBC解密*/public static String decryptCBC(String encryptedData, SecretKey key) throws Exception {byte[] decodedData = Base64.getDecoder().decode(encryptedData);byte[] iv = new byte[16];byte[] ciphertext = new byte[decodedData.length - 16];System.arraycopy(decodedData, 0, iv, 0, iv.length);System.arraycopy(decodedData, iv.length, ciphertext, 0, ciphertext.length);Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, key, new javax.crypto.spec.IvParameterSpec(iv));byte[] plaintext = cipher.doFinal(ciphertext);return new String(plaintext, "UTF-8");}/*** 密钥转换为Base64字符串(用于存储或传输)*/public static String keyToString(SecretKey key) {return Base64.getEncoder().encodeToString(key.getEncoded());}
}/*** 使用示例和测试类*/
class AESExample {public static void main(String[] args) {try {System.out.println("=== AES对称加密演示 ===\n");// 1. 生成密钥SecretKey key = AESEncryption.generateKey();String keyString = AESEncryption.keyToString(key);System.out.println("生成的AES密钥: " + keyString.substring(0, 32) + "...");String originalText = "这是一段需要加密的敏感数据!Secret message: Hello World!";System.out.println("原始文本: " + originalText);System.out.println("原始文本长度: " + originalText.length() + " 字符");// 2. 使用GCM模式加密(推荐)System.out.println("\n--- GCM模式加密 ---");String encryptedGCM = AESEncryption.encryptGCM(originalText, key);System.out.println("加密后: " + encryptedGCM.substring(0, 50) + "...");String decryptedGCM = AESEncryption.decryptGCM(encryptedGCM, key);System.out.println("解密后: " + decryptedGCM);System.out.println("GCM解密验证: " + originalText.equals(decryptedGCM));// 3. 使用CBC模式加密System.out.println("\n--- CBC模式加密 ---");String encryptedCBC = AESEncryption.encryptCBC(originalText, key);System.out.println("加密后: " + encryptedCBC.substring(0, 50) + "...");String decryptedCBC = AESEncryption.decryptCBC(encryptedCBC, key);System.out.println("解密后: " + decryptedCBC);System.out.println("CBC解密验证: " + originalText.equals(decryptedCBC));// 4. 从字符串恢复密钥测试System.out.println("\n--- 密钥恢复测试 ---");SecretKey restoredKey = AESEncryption.loadKey(keyString);String testEncrypted = AESEncryption.encryptGCM("测试密钥恢复", restoredKey);String testDecrypted = AESEncryption.decryptGCM(testEncrypted, restoredKey);System.out.println("密钥恢复测试: " + "测试密钥恢复".equals(testDecrypted));// 5. 性能测试System.out.println("\n--- 性能测试 ---");performanceTest(key);} catch (Exception e) {e.printStackTrace();}}private static void performanceTest(SecretKey key) throws Exception {// 生成1MB测试数据StringBuilder testData = new StringBuilder();for (int i = 0; i < 10000; i++) {testData.append("这是一段测试数据用于性能评估。");}String largeText = testData.toString();long startTime = System.currentTimeMillis();int iterations = 10;for (int i = 0; i < iterations; i++) {String encrypted = AESEncryption.encryptGCM(largeText, key);AESEncryption.decryptGCM(encrypted, key);}long endTime = System.currentTimeMillis();double avgTime = (endTime - startTime) / (double) iterations;System.out.printf("加密解密 %d KB 数据平均耗时: %.2f 毫秒%n", largeText.length() / 1024, avgTime);System.out.printf("吞吐量: %.2f MB/秒%n", (largeText.length() / (1024.0 * 1024)) / (avgTime / 1000.0));}
}/*** 文件加密工具类*/
class FileEncryptionTool {private static final int BUFFER_SIZE = 8192;/*** 加密文件*/public static void encryptFile(String inputFile, String outputFile, SecretKey key) throws Exception {try (java.io.FileInputStream fis = new java.io.FileInputStream(inputFile);java.io.FileOutputStream fos = new java.io.FileOutputStream(outputFile)) {// 生成随机IVbyte[] iv = new byte[16];SecureRandom random = new SecureRandom();random.nextBytes(iv);// 写入IV到文件开头fos.write(iv);Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, key, new javax.crypto.spec.IvParameterSpec(iv));try (javax.crypto.CipherOutputStream cos = new javax.crypto.CipherOutputStream(fos, cipher)) {byte[] buffer = new byte[BUFFER_SIZE];int bytesRead;while ((bytesRead = fis.read(buffer)) != -1) {cos.write(buffer, 0, bytesRead);}}}}/*** 解密文件*/public static void decryptFile(String inputFile, String outputFile, SecretKey key) throws Exception {try (java.io.FileInputStream fis = new java.io.FileInputStream(inputFile);java.io.FileOutputStream fos = new java.io.FileOutputStream(outputFile)) {// 读取IVbyte[] iv = new byte[16];if (fis.read(iv) != iv.length) {throw new IllegalStateException("文件已损坏或格式不正确");}Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, key, new javax.crypto.spec.IvParameterSpec(iv));try (javax.crypto.CipherOutputStream cos = new javax.crypto.CipherOutputStream(fos, cipher)) {byte[] buffer = new byte[BUFFER_SIZE];int bytesRead;while ((bytesRead = fis.read(buffer)) != -1) {cos.write(buffer, 0, bytesRead);}}}}
}

对称加密的工作模式

1. ECB (Electronic Codebook) - 不推荐

  • 每个块独立加密

  • 相同明文块产生相同密文块

  • 安全性差,会暴露数据模式

2. CBC (Cipher Block Chaining) - 常用

  • 每个明文块与前一个密文块进行异或操作

  • 需要初始化向量(IV)

  • 提供更好的安全性

3. GCM (Galois/Counter Mode) - 推荐

  • 提供机密性和完整性验证

  • 并行计算,性能好

  • 现代应用的首选模式

安全最佳实践

1. 密钥管理

// 安全的密钥生成
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256, SecureRandom.getInstanceStrong()); // 使用强随机数

2. IV使用原则

  • ​不要重复使用IV​​:每次加密使用随机IV

  • ​IV不需要保密​​:但必须不可预测

  • ​GCM模式IV​​:推荐12字节长度

3. 认证加密

优先选择提供认证的加密模式(如GCM),避免仅使用加密模式(如CBC)而不进行完整性验证。

对称加密 vs 非对称加密

特性

对称加密

非对称加密

密钥数量

1个共享密钥

公钥+私钥对

速度

快(适合大数据量)

慢(比对称加密慢100-1000倍)

主要用途

数据加密

密钥交换、数字签名

典型算法

AES, ChaCha20

RSA, ECC

实际应用场景

  1. ​HTTPS通信​​:使用对称加密加密实际数据传输

  2. ​文件加密​​:加密存储敏感文件

  3. ​数据库字段加密​​:保护数据库中的敏感数据

  4. ​消息加密​​:即时通讯应用的消息加密

对称加密是现代密码学的基石,正确使用对称加密可以有效地保护数据的机密性。在实际应用中,通常会将对称加密与非对称加密结合使用,发挥各自优势。

http://www.dtcms.com/a/475611.html

相关文章:

  • 8.5JavaScript函数 arguments
  • 免费网站建设c3sales给帅哥做奴视频网站地址
  • 中英文外贸网站源码代做效果图网站哪家好
  • 【Swift】LeetCode 15. 三数之和
  • 做网站表格单边框标记南通建设局网站查询
  • 百度正版下载恢复百度莱阳seo排名
  • 利用AI工具生成毕业论文,并智能管理相关文献资源。
  • erp网站建设方案asp自动获取网站快照 网站缩略图
  • 做网站为什么要备案照相石家庄网站排名推广
  • 机器学习实践项目(一)- Rossman商店销售预测 - 模型训练
  • 200M电信宽带做网站济南品牌网站建设价格低
  • 没后台的网站怎么做优化博物馆设计公司排名
  • 西部数码域名备案seo技术导航
  • 做的网站没有手机版网站如何推广好
  • 用网站做淘宝客的人多吗会员管理系统免费版
  • 网站建设仟首选金手指制作企业网站的新闻
  • 上海网站建设百度推广公司哪家好wordpress文章在哪
  • 重庆云诚度网站建设关键词排名优化教程
  • seo移动网站页面怎么做怎么在网站里做网页
  • 公司网站建设为什么不直接买模版h5招聘模板免费
  • 360搜索怎么做网站优化seo一个关键词多少钱
  • 开平市城乡建设局网站搜索引擎营销的主要方法包括
  • 类与对象 -- 日期类实现
  • 网站一键生成wapwordpress模板安装
  • 新能源网站建设哪家好门户网站建设要多少钱
  • 网站风格 颜色搭配美橙网站建设经典案例
  • 网站功能建设特点广西壮族自治区市场监督管理局
  • 【Bean】条件装配与动态注册
  • 做厨具公司网站广州开发网站
  • 网站建设编程时注意事项网站设计开发制作