Swift中RSA加密块大小为256,如何适配300+字节文本加密?
解决RSA OAEP SHA512加密大文本及提升块大小的问题
一、关于提升RSA加密块大小到512字节
RSA的加密块大小完全由密钥长度决定:
- 256字节块对应2048位RSA密钥(2048 ÷ 8 = 256)
- 512字节块对应4096位RSA密钥(4096 ÷ 8 = 512)
要达到512字节的块大小,你需要:
- 生成或从服务器获取4096位的RSA公钥,替换当前使用的2048位密钥
- 注意:即使是4096位密钥,使用
rsaEncryptionOAEPSHA512算法时,实际可加密的明文长度会小于512字节——OAEP填充会占用SHA512哈希长度(64字节)+ 2字节的填充开销,所以最大明文长度约为512 - 64 - 2 = 446字节,依然无法直接加密更大的文本。因此,加密大文本的标准方案是混合加密。
二、加密大文本的标准方案:混合加密
RSA适合加密小数据(比如对称密钥),对称加密(如AES)适合加密大文本,结合两者的步骤如下:
- 生成随机的AES对称密钥(推荐用AES-256-GCM,自带认证,更安全)
- 用AES密钥加密你的大文本
- 用RSA公钥加密AES密钥
- 将「加密后的AES密钥」+「AES加密后的文本」+「AES的IV/认证标签」打包发送给服务器
- 服务器端先用RSA私钥解密出AES密钥,再用AES密钥解密文本
Swift代码实现
1. 生成AES密钥和IV
func generateAESKey() throws -> Data { var key = Data(count: 32) // AES-256需要32字节密钥 let result = key.withUnsafeMutableBytes { bytes in SecRandomCopyBytes(kSecRandomDefault, 32, bytes.baseAddress!) } guard result == errSecSuccess else { throw NSError(domain: "AESKeyError", code: Int(result), userInfo: nil) } return key } func generateIV() -> Data { var iv = Data(count: 12) // GCM模式推荐12字节IV iv.withUnsafeMutableBytes { bytes in SecRandomCopyBytes(kSecRandomDefault, 12, bytes.baseAddress!) } return iv }
2. AES-GCM加密文本
func aesEncrypt(plainText: String, key: Data, iv: Data) throws -> (cipherData: Data, tag: Data) { let plainData = plainText.data(using: .utf8)! let tagLength = 16 // GCM认证标签长度,推荐16字节 var cipherData = Data(count: plainData.count) var tag = Data(count: tagLength) let status = cipherData.withUnsafeMutableBytes { cipherBytes in tag.withUnsafeMutableBytes { tagBytes in plainData.withUnsafeBytes { plainBytes in iv.withUnsafeBytes { ivBytes in key.withUnsafeBytes { keyBytes in CCCrypt( CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmAES), CCOptions(kCCModeGCM), keyBytes.baseAddress, key.count, ivBytes.baseAddress, plainBytes.baseAddress, plainData.count, cipherBytes.baseAddress, cipherData.count, tagBytes.baseAddress, tagLength ) } } } } } guard status == kCCSuccess else { throw NSError(domain: "AESEncryptError", code: Int(status), userInfo: nil) } return (cipherData, tag) }
3. 完整的混合加密函数
func hybridEncrypt(plainText: String, publicKey: SecKey, algorithm: SecKeyAlgorithm = .rsaEncryptionOAEPSHA512) throws -> [String: String] { // 1. 生成AES密钥和IV let aesKey = try generateAESKey() let iv = generateIV() // 2. AES加密文本 let (aesCipherData, tag) = try aesEncrypt(plainText: plainText, key: aesKey, iv: iv) // 3. RSA加密AES密钥 var error: Unmanaged<CFError>? guard SecKeyIsAlgorithmSupported(publicKey, .encrypt, algorithm) else { fatalError("Algorithm not supported by public key") } guard let encryptedAESKeyData = SecKeyCreateEncryptedData(publicKey, algorithm, aesKey as CFData, &error) else { throw error!.takeRetainedValue() as Error } // 4. 转换为Base64字符串,方便传输 let encryptedAESKey = (encryptedAESKeyData as Data).base64EncodedString() let encryptedText = aesCipherData.base64EncodedString() let ivBase64 = iv.base64EncodedString() let tagBase64 = tag.base64EncodedString() // 返回打包后的结果 return [ "encrypted_key": encryptedAESKey, "encrypted_text": encryptedText, "iv": ivBase64, "tag": tagBase64 ] }
三、服务器端处理逻辑(简要说明)
服务器需要:
- 用RSA私钥解密
encrypted_key得到AES密钥 - 用AES密钥、
iv、tag解密encrypted_text得到原始文本
内容的提问来源于stack exchange,提问作者Satyam
相关产品推荐
相关产品推荐

