You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中基于字节数组创建RSA公钥失败,求无第三方库解决方案

解决SecKeyCreateWithData创建RSA公钥报错-50的问题

碰到这个SecKeyCreateWithData报错NSOSStatusErrorDomain Code=-50的问题,我太熟悉了!本质就是公钥数据格式不符合Apple Security框架的要求,咱们一步步排查解决:

核心原因:公钥数据格式不对

SecKeyCreateWithData并不接受裸的RSA模(n)+指数(e)字节数组,它要求的是DER编码的PKCS#1或PKCS#8格式的公钥数据。如果你的PublicKeyDataDevQA是直接拼接模和指数得到的,或者格式不对,必然会触发这个错误。

解决方案步骤

1. 确认你的公钥原始形态

分两种情况处理:

  • 情况一:有PEM格式公钥
    如果你的公钥原本是PEM格式(开头是-----BEGIN RSA PUBLIC KEY-----),需要先去掉头尾标记和换行符,然后Base64解码得到DER格式数据,再传入SecKeyCreateWithData。
  • 情况二:只有模和指数的字节数组
    这种情况需要手动组装成PKCS#1格式的DER编码数据,下面是封装好的Swift函数:
    func rsaPublicKeyDataFromModulus(_ modulus: Data, exponent: Data) -> Data? {
        // PKCS#1 RSAPublicKey ASN.1结构定义
        // 先构建基础的ASN.1头部,这里适配1024位RSA公钥
        var asn1Header: [UInt8] = [
            0x30, 0x82, 0x01, 0x22, // SEQUENCE标签+长度占位
            0x02, 0x82, 0x01, 0x01, // INTEGER(模)的标签+长度
        ]
        
        // 处理模数据:如果最高位是1,补0x00避免被解析为负数
        var modulusData = modulus
        if (modulusData[0] & 0x80) != 0 {
            modulusData.insert(0x00, at: 0)
        }
        
        // 处理指数数据(通常是65537,即0x010001)
        let exponentHeader: [UInt8] = [
            0x02, 0x03, // INTEGER(指数)的标签+长度
        ]
        var exponentData = exponent
        if (exponentData[0] & 0x80) != 0 {
            exponentData.insert(0x00, at: 0)
        }
        
        // 拼接所有部分
        var derData = Data(asn1Header)
        derData.append(modulusData)
        derData.append(exponentHeader)
        derData.append(exponentData)
        
        // 修正SEQUENCE的实际长度
        let totalLength = derData.count - 2
        derData[1] = UInt8(totalLength >> 16)
        derData[2] = UInt8(totalLength >> 8)
        derData[3] = UInt8(totalLength)
        
        return derData
    }
    

2. 修正公钥创建代码

用上面的函数生成正确的DER数据后,再调用SecKeyCreateWithData,同时注意属性字典的正确性:

// 假设你已经拆分出模和指数的Data
let modulusData: Data = ... // 你的RSA模字节数组
let exponentData: Data = ... // 你的RSA指数字节数组

guard let correctPublicKeyData = rsaPublicKeyDataFromModulus(modulusData, exponent: exponentData) else {
    print("无法生成正确的DER格式公钥")
    return
}

// 属性字典:确保KeySize和你的公钥长度一致(1024/2048等)
let attributes: [String: Any] = [
    kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
    kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
    kSecAttrKeySizeInBits as String: 1024 // 这里要匹配你的公钥实际长度
]

var pubKeyCreateError: Unmanaged<CFError>?
if let publicKey = SecKeyCreateWithData(correctPublicKeyData as CFData, attributes as CFDictionary, &pubKeyCreateError) {
    print("公钥创建成功!")
    // 接下来可以用SecKeyEncrypt加密密码
    let password = "your_password".data(using: .utf8)!
    var encryptError: Unmanaged<CFError>?
    if let encryptedData = SecKeyEncrypt(publicKey, .pkcs1, password as CFData, &encryptError) {
        print("密码加密成功:\(encryptedData as Data)")
    } else {
        print("加密失败:\(encryptError?.takeRetainedValue() ?? "")")
    }
} else {
    if let error = pubKeyCreateError?.takeRetainedValue() {
        print("SecKeyCreateWithData failed: \(error.localizedDescription)")
        print("错误详情:\(error)")
    }
}

3. 额外排查点

  • 检查kSecAttrKeySizeInBits的值是否和你的公钥实际长度一致,比如公钥是2048位的,这里要改成2048,否则也会触发错误。
  • 打印correctPublicKeyData的长度:1024位RSA的PKCS#1 DER数据大概是162字节左右,如果长度偏差太大,说明格式组装有误。

内容的提问来源于stack exchange,提问作者Kannan Prasad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:00:04