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

Swift中使用RSA公钥无法正确加密数据的问题求助

问题描述

我用OpenSSL生成了AES256、2048位的RSA公私钥对,服务器端用OpenSSL加解密完全正常,但在Swift里始终无法成功加密数据。尝试多种方法后,数据看似加密完成,但服务器解密时持续报错:

rsa routines:rsa_ossl_private_decrypt:data greater than mod len:crypto\rsa\rsa_ossl.c:407

以下是我的测试代码(忽略强制解包):

1. 从公钥创建SecKey

private func createSecKey() -> SecKey {
    // Remove headers and footers from the PEM, leaving us with DER encoded data split by new lines
    [
        "-----BEGIN RSA PUBLIC KEY-----", "-----END RSA PUBLIC KEY-----",
        "-----BEGIN PUBLIC KEY-----", "-----END PUBLIC KEY-----"
    ].forEach { publicKey = publicKey.replacingOccurrences(of: $0, with: "") }

    // Construct DER data from the remaining PEM data
    let der = Data(base64Encoded: publicKey, options: .ignoreUnknownCharacters)!
    let attributes: [String: Any] = [
        String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
        String(kSecAttrKeyClass): kSecAttrKeyClassPublic,
        String(kSecAttrKeySizeInBits): der.count * 8
    ]
    let key = SecKeyCreateWithData(der as CFData, attributes as CFDictionary, nil)!
    return key
}

2. 加密数据

private func encryptMessageData(secKey: SecKey, message: String) {
    print(aesKeyPair)
    // An example message to encrypt
    let messageData = message.data(using: .utf8)!
        
    // Perform the actual encryption
    let encryptedMessage = SecKeyCreateEncryptedData(secKey, .rsaEncryptionOAEPSHA256, messageData as CFData, nil)! as Data
    print("=====Encrypted Message Below=====")
    print(encryptedMessage.map { String(format: "%02x", $0) }.joined())
    self.encryptedAESKey.text = cipherText.map { String(format: "%02x", $0) }.joined()
    
}

我尝试把加密结果编码为Base64后再解密:

let base64Data = encryptedMessage.base64EncodedData(options: .endLineWithLineFeed)

服务器端执行解密命令:

openssl pkeyutl -decrypt -inkey tvde_private.pem -in message.decoded > message.txt -pkeyopt rsa_padding_mode:oaep

此时报错:

Public Key operation error
501A0000:error:02000079:rsa routines:RSA_padding_check_PKCS1_OAEP_mgf1:oaep decoding error:crypto\rsa\rsa_oaep.c:314:

我怀疑问题出在加密阶段的算法选择:

let encryptedMessage = SecKeyCreateEncryptedData(secKey, .rsaEncryptionOAEPSHA256, messageData as CFData, nil)! as Data

试过.rsaEncryptionOAEPSHA256和.rsaEncryptionOAEPSHA256AESGCM,但对SecKeyAlgorithm里的算法不太了解,我的密钥是AES256、2048位RSA生成的,求建议。


解决方案

1. 修正公钥解析错误

你的createSecKey方法中,kSecAttrKeySizeInBits设置错误:DER编码的公钥包含ASN.1结构,不能用der.count * 8计算密钥长度,直接指定2048位即可(和你生成的密钥匹配):

let attributes: [String: Any] = [
    String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
    String(kSecAttrKeyClass): kSecAttrKeyClassPublic,
    String(kSecAttrKeySizeInBits): 2048 // 直接匹配密钥长度
]

另外,优先使用PKCS#8格式的公钥(-----BEGIN PUBLIC KEY-----开头),iOS对这种格式支持更稳定。如果你的公钥是PKCS#1格式(-----BEGIN RSA PUBLIC KEY-----),可以用OpenSSL转换:

openssl rsa -in public.pem -pubout -outform PEM -out public_pkcs8.pem

2. 对齐iOS与OpenSSL的OAEP参数

iOS的SecKeyCreateEncryptedData默认用MGF1-SHA256,但OpenSSL默认的OAEP参数是MGF1-SHA1,这是解密报错的核心原因。需要手动指定参数让两端对齐:

// 明确指定OAEP的哈希和MGF1算法
let parameters: [String: Any] = [
    kSecKeyAlgorithmOAEPSHA256 as String: [
        kSecKeyOAEPHashAttribute: kSecDigestSHA256,
        kSecKeyOAEPmgfAttribute: kSecKeyOAEPmgf1SHA256
    ]
]

guard let encryptedMessage = SecKeyCreateEncryptedData(secKey, .rsaEncryptionOAEPSHA256, messageData as CFData, parameters as CFDictionary) as Data? else {
    // 处理加密失败逻辑
    return
}

服务器端解密时,必须指定相同的哈希和MGF1算法:

openssl pkeyutl -decrypt -inkey tvde_private.pem -in message.decoded > message.txt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256

3. 规范数据编码传输

加密后的二进制数据,推荐用Base64编码后传给服务器(避免十六进制转换可能的错误):

let encryptedBase64 = encryptedMessage.base64EncodedString()
// 将encryptedBase64传给服务器

服务器读取Base64文件后直接解密即可,无需额外转码。

4. 遵守RSA加密长度限制

2048位RSA用OAEP-SHA256加密时,最大明文长度为2048/8 - 2*256/8 - 2 = 190字节,超过会触发data greater than mod len错误。这时候应该用你提到的AES256配合RSA:

  • 生成随机AES256密钥
  • 用RSA加密这个AES密钥
  • 用AES加密明文数据
  • 将加密后的AES密钥+AES密文一起传给服务器,服务器先解密AES密钥,再解密明文

内容的提问来源于stack exchange,提问作者Ryan H

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 17:31:04