将Java的PBKDF2WithHmacSHA512&AES密钥生成逻辑转为Swift实现
Java PBKDF2WithHmacSHA512生成AES密钥的Swift等效实现
原Swift代码的问题
你的Swift代码存在几个关键错误,导致结果和Java逻辑不一致:
- 变量名混淆:
accessKeyData使用了未定义的accessKey变量,应替换为传入的secretKey;同时secretKeyData属于未声明的笔误 - 强制解包风险:用
!强制解包Base64数据和字符串转换,容易引发崩溃,需用安全的可选处理 - CommonCrypto参数传递错误:直接传入
password字符串而非其UTF-8字节的指针,不符合C接口要求
正确的等效实现(基于CommonCrypto)
import CommonCrypto func createKey(secretKey: String, secretId: String) throws -> SymmetricKey { // 处理盐:将secretId转为UTF-8数据 guard let salt = secretId.data(using: .utf8) else { throw NSError(domain: "KeyDerivationError", code: 1, userInfo: [NSLocalizedDescriptionKey: "secretId转UTF-8数据失败"]) } // Base64解码传入的secretKey guard let secretKeyData = Data(base64Encoded: secretKey) else { throw NSError(domain: "KeyDerivationError", code: 2, userInfo: [NSLocalizedDescriptionKey: "secretKey不是有效的Base64格式"]) } // 将解码后的数据转为UTF-8字符串 guard let finalKey = String(data: secretKeyData, encoding: .utf8) else { throw NSError(domain: "KeyDerivationError", code: 3, userInfo: [NSLocalizedDescriptionKey: "secretKey解码后无法转为UTF-8字符串"]) } let keyData = try deriveKey(password: finalKey, salt: salt, iterations: 10000, keyLength: 256 / 8) return SymmetricKey(data: keyData) } func deriveKey(password: String, salt: Data, iterations: Int, keyLength: Int) throws -> Data { var derivedKeyData = Data(count: keyLength) guard let passwordData = password.data(using: .utf8) else { throw NSError(domain: "KeyDerivationError", code: 4, userInfo: [NSLocalizedDescriptionKey: "密码转UTF-8数据失败"]) } let result = derivedKeyData.withUnsafeMutableBytes { derivedKeyBytes in salt.withUnsafeBytes { saltBytes in CCKeyDerivationPBKDF( CCPBKDFAlgorithm(kCCPBKDF2), passwordData.baseAddress?.assumingMemoryBound(to: CChar.self), passwordData.count, saltBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), salt.count, CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA512), UInt32(iterations), derivedKeyBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), keyLength ) } } guard result == kCCSuccess else { throw NSError(domain: NSOSStatusErrorDomain, code: Int(result), userInfo: [NSLocalizedDescriptionKey: "PBKDF2密钥派生失败,错误码:\(result)"]) } return derivedKeyData }
更简洁的实现(基于CryptoKit,iOS 13+/macOS 10.15+)
苹果官方的CryptoKit框架封装了PBKDF2的实现,无需手动处理C接口的内存和指针,代码更简洁安全:
import CryptoKit func createKey(secretKey: String, secretId: String) throws -> SymmetricKey { guard let salt = secretId.data(using: .utf8) else { throw NSError(domain: "KeyDerivationError", code: 1, userInfo: [NSLocalizedDescriptionKey: "secretId转UTF-8数据失败"]) } guard let secretKeyData = Data(base64Encoded: secretKey) else { throw NSError(domain: "KeyDerivationError", code: 2, userInfo: [NSLocalizedDescriptionKey: "secretKey不是有效的Base64格式"]) } guard let finalKey = String(data: secretKeyData, encoding: .utf8) else { throw NSError(domain: "KeyDerivationError", code: 3, userInfo: [NSLocalizedDescriptionKey: "secretKey解码后无法转为UTF-8字符串"]) } let passwordData = finalKey.data(using: .utf8)! let derivedKey = try PBKDF2<SHA512>.deriveKey( password: passwordData, salt: salt, iterations: 10000, derivedKeyLength: 32 // 256位密钥对应32字节 ) return SymmetricKey(data: derivedKey) }
逻辑对齐说明
以上两种实现都和你的Java代码逻辑完全一致:
- 将
secretId作为盐,采用UTF-8编码 - 对传入的
secretKey做Base64解码,得到原始字符串 - 使用PBKDF2WithHmacSHA512算法,10000次迭代,生成256位的AES密钥
内容的提问来源于stack exchange,提问作者coder hard
相关产品推荐
相关产品推荐

