加密与解密完全指南,使用Java实现

news2025/5/9 18:34:21

文章目录

    • 1. 加密基础知识
      • 1.1 什么是加密?
      • 1.2 加密的历史简介
        • 1.2.1 古典加密
        • 1.2.2 现代加密的起源
      • 1.3 加密的基本概念
        • 1.3.1 密码学中的关键术语
        • 1.3.2 加密的基本原则
      • 1.4 加密的分类
        • 1.4.1 对称加密(Symmetric Encryption)
        • 1.4.2 非对称加密(Asymmetric Encryption)
        • 1.4.3 哈希函数(Hash Functions)
      • 1.5 加密的核心特性
    • 2. 对称加密详解
      • 2.1 对称加密的工作原理
      • 2.2 对称加密的分类
        • 2.2.1 块加密(Block Ciphers)
        • 2.2.2 流加密(Stream Ciphers)
      • 2.3 常用对称加密算法详解
        • 2.3.1 DES(Data Encryption Standard)
        • 2.3.2 3DES(Triple DES)
        • 2.3.3 AES(Advanced Encryption Standard)
        • 2.3.4 Blowfish
      • 2.4 对称加密的优缺点
        • 2.4.1 优点
        • 2.4.2 缺点
      • 2.5 对称加密的实际应用场景
      • 2.6 对称加密中的填充
      • 2.7 对称加密密钥生成
    • 3. 非对称加密详解
      • 3.1 非对称加密的工作原理
      • 3.2 常用非对称加密算法
        • 3.2.1 RSA(Rivest-Shamir-Adleman)
        • 3.2.2 ECC(Elliptic Curve Cryptography)
        • 3.2.3 DSA(Digital Signature Algorithm)
        • 3.2.4 DH(Diffie-Hellman)
      • 3.3 非对称加密的优缺点
        • 3.3.1 优点
        • 3.3.2 缺点
      • 3.4 非对称加密的实际应用场景
      • 3.5 混合加密系统
    • 4. 散列算法详解
      • 4.1 散列算法的特性
      • 4.2 常用散列算法
        • 4.2.1 MD5(Message Digest Algorithm 5)
        • 4.2.2 SHA(Secure Hash Algorithm)系列
        • 4.2.3 HMAC(Hash-based Message Authentication Code)
      • 4.3 散列算法的实际应用
      • 4.4 安全的密码散列
        • 4.4.1 盐(Salt)
        • 4.4.2 常用的密码散列算法
    • 5. 数字签名详解
      • 5.1 数字签名的工作原理
      • 5.2 数字签名的特性
      • 5.3 常用数字签名算法
        • 5.3.1 RSA签名
        • 5.3.2 DSA签名
        • 5.3.3 ECDSA(Elliptic Curve Digital Signature Algorithm)
      • 5.4 数字签名的应用场景
      • 5.5 JAR文件签名示例
    • 6. 常见加密标准和协议
      • 6.1 SSL/TLS协议
        • 6.1.1 工作原理
        • 6.1.2 Java中的SSL/TLS示例
      • 6.2 OpenPGP
      • 6.3 X.509证书
      • 6.4 PKCS(公钥加密标准)
    • 7. Java加解密应用与实践
      • 7.1 Java加密架构(JCA)概述
      • 7.2 文件加密解密实用例子
      • 7.3 安全密码存储
      • 7.4 数据签名与验证
      • 7.5 安全的客户端-服务器通信
      • 7.6 加密配置信息
    • 8. 加密在实际场景中的应用
      • 8.1 网络安全应用
        • 8.1.1 HTTPS/TLS
        • 8.1.2 VPN (虚拟专用网络)
        • 8.1.3 SSH (安全Shell)
      • 8.2 数据存储安全
        • 8.2.1 全盘加密
        • 8.2.2 数据库加密
        • 8.2.3 云存储加密
      • 8.3 身份验证和访问控制
        • 8.3.1 密码存储
        • 8.3.2 多因素认证
        • 8.3.3 OAuth和JWT
      • 8.4 移动和物联网安全
        • 8.4.1 移动应用数据加密
        • 8.4.2 物联网设备安全
      • 8.5 区块链和加密货币
    • 9. 加密实践的常见问题与解决方案
      • 9.1 密钥管理挑战
      • 9.2 加密算法选择错误
      • 9.3 实施缺陷和漏洞
      • 9.4 加密过度使用导致性能问题
      • 9.5 合规性和法律考虑

