1. HTTPS/SSL网站安全(最常见应用)
实际场景:网上购物、网银登录
工作原理:
-
当你访问
https://
开头的网站时,浏览器会请求服务器的公钥证书 -
浏览器验证证书的合法性(由可信的证书颁发机构签发)
-
使用服务器的公钥加密一个随机生成的对称会话密钥
-
服务器用私钥解密获得会话密钥
-
后续通信使用对称加密(速度更快)
java
// 简化的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 BTC Transaction 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商店 |
智能门禁 | 身份认证、访问控制 | 办公室门禁、酒店门卡 |
这些应用都依赖于非对称加密的核心优势:公钥可以公开分享,私钥必须严格保密,从而解决了安全通信中的密钥分发问题。