Swift中RSA私钥从数据创建失败问题的解决方法
RSA私钥创建失败(Code=-50)的解决方案
问题背景
使用自定义RSA结构体执行解密操作时,在创建SecKey私钥实例环节报错:
Optional(Swift.Unmanaged<__C.CFErrorRef>(_value: Error Domain=NSOSStatusErrorDomain Code=-50 "RSA private key creation from data failed" UserInfo={numberOfErrorsDeep=0, NSDescription=RSA private key creation from data failed}))
核心原因
你的私钥是PKCS#8格式的Base64字符串,但SecKeyCreateWithData默认会按PKCS#1格式解析私钥数据,格式不匹配导致创建失败。此外,解密环节还存在加密数据处理错误的问题。
解决方案
1. 修改私钥解析属性,适配PKCS#8格式
在解密方法的attributes字典中,新增kSecAttrKeyDataVersion字段指定私钥格式为PKCS#8:
var attributes: CFDictionary { return [kSecAttrKeyType : kSecAttrKeyTypeRSA, kSecAttrKeyClass : kSecAttrKeyClassPrivate, kSecAttrKeySizeInBits : keySizeInBits, kSecAttrKeyDataVersion : kSecAttrKeyDataVersionPKCS8] as CFDictionary }
2. 修复加密数据的解码错误
加密结果是Base64编码字符串,不能直接转UTF8字节数组,需要先解码为原始二进制数据再传入解密方法:
// 替换原代码中的let buffer = [UInt8](string.utf8) guard let encryptedData = Data(base64Encoded: string), !encryptedData.isEmpty else { print("Invalid encrypted string") return nil } let buffer = [UInt8](encryptedData)
3. 修正后完整的解密方法
func decrypt(string: String, privateKey: String?) -> String? { guard let privateKey = privateKey else { return nil } let keyString = privateKey .replacingOccurrences(of: "-----BEGIN RSA PRIVATE KEY-----\n", with: "") .replacingOccurrences(of: "\n-----END RSA PRIVATE KEY-----", with: "") .replacingOccurrences(of: "\r\n", with: "") guard let data = Data(base64Encoded: keyString, options: .ignoreUnknownCharacters) else { return nil } var attributes: CFDictionary { return [kSecAttrKeyType : kSecAttrKeyTypeRSA, kSecAttrKeyClass : kSecAttrKeyClassPrivate, kSecAttrKeySizeInBits : keySizeInBits, kSecAttrKeyDataVersion : kSecAttrKeyDataVersionPKCS8] as CFDictionary } var error: Unmanaged<CFError>? = nil guard let secKey = SecKeyCreateWithData(data as CFData, attributes, &error) else { print(error.debugDescription) return nil } // 修复Base64解码逻辑 guard let encryptedData = Data(base64Encoded: string), !encryptedData.isEmpty else { print("Invalid encrypted string") return nil } let buffer = [UInt8](encryptedData) let keySize = SecKeyGetBlockSize(secKey) var messageDecrypted = [UInt8](repeating: 0, count: keySize) var messageDecryptedSize = keySize var status = SecKeyDecrypt(secKey, SecPadding.PKCS1, buffer, buffer.count, &messageDecrypted, &messageDecryptedSize) if status != noErr { print("Decryption Error!") return nil } // 仅提取实际解密的有效数据(去除填充的空字节) let resultData = Data(bytes: messageDecrypted, count: messageDecryptedSize) let result = String(data: resultData, encoding: .utf8) print(result) return result }
内容的提问来源于stack exchange,提问作者David Murillo
相关产品推荐
相关产品推荐