1. 加密基础知识

1.1 什么是加密?

加密是将明文信息转换为难以理解的密文的过程,目的是保护信息的机密性。只有拥有正确密钥的人才能将密文转换回明文,这个过程称为解密。

明文 + 加密算法 + 密钥 = 密文
密文 + 解密算法 + 密钥 = 明文

1.2 加密的历史简介

1.2.1 古典加密

最早的加密可以追溯到古埃及时期,大约公元前1900年。随着时间的推移,出现了各种加密方法:

  • 凯撒密码:古罗马时期的简单替换密码,由朱利叶斯·凯撒使用。它通过将字母表中的每个字母移动固定位置来加密信息。

    例如,位移量为3的凯撒密码:

    明文:HELLO
    密文:KHOOR (每个字母在字母表中向后移动3位)
    
  • 维吉尼亚密码:16世纪出现的多表替换密码,使用一系列不同的凯撒密码来加密消息的不同部分。

1.2.2 现代加密的起源

二战期间,加密技术得到了极大发展,特别是德国的恩尼格玛机(Enigma machine)和英国破解恩尼格玛密码的努力。计算机时代的到来彻底改变了加密领域,1970年代出现了现代加密的两个重要里程碑:

  • DES(数据加密标准):1977年由美国国家标准与技术研究院(NIST)发布
  • RSA算法:1977年由Rivest、Shamir和Adleman三位密码学家发明的第一个实用的公钥加密系统

1.3 加密的基本概念

1.3.1 密码学中的关键术语
  • 明文(Plaintext):原始、可读的信息
  • 密文(Ciphertext):经过加密后的、不可读的信息
  • 加密(Encryption):将明文转换为密文的过程
  • 解密(Decryption):将密文转换回明文的过程
  • 密钥(Key):控制加密和解密操作的参数
  • 密码算法(Cipher):执行加密和解密的数学函数或算法
1.3.2 加密的基本原则
  1. 克克霍夫原则:即使加密系统的所有细节(除了密钥)都是公开的,系统也应该是安全的
  2. 香农理论:完美的加密系统需要密钥长度至少与明文一样长
  3. 计算安全性:实际的加密系统依赖于计算难题,使得在合理的时间内无法破解

1.4 加密的分类

加密主要分为三大类:

1.4.1 对称加密(Symmetric Encryption)

使用同一个密钥进行加密和解密。

特点

  • 速度快,适合大量数据加密
  • 需要安全地共享密钥
  • 代表算法:AES, DES, 3DES, Blowfish
1.4.2 非对称加密(Asymmetric Encryption)

使用一对密钥:公钥和私钥。公钥用于加密,私钥用于解密。

特点

  • 解决了密钥分发问题
  • 计算密集型,速度较慢
  • 代表算法:RSA, DSA, ECC, ElGamal
1.4.3 哈希函数(Hash Functions)

将任意长度的输入转换为固定长度的输出,且不可逆。

特点

  • 不使用密钥
  • 无法从哈希值恢复原始数据
  • 用于验证数据完整性
  • 代表算法:MD5, SHA-1, SHA-256, SHA-3

1.5 加密的核心特性

现代加密系统通常提供以下四种核心安全服务:

  1. 机密性(Confidentiality):确保只有授权方可以读取信息
  2. 完整性(Integrity):确保信息在传输过程中未被修改
  3. 认证(Authentication):确认信息来源的真实性
  4. 不可否认性(Non-repudiation):防止发送方否认曾发送过信息

2. 对称加密详解

对称加密是最古老、最直观的加密形式,也称为"共享密钥加密"或"秘密密钥加密"。

2.1 对称加密的工作原理

在对称加密中,加密和解密使用同一个密钥:

  1. 发送方使用密钥和加密算法将明文转换为密文
  2. 接收方使用同一个密钥和解密算法将密文转换回明文
加密:明文 + 密钥 + 算法 = 密文
解密:密文 + 密钥 + 算法 = 明文

2.2 对称加密的分类

对称加密算法主要分为两类:

2.2.1 块加密(Block Ciphers)

将明文分成固定大小的块,然后对每个块进行加密。最常见的块大小是64位和128位。

