iOS开发基础46-数据安全与网络状态监控:加密算法、HTTPS/TLS 握手、SSL Pinning 与 Reachability
iOS 数据安全与网络状态监控深度解析:加密算法、HTTPS/TLS 握手、SSL Pinning 与 Reachability
本文系统梳理 iOS 数据安全:隐私数据提交策略、加密算法分类(哈希/对称/非对称)、MD5 原理与加盐改进、现代密码存储最佳实践、HTTPS/TLS 完整握手流程(RSA 与 ECDHE)、AEAD 加密、防止中间人攻击与 SSL Pinning、以及网络状态监控(Reachability 与 NWPathMonitor)。
一、数据安全
1. 隐私数据的安全提交
传输用户隐私数据时,HTTP 方法的选择至关重要:
| 方法 | 参数位置 | 暴露风险 |
|---|---|---|
| GET | URL 中(?key=value) |
高:URL 记录在服务器访问日志、浏览器历史、Referer 中 |
| POST | 请求体(Body)中 | 低:不暴露在 URL 中 |
隐私数据(密码、银行账号、Token 等)必须使用 POST 请求。
重要:POST 只是把参数放在请求体中,不等于加密。如果使用 HTTP 明文传输,POST 请求体仍可被抓包工具(如 Charles)完整拦截查看。真正保证传输安全的是 HTTPS(SSL/TLS 加密)。POST + HTTPS 才是隐私数据提交的正确组合。
2. 加密算法分类
常见安全算法分为三类:
| 类别 | 算法 | 特点 | 用途 |
|---|---|---|---|
| 哈希算法(单向) | MD5、SHA-1、SHA-256、SHA-512、SHA-3 | 不可逆,固定长度输出,用于完整性校验 | 数字签名、文件校验、密码存储(加盐) |
| 对称加密 | DES、3DES、AES、RC4、IDEA | 加解密用同一密钥,速度快 | 大量数据加密、HTTPS 会话加密 |
| 非对称加密 | RSA、DSA、ECC(椭圆曲线) | 公钥加密、私钥解密,速度慢 | 密钥交换、数字签名、HTTPS 证书 |
MD5 和 SHA 是哈希算法(单向散列),不是加密算法——它们不可逆,不能"解密"还原原文。日常说"MD5 加密"是口语化表述,准确说法是"MD5 哈希"或"MD5 摘要"。
3. MD5 详解
MD5(Message-Digest Algorithm 5)是一种广泛使用的单向哈希函数,将任意长度输入映射为 128 位(16 字节,32 个十六进制字符)的散列值。
特点:
- 固定长度输出:无论输入多长,输出都是 32 个十六进制字符。
- 单向不可逆:无法从散列值还原原始明文。
- 雪崩效应:输入微小变化导致输出完全不同。
- 不保证绝对唯一性:MD5 存在碰撞(不同输入生成相同输出),2004 年王小云院士团队证明了 MD5 碰撞攻击,MD5 已不推荐用于安全场景。
MD5 用途:
- 文件完整性校验(下载文件后比对 MD5 值)。
- 数字签名(配合非对称加密)。
- 密码存储(需加盐,现代已不推荐单独使用)。
关于"MD5 解密网站":这类网站(如 cmd5.com)并不是真正"解密"MD5,而是维护了一个巨大的彩虹表(常见明文与其 MD5 值的映射数据库),通过查询散列值反查常见明文。对于加盐或复杂随机明文,彩虹表无法查询。
4. MD5 改进(加盐)
由于 MD5 可通过彩虹表查询,直接对密码做 MD5 不安全。改进措施:
加盐(Salt):在明文的固定位置插入随机字符串,再做 MD5。每个用户使用不同的随机盐,即使两个用户密码相同,存储的 MD5 值也不同。
#import <CommonCrypto/CommonDigest.h>
// 简单 MD5
- (NSString *)md5:(NSString *)input {
const char *cStr = [input UTF8String];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr, (CC_LONG)strlen(cStr), digest);
NSMutableString *result = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[result appendFormat:@"%02x", digest[i]];
}
return result;
}
// 加盐 MD5
- (NSString *)md5:(NSString *)input withSalt:(NSString *)salt {
NSString *salted = [NSString stringWithFormat:@"%@%@", salt, input];
return [self md5:salted];
}
使用示例:
NSString *password = @"userPassword123";
NSString *salt = [[NSUUID UUID].UUIDString stringByReplacingOccurrencesOfString:@"-" withString:@""]; // 随机盐
NSString *hashed = [self md5:password withSalt:salt];
// 存储 hashed 和 salt 到数据库
现代最佳实践:密码存储不推荐 MD5(即使加盐),因为 MD5 计算速度太快,可被暴力破解。推荐使用专门的密码哈希算法:bcrypt、scrypt 或 Argon2,这些算法计算慢、自带加盐、可调节计算成本,能有效抵抗暴力破解。iOS 开发中可使用 CryptoKit(iOS 13+)或第三方库(如 CryptoSwift)实现。
5. 提交隐私数据的安全过程
| 阶段 | 客户端 | 服务器 |
|---|---|---|
| 注册 | 输入明文密码 → 加盐 MD5(或通过 HTTPS 直接传明文)→ 传输 | 接收密码 → bcrypt/Argon2 加盐哈希 → 存储哈希值 |
| 登录 | 输入明文密码 → 同样处理 → 传输 | 接收密码 → 用存储的盐哈希 → 与存储的哈希值比对 |
两种常见模式:
- 客户端哈希后传输:客户端先 MD5(加盐),把哈希当密码传。好处是即使 HTTPS 被攻破也不暴露明文密码;坏处是客户端哈希逻辑可被逆向,且服务器存储的仍是客户端哈希(安全性取决于客户端算法)。
- HTTPS 传明文,服务器哈希(现代推荐):客户端通过 HTTPS 直接传明文密码(HTTPS 已加密传输),服务器用 bcrypt/Argon2 加盐哈希后存储。安全性更高,因为慢哈希算法在服务器端,可调节计算成本。
二、HTTPS
1. HTTPS 简介
HTTPS(HyperText Transfer Protocol Secure)是 HTTP 的安全版本,在 HTTP 与 TCP 之间加入 SSL/TLS 层,提供:
- 数据加密:传输内容加密,防止窃听。
- 身份认证:通过证书验证服务器真实身份,防止冒充。
- 数据完整性:防止传输过程中被篡改。
HTTPS 默认端口 443(HTTP 为 80)。
HTTPS 大幅提升了传输安全性,但不是"绝对安全"——如果用户手动信任了伪造证书(如 Charles 抓包时安装并信任证书),仍可能被中间人攻击。SSL Pinning(证书固定)可进一步防御。
2. HTTPS 历史
- 1994 年:网景公司开发 HTTPS,最初使用 SSL 协议,内置于 Netscape Navigator。
- 1999 年:SSL 3.0 发布(后因 POODLE 漏洞被废弃)。
- 1999 年:TLS 1.0 发布(SSL 的标准化继任者)。
- 2000 年:HTTPS 协议由 RFC 2818 正式规范。
- 2008 年:TLS 1.2 发布(目前广泛使用的版本)。
- 2018 年:TLS 1.3 发布(简化握手、提升性能、移除不安全算法,现代推荐)。
现代 App 和服务器应使用 TLS 1.2 或 TLS 1.3,SSL 3.0 和 TLS 1.0/1.1 已因安全漏洞被废弃(iOS 15+ 默认不再支持 TLS 1.0/1.1)。
3. HTTPS 与 HTTP 区别
| 对比项 | HTTP | HTTPS |
|---|---|---|
| 端口 | 80 | 443 |
| 传输方式 | 明文 | SSL/TLS 加密 |
| 证书 | 不需要 | 需要 CA 签发的证书 |
| 身份验证 | 无 | 验证服务器身份 |
| 数据完整性 | 无保障 | MAC/AEAD 校验 |
| 性能 | 快(无加密开销) | 略慢(握手和加密开销,现代硬件可忽略) |
| 安全性 | 低(可被窃听/篡改/冒充) | 高 |
4. HTTPS 实现原理(TLS 握手)
HTTPS = HTTP + SSL/TLS。TLS 握手的目标是:双方协商加密算法、验证服务器身份、生成会话密钥,之后用对称加密传输数据。
RSA 密钥交换流程(传统流程)
客户端 服务器
│ │
│────── 1. ClientHello ────────────────▶│ 支持的TLS版本、加密套件、随机数A
│ │
│◀────── 2. ServerHello ────────────────│ 选定的TLS版本、加密套件、随机数B
│◀────── 证书(Certificate)────────────│ 服务器证书(含公钥)
│◀────── ServerHelloDone ───────────────│
│ │
│ 3. 验证证书(CA 链、域名、有效期) │
│ │
│────── 4. ClientKeyExchange ───────────▶│ 预主密钥(用服务器公钥加密)
│ │ 服务器用私钥解密得到预主密钥
│ │
│ 5. 双方用 预主密钥+随机数A+随机数B │
│ 生成主密钥(Master Secret) │
│ 再派生出加密密钥、MAC密钥、IV │
│ │
│────── 6. ChangeCipherSpec ────────────▶│ 通知后续用协商密钥加密
│────── Finished ───────────────────────▶│ 握手完成校验
│◀────── ChangeCipherSpec ───────────────│
│◀────── Finished ───────────────────────│
│ │
│══════ 7. 加密 HTTP 数据传输 ═══════════│ 对称加密(AES)+ 完整性校验
步骤说明:
- ClientHello:客户端发送支持的 TLS 版本、加密套件列表、随机数 A(Client Random)。
- ServerHello:服务器选定 TLS 版本和加密套件,发送随机数 B(Server Random)、服务器证书(含公钥)。
- 验证证书:客户端用系统内置根证书验证服务器证书链的签名、域名、有效期,确保证书合法且属于目标服务器。
- ClientKeyExchange:客户端生成预主密钥(Pre-Master Secret),用服务器公钥加密后发送。只有服务器私钥能解密。
- 生成主密钥:双方用预主密钥 + 随机数 A + 随机数 B 通过 PRF(伪随机函数)生成主密钥(Master Secret),再派生出加密密钥、MAC 密钥、IV 等多个密钥。
- 握手完成:双方交换 ChangeCipherSpec 和 Finished 消息,确认握手完成。
- 加密传输:后续所有 HTTP 数据用协商好的对称密钥加密传输。
ECDHE 密钥交换(现代推荐,支持前向保密)
RSA 密钥交换的问题:如果服务器私钥泄露,历史所有会话都可被解密(因为预主密钥用服务器公钥加密)。
现代 TLS 1.2/1.3 普遍使用 ECDHE(椭圆曲线 Diffie-Hellman 临时密钥交换):
- 服务器生成临时椭圆曲线密钥对,发送临时公钥参数(用证书私钥签名,证明是服务器发出的)。
- 客户端也生成临时椭圆曲线密钥对,发送临时公钥。
- 双方用自己的临时私钥 + 对方的临时公钥,通过 ECDH 算法计算出相同的共享密钥(预主密钥)。
- 每次会话的临时密钥对都是新的,会话结束后销毁——即使服务器长期私钥泄露,也无法解密历史会话。这就是前向保密(Forward Secrecy)。
TLS 1.3 进一步简化了握手:默认使用 ECDHE,移除了 RSA 密钥交换和不安全加密套件,握手从 2-RTT 缩减为 1-RTT(甚至支持 0-RTT 恢复),性能大幅提升。
5. 数据加密与安全传输
握手完成后,应用层数据通过对称加密传输:
| 机制 | 算法 | 作用 |
|---|---|---|
| 对称加密 | AES-128-GCM、AES-256-GCM、ChaCha20-Poly1305 | 加密数据内容 |
| 消息认证 | AEAD(GCM/Poly1305 内置) | 同时提供加密和完整性/来源认证 |
| 密钥派生 | HKDF | 从主密钥派生出加密密钥、IV 等 |
现代 TLS 使用 AEAD(Authenticated Encryption with Associated Data,带关联数据的认证加密)算法,如 AES-GCM 和 ChaCha20-Poly1305,一次操作同时完成加密和完整性认证,比传统"加密 + 单独 HMAC"更安全高效。
6. 防止中间人攻击(MITM)
中间人攻击:攻击者在客户端和服务器之间截获并篡改通信。HTTPS 通过以下机制防御:
| 机制 | 作用 |
|---|---|
| 证书验证 | 客户端用 CA 根证书验证服务器证书,确保证书由可信 CA 签发、域名匹配、未过期,防止攻击者冒充服务器 |
| 非对称加密密钥交换 | 预主密钥用服务器公钥加密,只有服务器私钥能解密,中间人截获也无法解密 |
| 前向保密(ECDHE) | 每次会话用临时密钥,即使长期私钥泄露也无法解密历史会话 |
| 消息认证(AEAD/MAC) | 验证数据未被篡改,篡改的数据会被拒绝 |
| 会话密钥独立 | 每个会话生成独立密钥,防止重放攻击 |
Charles 抓包 HTTPS 的原理:Charles 作为中间人,生成伪造证书(用 Charles 自己的 CA 签发),客户端需要手动安装并信任 Charles 的 CA 证书,Charles 才能分别与客户端和服务器建立 TLS 连接并解密转发。如果客户端做了 SSL Pinning(证书固定,只信任服务器特定证书或公钥),即使信任了 Charles 证书也会拒绝连接,Charles 无法抓包。
7. SSL Pinning(证书固定)
SSL Pinning 是 App 端额外的安全措施:在 App 中硬编码服务器证书(或公钥哈希),TLS 握手时不仅验证系统 CA 链,还校验服务器证书是否与 App 内置的一致。即使系统信任了伪造证书,只要不匹配内置证书就拒绝连接。
// URLSession 代理中实现 SSL Pinning
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
NSData *certificateData = (__bridge_transfer NSData *)SecCertificateCopyData(certificate);
// 与 App 内置的证书数据比对
NSString *certPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];
NSData *localCertData = [NSData dataWithContentsOfFile:certPath];
if ([certificateData isEqualToData:localCertData]) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}
} else {
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}
}
也可以固定公钥哈希(比固定证书更灵活,证书轮换时公钥不变则不需要发版)。AFNetworking/Alamofire 都内置了 SSL Pinning 支持,配置更简单。
三、网络状态监控
1. 检测网络状态的必要性
实时监控网络状态可以:
- 让用户了解当前网络状况,避免因网络问题引起误会。
- 根据网络状况智能处理:WiFi 下下载高清图片,蜂窝网络下仅下载缩略图或提示用户。
- 网络断开时暂停下载、缓存请求,网络恢复后自动重试。
2. Reachability(传统方案)
苹果提供的 Reachability 示例代码(不是官方框架 API,需手动将源码加入项目),基于 SystemConfiguration 框架。
使用步骤:
- 导入
SystemConfiguration.framework。 - 将苹果示例代码
Reachability.h/.m加入项目。 - 引入头文件
#import "Reachability.h"。
判断网络状态:
#import "Reachability.h"
// 是否 WiFi
+ (BOOL)isEnableWIFI {
return ([[Reachability reachabilityForLocalWiFi] currentReachabilityStatus] != NotReachable);
}
// 是否蜂窝网络(WWAN,含 3G/4G/5G)
+ (BOOL)isEnableWWAN {
return ([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] != NotReachable);
}
reachabilityForLocalWiFi在 iOS 9 已废弃;"3G"是旧称,现在应称 WWAN(无线广域网,包括 3G/4G/5G)。
监听网络变化(通知):
@interface ViewController ()
@property (nonatomic, strong) Reachability *netReachability;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 注册通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
// 开始监听
self.netReachability = [Reachability reachabilityForInternetConnection];
[self.netReachability startNotifier];
}
- (void)reachabilityChanged:(NSNotification *)note {
Reachability *curReach = [note object];
NetworkStatus status = [curReach currentReachabilityStatus];
switch (status) {
case NotReachable:
NSLog(@"无网络");
break;
case ReachableViaWiFi:
NSLog(@"WiFi");
break;
case ReachableViaWWAN:
NSLog(@"蜂窝网络");
break;
}
}
- (void)dealloc {
[self.netReachability stopNotifier];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
3. NWPathMonitor(现代方案,iOS 12+ 推荐)
iOS 12 引入的 Network 框架提供了 NWPathMonitor,是 Reachability 的现代替代,API 更简洁、支持更细粒度的网络类型判断(WiFi/蜂窝/有线/虚拟网络等)。
#import <Network/Network.h>
@interface ViewController ()
@property (nonatomic, strong) NWPathMonitor *pathMonitor;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.pathMonitor = [[NWPathMonitor alloc] init];
// 设置回调队列
[self.pathMonitor setQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
// 监听网络变化
[self.pathMonitor setPathUpdateHandler:^(NWPath *path) {
if (path.status == NWPathStatusSatisfied) {
NSLog(@"网络已连接");
// 判断网络类型
if ([path usesInterfaceType:NWInterfaceTypeWifi]) {
NSLog(@"WiFi");
} else if ([path usesInterfaceType:NWInterfaceTypeCellular]) {
NSLog(@"蜂窝网络");
} else if ([path usesInterfaceType:NWInterfaceTypeWired]) {
NSLog(@"有线网络");
}
} else if (path.status == NWPathStatusUnsatisfied) {
NSLog(@"无网络");
} else if (path.status == NWPathStatusRequiresConnection) {
NSLog(@"需要连接(如 VPN/热点)");
}
}];
[self.pathMonitor start];
}
- (void)dealloc {
[self.pathMonitor cancel];
}
@end
Reachability vs NWPathMonitor:Reachability 是苹果示例代码,需手动加入项目,API 较旧;NWPathMonitor 是 iOS 12+ 官方框架 API,更现代、更稳定,新项目推荐使用 NWPathMonitor。
四、Swift 版本对照
MD5 哈希(Swift)
import CryptoKit
// iOS 13+ 推荐 CryptoKit
func md5(_ input: String) -> String {
let data = Data(input.utf8)
let digest = Insecure.MD5.hash(data: data)
return digest.map { String(format: "%02x", $0) }.joined()
}
// 加盐 MD5
func md5(_ input: String, salt: String) -> String {
md5(salt + input)
}
// SHA-256(推荐替代 MD5)
func sha256(_ input: String) -> String {
let data = Data(input.utf8)
let digest = SHA256.hash(data: data)
return digest.map { String(format: "%02x", $0) }.joined()
}
NWPathMonitor(Swift)
import Network
let monitor = NWPathMonitor()
monitor.pathUpdateHandler = { path in
if path.status == .satisfied {
if path.usesInterfaceType(.wifi) {
print("WiFi")
} else if path.usesInterfaceType(.cellular) {
print("蜂窝网络")
}
} else {
print("无网络")
}
}
monitor.start(queue: .global())
SSL Pinning(Alamofire,Swift)
import Alamofire
// 证书固定(公钥哈希)
let serverTrustManager = ServerTrustManager(evaluators: [
"api.example.com": PublicKeysTrustEvaluator()
])
let session = Session(serverTrustManager: serverTrustManager)
session.request("https://api.example.com/data").responseJSON { response in
// 处理响应
}
五、总结
- 隐私数据提交:必须用 POST(参数在请求体不暴露在 URL),但 POST 不等于加密,必须配合 HTTPS 才能保证传输安全。
- 加密算法分类:哈希算法(MD5/SHA,单向不可逆,用于完整性校验和密码存储)、对称加密(DES/3DES/AES,加解密同密钥,速度快,用于大量数据加密)、非对称加密(RSA/ECC,公钥加密私钥解密,用于密钥交换和数字签名)。
- MD5:128 位哈希,存在碰撞(2004 年被证明),已不推荐安全场景;"MD5 解密网站"是彩虹表查询非真解密;改进用加盐(每个用户随机盐);现代密码存储推荐 bcrypt/scrypt/Argon2(慢哈希、自带加盐)。
- 密码传输两种模式:客户端哈希后传输(防 HTTPS 攻破暴露明文)或 HTTPS 传明文+服务器慢哈希(现代推荐,安全性更高)。
- HTTPS/TLS:HTTP + SSL/TLS,443 端口,提供加密、认证、完整性;现代用 TLS 1.2/1.3,SSL 3.0 和 TLS 1.0/1.1 已废弃。
- TLS 握手:RSA 流程(ClientHello → ServerHello+证书 → 验证证书 → 预主密钥用公钥加密 → 双方生成主密钥 → 加密传输);现代用 ECDHE(临时密钥交换,支持前向保密,即使长期私钥泄露也无法解密历史会话);TLS 1.3 简化为 1-RTT。
- 数据加密:用 AEAD 算法(AES-GCM/ChaCha20-Poly1305)同时提供加密和完整性认证。
- 防中间人攻击:证书验证(CA 链)、非对称密钥交换、前向保密、消息认证;Charles 抓包需安装信任伪造证书;SSL Pinning(证书固定)可进一步防御,即使信任伪造证书也拒绝连接。
- 网络监控:Reachability(苹果示例代码,传统方案,iOS 9 部分 API 废弃);NWPathMonitor(iOS 12+ Network 框架,现代推荐,支持 WiFi/蜂窝/有线等细粒度判断)。

浙公网安备 33010602011771号