三长两短 - 三层加密架构详解
Scheme B: 分离验证加密方案
本系统采用三层AES-GCM-256加密架构,实现了数据的分层保护和灵活访问控制。
目的:保护用户完整信息
密钥:User Key(用户主密钥,256位)
算法:AES-GCM-256
输入:完整用户信息(姓名、身份证、电话等所有字段)
输出:Layer1Data(加密后的用户数据)
// Swift示例
let userData = UserData(
name: "张三",
idCard: "110101199001011234",
phone: "13800138000",
// ... 其他字段
)
let userKey = generateUserKey() // 256位密钥
let layer1Data = encryptAESGCM(userData, key: userKey)
目的:生成唯一用户映射ID,防止直接关联
算法:SHA256哈希
输入:Layer1Data
输出:UMID(64位十六进制字符串)
// Swift示例
let umid = SHA256.hash(data: layer1Data)
.compactMap { String(format: "%02x", $0) }
.joined()
// 结果: "a1b2c3d4e5f6..." (64位)
目的:生成二维码/分享码,包含姓名和UMID
密钥:App Key(时间敏感,每5分钟更新)
算法:AES-GCM-256
输入:Layer3Info(姓名 + UMID + 时间戳等)
输出:Layer3Data → 二维码/分享码
// Swift示例
let layer3Info = Layer3Info(
name: "张三",
umid: umid,
generatedAt: Date(),
validityMinutes: 5,
nonce: UUID().uuidString
)
let appKey = generateAppKey(timeWindow: currentTimeWindow)
let layer3Data = encryptAESGCM(layer3Info, key: appKey)
// 生成二维码和分享码
let qrCode = generateQRCode(layer3Data)
let shareCode = generateShareCode(layer3Data) // 6位
| 密钥类型 | 用途 | 生成方式 | 有效期 | 存储位置 |
|---|---|---|---|---|
| User Key | Layer 1加密(用户数据) | 用户设置时生成 | 永久 | Keychain(安全) |
| App Key | Layer 3加密(分享) | 基于时间窗口生成 | 5分钟 | 运行时计算 |
| External Key | 完整数据解密 | 外部安全密钥 | - | 物理设备/法律机构 |
// 时间窗口:5分钟
let timeWindow = Int(Date().timeIntervalSince1970) / 300
// App Key派生
func generateAppKey(timeWindow: Int) -> SymmetricKey {
let baseKey = getBaseAppKey() // 应用基础密钥
let material = baseKey + String(timeWindow)
return deriveKey(from: material)
}
// 验证时尝试当前和上一个时间窗口
func decryptWithTimeWindow(_ data: Data) -> Layer3Info? {
let currentWindow = getCurrentTimeWindow()
// 尝试当前窗口
if let info = tryDecrypt(data, window: currentWindow) {
return info
}
// 尝试上一个窗口(容错)
if let info = tryDecrypt(data, window: currentWindow - 1) {
return info
}
return nil // 过期
}
A生成二维码 → B扫描 → App解密姓名 → B验证最后一字 → 发起状态请求
✅ App端完成,无需额外密钥
A身故 → 指定人员持有External Key → 从CloudKit获取Layer1Data → 使用User Key + External Key解密 → 获取完整用户信息
⚠️ 需要在安全环境下操作,不在App内进行
生成分享码 → 检查服务器是否已存在 → 存在则重新生成 → 记录碰撞 → 用户量增长时自动升级位数
📊 6位 → 8位 → 10位 → 12位自动升级
import CryptoKit
func encryptAESGCM(_ data: T, key: SymmetricKey) throws -> Data {
let jsonData = try JSONEncoder().encode(data)
let sealedBox = try AES.GCM.seal(jsonData, using: key)
return sealedBox.combined!
}
func decryptAESGCM(_ encryptedData: Data, key: SymmetricKey) throws -> T {
let sealedBox = try AES.GCM.SealedBox(combined: encryptedData)
let decryptedData = try AES.GCM.open(sealedBox, using: key)
return try JSONDecoder().decode(T.self, from: decryptedData)
}
import CryptoKit
func generateUMID(from layer1Data: Data) -> String {
let hash = SHA256.hash(data: layer1Data)
return hash.compactMap { String(format: "%02x", $0) }.joined()
}
func generateShareCode(length: Int = 6) -> String {
let chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" // 去除易混淆字符
return String((0..<length).map { _ in chars.randomElement()! })
}