主要算法

  • DES(Data Encryption Standard)
  • 3DES(Triple DES)
  • AES(Advanced Encryption Standard)
  • Blowfish
  • Twofish

工作模式
块加密有多种工作模式,每种模式有不同的安全属性:

  • ECB(Electronic Codebook):最简单的模式,直接对每个块加密,但安全性较低
  • CBC(Cipher Block Chaining):每个块与前一个密文块异或后再加密
  • CFB(Cipher Feedback):将密码算法转换为流密码
  • OFB(Output Feedback):类似CFB,但使用加密输出而非密文进行反馈
  • CTR(Counter):将块密码转换为流密码,使用计数器确保每个块使用不同的输入
2.2.2 流加密(Stream Ciphers)

一次加密一位或一字节数据,通常使用伪随机密钥流(keystream)与明文进行异或操作。

主要算法

  • RC4(Rivest Cipher 4)
  • ChaCha20
  • A5/1, A5/2(用于GSM通信)
  • SNOW 3G(用于3G网络)

2.3 常用对称加密算法详解

2.3.1 DES(Data Encryption Standard)

简介:1977年成为美国联邦标准的第一个公开加密算法。

特点

  • 块大小:64位
  • 密钥长度:56位(实际为64位,但8位用于奇偶校验)
  • 轮数:16轮
  • 目前被认为不安全,因为56位密钥可以通过暴力破解

Java示例

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class DESExample {
   
    public static void main(String[] args) throws Exception {
   
        // 生成DES密钥
        KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
        SecretKey secretKey = keyGenerator.generateKey();
        
        // 获取密钥的字节表示
        byte[] keyBytes = secretKey.getEncoded();
        
        // 创建DES密钥规范
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "DES");
        
        // 创建加密器
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        
        // 加密
        String plainText = "Hello, DES!";
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
        String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
        System.out.println("加密后: " + encryptedText);
        
        // 解密
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
        String decryptedText = new String(decryptedBytes);
        System.out.println("解密后: " + decryptedText);
    }
}
2.3.2 3DES(Triple DES)

简介:为增强DES安全性而开发,使用三重DES加密。

特点

  • 块大小:64位
  • 密钥长度:112位或168位(取决于是使用两个还是三个不同密钥)
  • 操作:对每个数据块应用三次DES(加密-解密-加密或加密-加密-加密)
  • 比DES安全,但比AES慢

Java示例

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class TripleDESExample {
   
    public static void main(String[] args) throws Exception {
   
        // 生成3DES密钥
        KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede"); // DESede = Triple DES
        SecretKey secretKey = keyGenerator.generateKey();
        
        // 获取密钥的字节表示
        byte[] keyBytes = secretKey.getEncoded();
        
        // 创建3DES密钥规范
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "DESede");
        
        // 创建加密器
        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        
        // 加密
        String plainText = "Hello, Triple DES!";
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
        String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
        System.out.println("加密后: " + encryptedText);
        
        // 解密
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
        String decryptedText = new String(decryptedBytes);
        System.out.println("解密后: " + decryptedText);
    }
}
2.3.3 AES(Advanced Encryption Standard)

简介:2001年成为新的加密标准,取代了DES。由Rijndael算法改编而来。

特点

  • 块大小:128位
  • 密钥长度:128位、192位或256位
  • 轮数:取决于密钥长度(128位密钥为10轮,192位为12轮,256位为14轮)
  • 高效、安全,目前是最广泛使用的对称加密算法

Java示例

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

public class AESExample {
   
    public static void main(String[] args) throws Exception {
   
        // 生成AES密钥
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(256); // 使用256位密钥
        SecretKey secretKey = keyGenerator.generateKey();
        
        // 获取密钥的字节表示
        byte[] keyBytes = secretKey.getEncoded();
        
        // 创建AES密钥规范
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        
        // 创建初始化向量IV(使用CBC模式时需要)
        byte[] ivBytes = new byte[16];
        new SecureRandom().nextBytes(ivBytes);
        IvParameterSpec iv = new IvParameterSpec(ivBytes);
        
        // 创建加密器,使用CBC模式和PKCS5填充
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        
        // 加密
        String plainText = "Hello, AES!";
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
        
        // 将加密结果和IV一起编码
        String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
        String ivText = Base64.getEncoder().encodeToString(ivBytes);
        System.out.println("加密后: " + encryptedText);
        System.out.println("初始化向量: " + ivText);
        
        // 解密
        cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
        String decryptedText = new String(decryptedBytes);
        System.out.println("解密后: " + decryptedText);
    }
}
2.3.4 Blowfish

