非对称加密使用举例
1. HTTPS/SSL网站安全(最常见应用)
实际场景:网上购物、网银登录
工作原理:
当你访问
https://
开头的网站时,浏览器会请求服务器的公钥证书浏览器验证证书的合法性(由可信的证书颁发机构签发)
使用服务器的公钥加密一个随机生成的对称会话密钥
服务器用私钥解密获得会话密钥
后续通信使用对称加密(速度更快)
// 简化的HTTPS握手过程模拟
import java.security.*;
import javax.crypto.*;
import java.util.Base64;class HttpsHandshakeSimulation {public static void main(String[] args) throws Exception {// 网站服务器生成密钥对KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);KeyPair serverKeyPair = keyGen.generateKeyPair();// 客户端生成随机会话密钥(用于对称加密)KeyGenerator aesKeyGen = KeyGenerator.getInstance("AES");aesKeyGen.init(256);SecretKey sessionKey = aesKeyGen.generateKey();System.out.println("=== HTTPS握手过程模拟 ===");// 步骤1: 客户端用服务器公钥加密会话密钥Cipher rsaCipher = Cipher.getInstance("RSA");rsaCipher.init(Cipher.ENCRYPT_MODE, serverKeyPair.getPublic());byte[] encryptedSessionKey = rsaCipher.doFinal(sessionKey.getEncoded());System.out.println("客户端: 使用服务器公钥加密会话密钥");System.out.println("加密后的会话密钥: " + Base64.getEncoder().encodeToString(encryptedSessionKey).substring(0, 50) + "...");// 步骤2: 服务器用私钥解密会话密钥rsaCipher.init(Cipher.DECRYPT_MODE, serverKeyPair.getPrivate());byte[] decryptedSessionKey = rsaCipher.doFinal(encryptedSessionKey);// 重建会话密钥SecretKey decryptedKey = new SecretKeySpec(decryptedSessionKey, 0, decryptedSessionKey.length, "AES");System.out.println("服务器: 使用私钥解密获得会话密钥");System.out.println("会话密钥匹配: " + java.util.Arrays.equals(sessionKey.getEncoded(), decryptedKey.getEncoded()));// 步骤3: 使用会话密钥进行对称加密通信(模拟)String sensitiveData = "信用卡号: 1234-5678-9012-3456";Cipher aesCipher = Cipher.getInstance("AES");aesCipher.init(Cipher.ENCRYPT_MODE, sessionKey);byte[] encryptedData = aesCipher.doFinal(sensitiveData.getBytes());System.out.println("使用会话密钥加密敏感数据: " + sensitiveData);System.out.println("加密后数据长度: " + encryptedData.length + " 字节");}
}
2. 电子邮件加密(PGP/GPG)
实际场景:商业机密邮件、个人隐私邮件
工作原理:
发送方使用接收方的公钥加密邮件内容
只有接收方可以用自己的私钥解密
数字签名确保邮件来源真实性和完整性
// 电子邮件加密模拟
import java.security.*;
import javax.crypto.*;
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;class SecureEmailExample {private KeyPair senderKeyPair; // 发件人密钥对(用于签名)private KeyPair receiverKeyPair; // 收件人密钥对(用于加密)public SecureEmailExample() throws Exception {// 生成发件人和收件人的密钥对KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);senderKeyPair = keyGen.generateKeyPair();receiverKeyPair = keyGen.generateKeyPair();}public void sendEncryptedEmail(String subject, String content) throws Exception {System.out.println("=== 发送加密邮件 ===");// 1. 发件人用私钥对邮件内容签名Signature signature = Signature.getInstance("SHA256withRSA");signature.initSign(senderKeyPair.getPrivate());signature.update(content.getBytes());byte[] digitalSignature = signature.sign();System.out.println("📧 邮件主题: " + subject);System.out.println("📝 原始内容: " + content);System.out.println("✍️ 生成数字签名完成");// 2. 使用收件人公钥加密邮件内容Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, receiverKeyPair.getPublic());String fullContent = content + "|SIGNATURE|" + Base64.getEncoder().encodeToString(digitalSignature);byte[] encryptedContent = cipher.doFinal(fullContent.getBytes());System.out.println("🔒 邮件内容已加密");System.out.println("加密后大小: " + encryptedContent.length + " 字节");// 模拟发送过程receiveAndDecryptEmail(encryptedContent, subject);}private void receiveAndDecryptEmail(byte[] encryptedContent, String subject) throws Exception {System.out.println("\n=== 接收并解密邮件 ===");// 1. 收件人用私钥解密Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, receiverKeyPair.getPrivate());byte[] decryptedContent = cipher.doFinal(encryptedContent);String[] parts = new String(decryptedContent).split("\\|SIGNATURE\\|");String content = parts[0];byte[] receivedSignature = Base64.getDecoder().decode(parts[1]);System.out.println("📧 收到邮件主题: " + subject);System.out.println("📝 解密内容: " + content);// 2. 使用发件人公钥验证签名Signature signature = Signature.getInstance("SHA256withRSA");signature.initVerify(senderKeyPair.getPublic());signature.update(content.getBytes());boolean valid = signature.verify(receivedSignature);System.out.println("✅ 签名验证: " + (valid ? "通过" : "失败"));System.out.println("🔍 邮件确实来自声称的发送者: " + valid);}
}// 使用示例
class EmailDemo {public static void main(String[] args) throws Exception {SecureEmailExample email = new SecureEmailExample();email.sendEncryptedEmail("商业合作提案", "尊敬的合作伙伴,\n\n我们有一个重要的商业合作提议...\n\n机密信息: 项目预算$1,000,000");}
}
3. 数字货币和区块链
实际场景:比特币交易、NFT所有权验证
工作原理:
每个用户有公钥(作为接收地址)和私钥(控制资产)
交易用私钥签名,全网用公钥验证
确保只有私钥持有者能花费数字货币
// 比特币交易签名验证模拟
import java.security.*;
import java.util.*;class BitcoinTransactionSimulation {static class Transaction {String fromAddress; // 发送方地址(公钥哈希)String toAddress; // 接收方地址double amount; // 转账金额byte[] signature; // 数字签名public Transaction(String from, String to, double amount) {this.fromAddress = from;this.toAddress = to;this.amount = amount;}// 对交易内容进行签名public void sign(PrivateKey privateKey) throws Exception {String transactionData = fromAddress + toAddress + amount;Signature sig = Signature.getInstance("SHA256withECDSA");sig.initSign(privateKey);sig.update(transactionData.getBytes());this.signature = sig.sign();}// 验证交易签名public boolean verifySignature(PublicKey publicKey) throws Exception {if (signature == null) return false;String transactionData = fromAddress + toAddress + amount;Signature sig = Signature.getInstance("SHA256withECDSA");sig.initVerify(publicKey);sig.update(transactionData.getBytes());return sig.verify(signature);}}public static void main(String[] args) throws Exception {System.out.println("=== 比特币交易模拟 ===");// 生成用户密钥对(比特币使用椭圆曲线加密)KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");keyGen.initialize(256);// 用户A(发送方)KeyPair userAKeys = keyGen.generateKeyPair();String userAAddress = "1A1zP1" + Base64.getEncoder().encodeToString(userAKeys.getPublic().getEncoded()).substring(0, 10);// 用户B(接收方) KeyPair userBKeys = keyGen.generateKeyPair();String userBAddress = "1B2zP2" + Base64.getEncoder().encodeToString(userBKeys.getPublic().getEncoded()).substring(0, 10);// 创建交易:用户A向用户B转账0.1 BTCTransaction tx = new Transaction(userAAddress, userBAddress, 0.1);// 用户A用私钥签名交易tx.sign(userAKeys.getPrivate());System.out.println("💰 交易创建: " + userAAddress + " → " + userBAddress + " 金额: " + tx.amount + " BTC");System.out.println("✍️ 交易已签名");// 矿工验证交易签名(使用用户A的公钥)boolean isValid = tx.verifySignature(userAKeys.getPublic());System.out.println("⛏️ 矿工验证结果: " + (isValid ? "有效交易" : "无效交易"));if (isValid) {System.out.println("✅ 交易将被包含在下一个区块中");} else {System.out.println("❌ 交易被拒绝:签名验证失败");}// 模拟恶意攻击:尝试用错误的公钥验证KeyPair attackerKeys = keyGen.generateKeyPair();boolean fakeVerify = tx.verifySignature(attackerKeys.getPublic());System.out.println("🎭 攻击者尝试验证: " + (fakeVerify ? "意外成功" : "失败(预期结果)"));}
}
4. SSH密钥认证
实际场景:远程服务器登录、自动化部署
工作原理:
客户端生成密钥对,将公钥上传到服务器
登录时客户端用私钥签名挑战信息
服务器用存储的公钥验证签名
// SSH密钥认证模拟
import java.security.*;
import java.util.Base64;class SSHAuthenticationSimulation {public static void main(String[] args) throws Exception {System.out.println("=== SSH公钥认证模拟 ===\n");// 用户生成SSH密钥对KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);KeyPair userKeys = keyGen.generateKeyPair();// 用户将公钥上传到服务器(模拟)String userPublicKey = Base64.getEncoder().encodeToString(userKeys.getPublic().getEncoded());System.out.println("1. 用户生成SSH密钥对");System.out.println("2. 公钥上传到服务器: ssh-rsa " + userPublicKey.substring(0, 30) + "...");// 登录过程System.out.println("\n3. 用户尝试登录服务器...");// 服务器生成随机挑战SecureRandom random = new SecureRandom();byte[] challenge = new byte[32];random.nextBytes(challenge);System.out.println("4. 服务器发送挑战: " + Base64.getEncoder().encodeToString(challenge).substring(0, 20) + "...");// 用户用私钥签名挑战Signature sig = Signature.getInstance("SHA256withRSA");sig.initSign(userKeys.getPrivate());sig.update(challenge);byte[] signature = sig.sign();System.out.println("5. 用户用私钥签名挑战");// 服务器用存储的公钥验证签名sig.initVerify(userKeys.getPublic());sig.update(challenge);boolean authenticated = sig.verify(signature);System.out.println("6. 服务器验证签名: " + (authenticated ? "成功" : "失败"));if (authenticated) {System.out.println("✅ 认证成功!允许访问服务器");} else {System.out.println("❌ 认证失败!拒绝访问");}}
}
5. 软件代码签名
实际场景:操作系统更新、手机APP验证
工作原理:
开发者用私钥对软件包生成数字签名
用户设备用开发者的公钥验证签名
确保软件未被篡改且来源可信
// 软件代码签名验证模拟
import java.security.*;
import java.util.zip.*;class CodeSigningSimulation {static class SoftwarePackage {String name;String version;byte[] content;byte[] signature;public SoftwarePackage(String name, String version, String content) {this.name = name;this.version = version;this.content = content.getBytes();}// 开发者签名软件public void sign(PrivateKey privateKey) throws Exception {Signature sig = Signature.getInstance("SHA256withRSA");sig.initSign(privateKey);sig.update(getHash());this.signature = sig.sign();}// 验证软件签名public boolean verify(PublicKey publicKey) throws Exception {if (signature == null) return false;Signature sig = Signature.getInstance("SHA256withRSA");sig.initVerify(publicKey);sig.update(getHash());return sig.verify(signature);}// 计算软件内容哈希private byte[] getHash() throws Exception {MessageDigest digest = MessageDigest.getInstance("SHA-256");return digest.digest(content);}}public static void main(String[] args) throws Exception {System.out.println("=== 软件代码签名验证 ===\n");// 软件公司生成密钥对KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);KeyPair companyKeys = keyGen.generateKeyPair();// 创建软件包SoftwarePackage app = new SoftwarePackage("MyApp", "2.1.0", "public class MyApp { /* 应用程序代码 */ }");// 公司签名软件app.sign(companyKeys.getPrivate());System.out.println("1. 软件公司发布: " + app.name + " v" + app.version);System.out.println("2. 已用公司私钥签名");// 用户下载后验证System.out.println("\n3. 用户下载软件...");System.out.println("4. 系统验证数字签名...");boolean isValid = app.verify(companyKeys.getPublic());if (isValid) {System.out.println("✅ 验证成功!软件未被篡改,来源可信");System.out.println("🔄 允许安装和运行");} else {System.out.println("❌ 验证失败!软件可能被篡改");System.out.println("🚫 阻止安装,警告用户");}// 模拟恶意软件System.out.println("\n--- 恶意软件模拟 ---");SoftwarePackage malware = new SoftwarePackage("FakeApp", "1.0", "恶意代码");// 攻击者尝试用错误密钥验证KeyPair attackerKeys = keyGen.generateKeyPair();boolean fakeVerify = malware.verify(attackerKeys.getPublic());System.out.println("恶意软件验证: " + (fakeVerify ? "意外通过" : "被正确阻止"));}
}
6. 智能门禁系统
实际场景:办公室门禁、酒店电子钥匙
// 智能门锁系统模拟
import java.security.*;
import java.time.LocalDateTime;class SmartLockSystem {static class DigitalKey {String keyId;PublicKey lockPublicKey; // 门锁的公钥PrivateKey userPrivateKey; // 用户的私钥LocalDateTime expiryDate;public DigitalKey(String keyId, PublicKey lockKey, PrivateKey userKey, LocalDateTime expiry) {this.keyId = keyId;this.lockPublicKey = lockKey;this.userPrivateKey = userKey;this.expiryDate = expiry;}// 生成开门请求public byte[] generateAccessRequest() throws Exception {String requestData = keyId + "|" + LocalDateTime.now().toString();// 用用户私钥签名Signature sig = Signature.getInstance("SHA256withRSA");sig.initSign(userPrivateKey);sig.update(requestData.getBytes());byte[] signature = sig.sign();// 用门锁公钥加密Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, lockPublicKey);return cipher.doFinal((requestData + "|SIG|" + Base64.getEncoder().encodeToString(signature)).getBytes());}}static class SmartLock {PrivateKey lockPrivateKey;PublicKey lockPublicKey;public SmartLock() throws Exception {KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);KeyPair keyPair = keyGen.generateKeyPair();this.lockPrivateKey = keyPair.getPrivate();this.lockPublicKey = keyPair.getPublic();}public boolean processAccessRequest(byte[] encryptedRequest, DigitalKey validKey) throws Exception {// 用门锁私钥解密Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, lockPrivateKey);String decrypted = new String(cipher.doFinal(encryptedRequest));String[] parts = decrypted.split("\\|SIG\\|");String requestData = parts[0];byte[] signature = Base64.getDecoder().decode(parts[1]);String[] dataParts = requestData.split("\\|");String keyId = dataParts[0];LocalDateTime requestTime = LocalDateTime.parse(dataParts[1]);// 验证签名Signature sig = Signature.getInstance("SHA256withRSA");sig.initVerify(validKey.lockPublicKey); // 应该用用户公钥验证sig.update(requestData.getBytes());boolean validSignature = sig.verify(signature);boolean validTime = requestTime.isAfter(LocalDateTime.now().minusMinutes(5));boolean notExpired = validKey.expiryDate.isAfter(LocalDateTime.now());System.out.println("🔐 门锁验证:");System.out.println(" - 签名有效: " + validSignature);System.out.println(" - 请求时间有效: " + validTime);System.out.println(" - 密钥未过期: " + notExpired);return validSignature && validTime && notExpired;}}public static void main(String[] args) throws Exception {System.out.println("=== 智能门锁系统 ===\n");SmartLock officeLock = new SmartLock();// 为员工生成数字钥匙KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");keyGen.initialize(2048);KeyPair employeeKeys = keyGen.generateKeyPair();DigitalKey employeeKey = new DigitalKey("EMP001", officeLock.lockPublicKey, employeeKeys.getPrivate(),LocalDateTime.now().plusDays(30));System.out.println("1. 员工数字钥匙已发放(有效期30天)");// 员工尝试开门System.out.println("\n2. 员工尝试进入办公室...");byte[] accessRequest = employeeKey.generateAccessRequest();boolean accessGranted = officeLock.processAccessRequest(accessRequest, employeeKey);if (accessGranted) {System.out.println("✅ 访问 granted!门锁打开");} else {System.out.println("❌ 访问 denied!门锁保持关闭");}}
}
总结
非对称加密在现代生活中的应用非常广泛:
应用场景 | 使用的非对称加密特性 | 实际例子 |
---|---|---|
HTTPS/SSL | 密钥交换、身份验证 | 网上银行、电商网站 |
电子邮件加密 | 保密性、完整性验证 | 商业机密通信 |
数字货币 | 数字签名、所有权证明 | 比特币、以太坊交易 |
SSH登录 | 身份认证 | 服务器远程管理 |
代码签名 | 来源验证、完整性保护 | 软件更新、APP商店 |
智能门禁 | 身份认证、访问控制 | 办公室门禁、酒店门卡 |
这些应用都依赖于非对称加密的核心优势:公钥可以公开分享,私钥必须严格保密,从而解决了安全通信中的密钥分发问题。