2、数据加密基础:对称加密(AES)、非对称加密(RSA)、哈希算法(SHA)、Base64编码
好,咱们直接进入正题。数据加密这块,是iOS安全防护的基石。你想想看,如果连数据都是明文裸奔的,那后面的反逆向工程做得再好,也等于把家底直接亮给黑客看。我个人习惯把加密分为四大类:对称加密、非对称加密、哈希算法,还有Base64编码。别小看Base64,它虽然不算严格意义上的加密,但在iOS开发里几乎天天用。
2.1 对称加密:AES
对称加密,说白了就是加密和解密用同一把钥匙。就像你家的门锁,用一把钥匙锁上,再用同一把钥匙打开。在iOS里,最常用的对称加密算法就是AES。
AES的核心参数
- 密钥长度:128位、192位、256位。我个人建议直接用AES-256,安全强度够高,性能损失其实可以忽略不计。
- 工作模式:ECB、CBC、CFB、OFB、CTR、GCM等。我在项目中遇到过用ECB模式踩坑的案例,后面细说。
- 填充方式:PKCS7Padding、ZeroPadding等。iOS的CommonCrypto默认用PKCS7Padding。
重要提醒:千万不要用ECB模式!ECB模式下,相同的明文块会加密成相同的密文块,这会给攻击者提供统计分析的机会。我曾经在一个金融类App里看到过ECB模式的使用,当时就建议他们立刻改成了CBC模式。
iOS中的AES实现
iOS原生提供了CommonCrypto库,用起来很方便。我一般这样写:
import CommonCrypto
func aesEncrypt(data: Data, key: Data, iv: Data) -> Data? {
var outData = Data(count: data.count + kCCBlockSizeAES128)
var outLength = 0
let status = outData.withUnsafeMutableBytes { outBytes in
data.withUnsafeBytes { dataBytes in
key.withUnsafeBytes { keyBytes in
iv.withUnsafeBytes { ivBytes in
CCCrypt(
CCOperation(kCCEncrypt),
CCAlgorithm(kCCAlgorithmAES),
CCOptions(kCCOptionPKCS7Padding),
keyBytes.baseAddress, key.count,
ivBytes.baseAddress,
dataBytes.baseAddress, data.count,
outBytes.baseAddress, outData.count,
&outLength
)
}
}
}
}
guard status == kCCSuccess else { return nil }
outData.count = outLength
return outData
}
嗯,这里要注意:IV(初始化向量)必须是随机的,而且每次加密都要生成新的IV。我见过有人把IV写死在代码里,那跟没加密其实没啥区别。
我的小技巧:IV可以拼接在密文前面一起存储或传输。解密时先取出前16字节作为IV,剩下的就是密文。这样既安全又方便管理。
2.2 非对称加密:RSA
非对称加密就更有意思了。它有两把钥匙:公钥和私钥。公钥可以公开,私钥必须保密。用公钥加密的数据,只能用私钥解密;反过来,用私钥签名的数据,可以用公钥验证。
为什么会这样?说白了就是数学原理。RSA基于大整数分解难题,你想想看,两个大素数相乘很容易,但要把乘积分解回两个素数,那就难了去了。
RSA在iOS中的典型应用场景
- 密钥交换:客户端用服务器的公钥加密一个对称密钥,服务器用私钥解密。这样后续通信就用对称加密,效率高。
- 数字签名:用私钥对数据签名,公钥验证签名是否有效。我经常用它来验证App更新的完整性。
iOS中的RSA实现
iOS的Security框架提供了RSA支持。我习惯用SecKeyRef来操作:
import Security
func rsaEncrypt(data: Data, publicKey: SecKey) -> Data? {
let blockSize = SecKeyGetBlockSize(publicKey)
var outData = Data(count: blockSize)
var outLength = blockSize
let status = outData.withUnsafeMutableBytes { outBytes in
data.withUnsafeBytes { dataBytes in
SecKeyEncrypt(
publicKey,
.PKCS1,
dataBytes.baseAddress!, data.count,
outBytes.baseAddress!, &outLength
)
}
}
guard status == errSecSuccess else { return nil }
outData.count = outLength
return outData
}
避坑指南:我曾经在项目中遇到过一个坑——RSA加密的数据长度有限制。对于2048位的RSA密钥,一次最多只能加密245字节(因为要留出填充空间)。如果数据太长,需要分段加密,或者先用对称加密加密数据,再用RSA加密对称密钥。
2.3 哈希算法:SHA
哈希算法跟前面两种加密完全不同。它是单向的,不可逆的。你输入任意长度的数据,它输出固定长度的哈希值。而且,哪怕输入只改了一个比特,输出的哈希值也会天差地别。
常见的SHA系列
| 算法 | 输出长度 | 安全性 |
|---|---|---|
| SHA-1 | 160位 | 已不推荐(有碰撞攻击) |
| SHA-256 | 256位 | 安全(推荐) |
| SHA-384 | 384位 | 安全 |
| SHA-512 | 512位 | 安全 |
我个人习惯用SHA-256,它在安全性和性能之间取得了很好的平衡。SHA-1就别用了,Google早在2017年就成功实现了SHA-1碰撞攻击。
iOS中的SHA实现
import CommonCrypto
func sha256(data: Data) -> Data {
var hash = Data(count: Int(CC_SHA256_DIGEST_LENGTH))
data.withUnsafeBytes { dataBytes in
hash.withUnsafeMutableBytes { hashBytes in
CC_SHA256(dataBytes.baseAddress, CC_LONG(data.count), hashBytes.bindMemory(to: UInt8.self).baseAddress)
}
}
return hash
}
我的经验:哈希算法在iOS安全里最常见的用途是校验文件完整性。比如下载一个配置文件,先计算它的SHA-256哈希值,再跟服务器返回的哈希值对比。如果一致,说明文件没有被篡改过。
2.4 Base64编码
Base64不是加密算法,它是一种编码方式。它的作用是把二进制数据转换成可打印的ASCII字符。你想想看,如果加密后的密文里包含不可见字符,直接传输或存储就会出问题。Base64就是来解决这个问题的。
Base64的原理
- 把3个字节(24位)分成4组,每组6位
- 每组6位对应一个Base64字符(共64个字符:A-Z、a-z、0-9、+、/)
- 如果最后不足3个字节,用=填充
iOS中的Base64实现
// 编码
let data = "Hello, iOS Security!".data(using: .utf8)!
let base64String = data.base64EncodedString()
print(base64String) // SGVsbG8sIGlPUyBTZWN1cml0eSE=
// 解码
if let decodedData = Data(base64Encoded: base64String),
let decodedString = String(data: decodedData, encoding: .utf8) {
print(decodedString) // Hello, iOS Security!
}
重要提醒:Base64只是编码,不是加密!我见过有人把Base64当成加密手段来保护敏感数据,这完全是在掩耳盗铃。Base64编码后的数据,任何人都可以轻松解码。它只适合用来传输二进制数据,不能提供任何安全性保障。
2.5 四种技术的配合使用
在实际的iOS项目中,这四种技术往往是配合使用的。我给大家画一个典型的场景:
- 客户端生成一个随机的AES密钥(对称加密)
- 用服务器的RSA公钥加密这个AES密钥(非对称加密)
- 用AES密钥加密实际的数据(对称加密,效率高)
- 对加密后的数据计算SHA-256哈希值(哈希算法,用于完整性校验)
- 把RSA加密后的AES密钥、AES加密后的数据、SHA-256哈希值,都用Base64编码(编码,方便传输)
你看,这样一套组合拳下来,既保证了数据的机密性(AES+RSA),又保证了完整性(SHA-256),还方便了传输(Base64)。
我的建议:在iOS开发中,尽量使用系统自带的加密库(CommonCrypto、Security),不要自己造轮子。系统库经过了严格的测试和审查,比自己写的实现要安全得多。而且,苹果每年都会在WWDC上更新安全相关的API,记得关注。
好了,数据加密基础就讲到这里。下一章我们会深入讨论iOS中的Keychain和Secure Enclave,这些是保护密钥安全的关键技术。到时候我会分享一些我在实际项目中遇到的坑和解决方案。