简介:1993年由Bruce Schneier设计的快速块加密算法。

特点

  • 块大小:64位
  • 可变密钥长度:32位到448位
  • 轮数:16轮
  • 设计简单,实现高效

Java示例

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class BlowfishExample {
   
    public static void main(String[] args) throws Exception {
   
        // 生成Blowfish密钥
        KeyGenerator keyGenerator = KeyGenerator.getInstance("Blowfish");
        keyGenerator.init(128); // 使用128位密钥
        SecretKey secretKey = keyGenerator.generateKey();
        
        // 获取密钥的字节表示
        byte[] keyBytes = secretKey.getEncoded();
        
        // 创建Blowfish密钥规范
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "Blowfish");
        
        // 创建加密器
        Cipher cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
        
        // 加密
        String plainText = "Hello, Blowfish!";
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
        String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
        System.out.println("加密后: " + encryptedText);
        
        // 解密
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
        String decryptedText = new String(decryptedBytes);
        System.out.println("解密后: " + decryptedText);
    }
}

2.4 对称加密的优缺点

2.4.1 优点
  • 速度快:对称加密算法通常非常高效,特别适合加密大量数据
  • 实现简单:算法相对简单,易于实现
  • 安全性高:当使用足够长的密钥时,提供很高的安全性
2.4.2 缺点
  • 密钥分发问题:安全地共享密钥是一个主要挑战
  • 密钥管理复杂:随着通信方数量增加,需要管理的密钥数量呈指数增长
  • 不提供真正的认证:不能确认信息的来源

2.5 对称加密的实际应用场景

  • 文件加密:保护存储在硬盘或云存储中的敏感文件
  • 数据库加密:加密存储在数据库中的敏感数据
  • 通信加密:TLS/SSL协议中的会话加密
  • 硬盘加密:BitLocker、FileVault等全盘加密解决方案
  • VPN通信:虚拟专用网络中的数据加密

2.6 对称加密中的填充

当明文长度不是块大小的整数倍时,需要使用填充(Padding)来补齐最后一个块。常见的填充方案包括:

  • PKCS#7/PKCS#5 Padding:添加n个值为n的字节(n是需要填充的字节数)
  • ISO/IEC 7816-4 Padding:添加一个值为0x80的字节,其余填充0x00
  • ANSI X.923 Padding:最后一个字节表示填充的字节数,其余填充0x00
  • Zero Padding:简单地用0填充

Java中的填充示例

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class PaddingExample {
   
    public static void main(String[] args) throws Exception {
   
        // 创建一个简单的AES密钥
        byte[] keyBytes = "0123456789abcdef".getBytes();
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        
        // 测试不同的填充方式
        String plainText = "测试填充";
        String[] paddings = {
   "AES/ECB/PKCS5Padding", "AES/ECB/NoPadding"};
        
        for (String padding : paddings) {
   
            try {
   
                Cipher cipher = Cipher.getInstance(padding);
                cipher.init(Cipher.ENCRYPT_MODE, keySpec);
                
                // 加密
                byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
                String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
                System.out.println(padding + " 加密结果: " + encryptedText);
                System.out.println(padding + " 加密结果长度: " + encryptedBytes.length + " 字节");
                
                // 解密
                cipher.init(Cipher.DECRYPT_MODE, keySpec);
                byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
                String decryptedText = new String(decryptedBytes);
                System.out.println(padding + " 解密结果: " + decryptedText);
                System.out.println();
            } catch (Exception e) {
   
                System.out.println(padding + " 错误: " + e.getMessage());
                System.out.println();
            }
        }
    }
}

2.7 对称加密密钥生成

在实际应用中,密钥应该是真正随机的。Java提供了几种方法来生成安全的随机密钥:

使用KeyGenerator生成密钥

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

public class KeyGenerationExample {
   
    public static void main(String[] args) throws NoSuchAlgorithmException {
   
        // 为AES生成128位密钥
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(128, SecureRandom.getInstanceStrong());
        SecretKey secretKey = keyGen.generateKey();
        
        // 输出密钥的Base64编码表示
        String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());
        System.out.println("生成的AES密钥: " + encodedKey);
        
        // 为Blowfish生成256位密钥
        keyGen = KeyGenerator.getInstance("Blowfish");
        keyGen.init(256, SecureRandom.getInstanceStrong());
        secretKey = keyGen.generateKey();
        
        // 输出密钥的Base64编码表示
        encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());
        System.out.println("生成的Blowfish密钥: " + encodedKey);
    }
}

使用密码生成密钥

在实际应用中,有时需要从用户密码生成密钥,这通常通过密钥派生函数(KDF)如PBKDF2实现:

import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Base64;

public class PasswordBasedKeyExample {
   
    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException {
   
        // 用户密码和盐值
        String password = "user_password";
        byte[] salt = "random_salt".getBytes();
        
        // 使用PBKDF2生成密钥
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
        SecretKey tmp = factory.generateSecret(spec);
        SecretKey secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
        
        // 输出密钥的Base64编码表示
        String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());
        System.out.println("从密码生成的AES密钥: " + encodedKey);
    }
}

3. 非对称加密详解

与对称加密不同,非对称加密(也称为公钥加密)使用一对密钥:公钥和私钥。公钥可以自由分发,而私钥必须保密。

3.1 非对称加密的工作原理

非对称加密基于数学问题,如大整数分解和离散对数:

  1. 加密:使用接收方的公钥加密消息,只有拥有对应私钥的接收方才能解密
  2. 数字签名:使用发送方的私钥对消息进行签名,任何人都可以使用发送方的公钥验证签名的真实性
加密:明文 + 接收方公钥 = 密文
解密:密文 + 接收方私钥 = 明文

签名:消息 + 发送方私钥 = 数字签名
验证:消息 + 数字签名 + 发送方公钥 = 真/假

3.2 常用非对称加密算法

3.2.1 RSA(Rivest-Shamir-Adleman)

简介:1977年发明,是第一个既可用于加密又可用于数字签名的算法。

工作原理

  • 基于大整数分解的难题
  • 密钥生成涉及选择两个大素数并计算它们的乘积
  • 安全性取决于大整数分解的计算困难性

特点

  • 密钥长度:通常为1024、2048或4096位
  • 加密消息的大小有限制
  • 比对称加密慢100-1000倍
  • 广泛用于安全通信和数字签名

Java示例(密钥生成、加密和解密)

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
import javax.crypto.Cipher;

public class RSAExample {
   
    public static void main(String[] args) throws Exception {
   
        // 生成RSA密钥对
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048); // 使用2048位密钥
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();
        
        // 打印密钥
        System.out.println("公钥: " + Base64.getEncoder().encodeToString(publicKey.getEncoded()));
        System.out.println("私钥: " + Base64.getEncoder().encodeToString(privateKey.getEncoded()));
        
        // 加密
        String plainText = "Hello, RSA!";
        Cipher encryptCipher = Cipher.getInstance("RSA");
        encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedBytes = encryptCipher.doFinal(plainText.getBytes());
        String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
        System.out.println("加密后: " + encryptedText);
        
        // 解密
        Cipher decryptCipher = Cipher.getInstance("RSA");
        decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = decryptCipher.doFinal(Base64.getDecoder().decode(encryptedText));
        String decryptedText = new String(decryptedBytes);
        System.out.println("解密后: " + decryptedText);
    }
}

RSA数字签名示例

import java.security.*;
import java.util.Base64;

public class RSASignatureExample {
   
    public static void main(String[] args) throws Exception {
   
        // 生成RSA密钥对
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        
        // 要签名的数据
        String data = "这是需要签名的重要文档";
        
        // 签名
        byte[] signature = sign(data.getBytes(), privateKey);
        System.out.println("签名: " + Base64.getEncoder().encodeToString(signature));
        
        // 验证签名
        boolean isValid = verify(data.getBytes(), signature, publicKey);
        System.out.println("签名验证: " + (isValid ? "有效" : "无效"));
        
        // 验证被篡改的数据
        String tamperedData = "这是被篡改的重要文档";
        boolean isTamperedValid = verify(tamperedData.getBytes(), signature, publicKey);
        System.out.println("篡改数据签名验证: " + (isTamperedValid ? "有效" : "无效"));
    }
    
    // 使用私钥签名数据
    public static byte[] sign(byte[] data, PrivateKey privateKey) throws Exception {
   
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(data);
        return signature.sign();
    }
    
    // 使用公钥验证签名
    public static boolean verify(byte[] data, byte[] signatureBytes, PublicKey publicKey) throws Exception {
   
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(signatureBytes);
    }
}
3.2.2 ECC(Elliptic Curve Cryptography)

简介:基于椭圆曲线数学的加密算法,与RSA相比,提供相同安全性但使用更短的密钥。

工作原理

  • 基于椭圆曲线上的离散对数问题
  • 使用点乘法进行加密操作

特点

  • 密钥长度短:224-521位的ECC密钥提供与2048-15360位RSA密钥相当的安全性
  • 计算效率高
  • 特别适合资源受限的设备,如智能卡和移动设备

Java示例(ECDSA数字签名)

import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;

public class ECDSASignatureExample {
   
    public static void main(String[] args) throws Exception {
   
        // 生成EC密钥对
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
        ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1");
        keyPairGenerator.initialize(ecSpec);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        
        // 要签名的数据
        String data = "使用ECDSA算法签名的数据";
        
        // 签名
        byte[] signature = sign(data.getBytes(), privateKey);
        System.out.println("ECDSA签名: " + Base64.getEncoder().encodeToString(signature));
        
        // 验证签名
        boolean isValid = verify(data.getBytes(), signature, publicKey);
        System.out.println("ECDSA签名验证: " + (isValid ? "有效" : "无效"));
    }
    
    // 使用私钥签名数据
    public static byte[] sign(byte[] data, PrivateKey privateKey) throws Exception {
   
        Signature signature = Signature.getInstance("SHA256withECDSA");
        signature.initSign(privateKey);
        signature.update(data);
        return signature.sign();
    }
    
    // 使用公钥验证签名
    public static boolean verify(byte[] data, byte[] signatureBytes, PublicKey publicKey) throws Exception {
   
        Signature signature = Signature.getInstance("SHA256withECDSA");
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(signatureBytes);
    }
}
3.2.3 DSA(Digital Signature Algorithm)

简介:专门为数字签名设计的算法。

特点

  • 只用于数字签名,不能用于加密
  • 签名生成比RSA快
  • 签名验证比RSA慢
  • 密钥长度通常为1024-3072位

Java示例

import java.security.*;
import java.util.Base64;

public class DSASignatureExample {
   
    public static void main(String[] args) throws Exception {
   
        // 生成DSA密钥对
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        
        // 要签名的数据
        String data = "使用DSA算法签名的数据";
        
        // 签名
        byte[] signature = sign(data.getBytes(), privateKey);
        System.out.println("DSA签名: " + Base64.getEncoder().encodeToString(signature));
        
        // 验证签名
        boolean isValid = verify(data.getBytes(), signature, publicKey);
        System.out.println("DSA签名验证: " + (isValid ? "有效" : "无效"));
    }
    
    // 使用私钥签名数据
    public static byte[] sign(byte[] data, PrivateKey privateKey) throws Exception {
   
        Signature signature = Signature.getInstance("SHA256withDSA");
        signature.initSign(privateKey);
        signature.update(data);
        return signature.sign();
    }
    
    // 使用公钥验证签名
    public static boolean verify(byte[] data, byte[] signatureBytes, PublicKey publicKey) throws Exception {
   
        Signature signature = Signature.getInstance("SHA256withDSA");
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(signatureBytes);
    }
}
3.2.4 DH(Diffie-Hellman)

简介:第一个发布的密钥交换协议,允许两方在不安全的通道上安全地建立共享密钥。

工作原理

  • 基于离散对数问题
  • 双方交换公开值,各自计算相同的共享密钥,而不直接传输密钥

特点

  • 不用于加密或签名,只用于密钥交换
  • 常用于建立对称加密的会话密钥
  • 易受中间人攻击,除非使用身份验证

Java示例(密钥交换)

import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.util.Base64;

public class DHKeyExchangeExample {
   
    public static void main(String[] args) throws Exception {
   
        // 初始化参数
        KeyPairGenerator aliceKpg = KeyPairGenerator.getInstance("DH");
        aliceKpg.initialize(2048);
        KeyPair aliceKp = aliceKpg.generateKeyPair();
        
        // 获取Alice的公钥和私钥
        PublicKey alicePubKey = aliceKp.getPublic();
        PrivateKey alicePrivKey = aliceKp.getPrivate();
        
        // Bob接收Alice的公钥并生成自己的密钥对
        KeyPairGenerator bobKpg = KeyPairGenerator.getInstance("DH");
        bobKpg.initialize(((DHPublicKey)alicePubKey).getParams());
        KeyPair bobKp = bobKpg.generateKeyPair();
        
        // 获取Bob的公钥和私钥
        PublicKey bobPubKey = bobKp.getPublic();
        PrivateKey bobPrivKey = bobKp.getPrivate();
        
        // Alice使用Bob的公钥和自己的私钥生成共享密钥
        KeyAgreement aliceKa = KeyAgreement.getInstance("DH");
        aliceKa.init(alicePrivKey);
        aliceKa.doPhase(bobPubKey, true);
        byte[] aliceSharedSecret = aliceKa.generateSecret();
        
        // Bob使用Alice的公钥和自己的私钥生成共享密钥
        KeyAgreement bobKa = KeyAgreement.getInstance("DH");
        bobKa.init(bobPrivKey);
        bobKa.doPhase(alicePubKey, true);
        byte[] bobSharedSecret = bobKa.generateSecret();
        
        // 打印共享密钥
        System.out.println("Alice的共享密钥: " + Base64.getEncoder().encodeToString(aliceSharedSecret));
        System.out.println("Bob的共享密钥: " + Base64.getEncoder().encodeToString(bobSharedSecret));
        
        // 从共享密钥派生AES密钥
        SecretKey aliceAesKey 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2338757.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单片机AIN0、AIN1引脚功能

目录 1. 模拟-数字转换器(ADC) 2. 交流电源(AC) 总结 这两部分有什么区别? 在这个电路图中,两个部分分别是模拟-数字转换器(ADC)和交流电源(AC)。以下是这…

如何增加 Elasticsearch 中的 primary shard 数量

作者:来自 Elastic Kofi Bartlett 探索增加 Elasticsearch 中 primary shard 数量的方法。 更多阅读: Elasticsearch:Split index API - 把一个大的索引分拆成更多分片 Elasticsearch:通过 shrink API 减少 shard 数量来缩小 El…

Java 并发性能优化:线程池的最佳实践

Java 并发性能优化:线程池的最佳实践 在 Java 并发编程的世界里,线程池堪称提高应用性能与稳定性的神器。恰如其分地运用线程池,能让我们在多线程任务调度时游刃有余,既能避免线程频繁创建销毁带来的开销,又能合理管控…

【综述】一文读懂卷积神经网络(CNN)

卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(Feedforward Neural Networks),是深度学习(deep learning)的代表算法之一。本文旨在介绍CN…

阿里云集群开启debug

1、安装 kubectl Macos brew install kubectl Windows: https://kubernetes.io/zh-cn/docs/tasks/tools/install-kubectl-windows/ 下载后,放到任意目录 2、配置连接信息 mac 将以下内容复制到计算机 $HOME/.kube/config 文件下: windows 不同集…

Unity之如何实现RenderStreaming视频推流

文章目录 前言引入 UnityRenderStreaming 的好处教程步骤 1:设置环境步骤 2: 创建项目步骤 3:安装软件包步骤 5:下载示例步骤 6:检查配置环境步骤 7:打开推流场景步骤 8: 准备用于流式传输的WebServer应用程序步骤 9: 运行 示例场景步骤 10:检查视频是否在浏览器中显示…

【java实现+4种变体完整例子】排序算法中【桶排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格

以下是桶排序的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格: 一、桶排序基础实现 原理 将数据分到有限数量的桶中,每个桶内部使用其他排序算法(如插入排序或快速排序)&#xf…

计算机三级:信息安全基础技术与原理(2.1密码技术简单梳理)

以下是密码学发展历程的表格归纳: ​发展阶段​时间范围​关键节点与标志性技术​技术突破与核心贡献​古典密码时期古代至19世纪• 公元前17世纪 克里特岛Phaistos圆盘(未知符号加密) • 中国西周“阴符”、北宋五言诗密码 • 1466年 艾伯蒂多表代替密码 • 1883年 克尔克霍…

【每天一个知识点】模式识别

“模式识别”是一种从数据中识别出规律、结构或趋势的技术,它广泛应用于人工智能、机器学习、图像处理、语音识别、自然语言处理等领域。简单来说,就是让计算机学会“看出”数据中的规律,比如: 从图像中识别人脸(人脸识…

Codeforces Educational Round 177 Div. 2 【B题,C待补

B 二分 题意 样例 5 3 10 3 4 2 1 512 找最右边的L下标即可 思路 二分最靠右的L端点,R端点取最右端(n*k处),找到后,答案就是L的位置(pos),(因为如果pos满足,则pos左边的所有下标都满足 代码 const in…

哈夫曼编码和哈夫曼树

哈夫曼编码(Huffman Coding) 是一种基于字符出现频率的无损数据压缩算法,通过构建哈夫曼树(Huffman Tree) 来生成最优前缀编码,使得高频字符用短编码,低频字符用长编码,从而实现高效…

中西面点实训室虚拟仿真操作平台

在餐饮行业蓬勃发展的当下,中西面点作为其中极具特色与市场需求的重要分支,对于专业人才的渴望愈发强烈。一个功能完备、设施先进的中西面点实训室,已然成为培养高素质面点专业人才的关键阵地。凯禾瑞华——实训室建设 一、中西面点实训室建设…

C++游戏服务器开发之⑦redis的使用

目录 1.当前进度 2.守护进程 3.进程监控 4.玩家姓名添加文件 5.文件删除玩家姓名 6.redis安装 7.redis存取命令 8.redis链表存取 9.redis程序结构 10.hiredisAPI使用 11.基于redis查找玩家姓名 12.MAKEFILE编写 13.游戏业务实现总结 1.当前进度 2.守护进程 3.进程监…

模拟投资大师思维:AI对冲基金开源项目详解

这里写目录标题 引言项目概述核心功能详解多样化的AI投资智能体灵活的运行模式透明的决策过程 安装和使用教程环境要求安装步骤基本使用方法运行对冲基金模式运行回测模式 应用场景和实际价值教育和研究价值潜在的商业应用与现有解决方案的对比局限性与发展方向 结论 引言 随着…

Cocos Creater打包安卓App添加隐私弹窗详细步骤+常见问题处理

最终演示效果,包含所有代码内容 + 常见错误问题处理 点击服务协议、隐私政策,跳转到相关网页, 点击同意进入游戏,不同意关闭应用 一,添加Activity,命名为MyLaunchActivity 二,编写MyLaunchActivity.java的内容 package com.cocos.game.launch;import android.os.Bund…

Android 热点二维码简单示例

Android 热点二维码简单示例 一、前言 Android 原生设置有热点二维码分享功能,有些系统应用也会有这个需求。 下面看看是如何实现的。 本文是一个比较简单的内容。 二、热点二维码生成实现 1、效果 整个应用就一个普通的Activity,显示一个按钮和二维…

JAVAEE(网络原理—UDP报头结构)

我们本篇文章要讲的是UDP的报头结构以及注意事项。 下面呢,我先说一下UDP是什么? 1.UDP是什么? UDP是一种网络协议。网络协议是计算机网络中,为了使不同设备之间能够准确、高效地进行数据交换和通信,而预先制定的一…

通过docker create与export来分析诊断故障镜像

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…

LINUX419 更换仓库(没换成)find命令

NAT模式下虚拟机需与网卡处在同一个网段中吗 和VM1同个网段 会不会影响 这个很重要 是2 改成点2 倒是Ping通了 为啥ping百度 ping到别的地方 4399 倒是ping通了 准备下载httpd包 下不下来 正在替换为新版本仓库 报错 failure: repodata/repomd.xml from local: [Er…

鸿蒙学习笔记(5)-HTTP请求数据

一、Http请求数据 http模块是鸿蒙内置的一个模块,提供了网络请求的能力。不需要再写比较原始的AJAS代码。 ps:在项目中如果要访问网络资源,不管是图片文件还是网络请求,必须给项目开放权限。 (1)网络连接方式 HTTP数…