Swift中如何从PEM字符串生成公钥并解决加密乱码问题?
解决你的RSA加密乱码与跨平台一致性问题
你的问题核心是加密结果的编码格式不匹配,再加上可能存在的算法、证书处理对齐问题,我一步步帮你梳理解决:
1. 为什么会出现乱码?
加密生成的cipherText是二进制Data类型,这类数据包含大量不可打印的控制字符,直接转字符串必然会出现乱码。而Android团队能得到正常字符串,是因为他们对加密后的二进制数据做了Base64编码,把二进制转成了可打印的ASCII字符集。
你需要在返回结果前,给加密后的Data做Base64编码,修改后的Swift代码如下:
调整后的Swift加密代码
func encryptBase64(text: String, certificateStr: String) throws -> String { let encryptionError = EncrpytionError(message: "There has been an issue with encryption") // 先清理证书字符串:移除换行符(避免Base64解码失败) let cleanedCertStr = certificateStr .replacingOccurrences(of: "\n", with: "") .replacingOccurrences(of: "\r", with: "") guard let certData = Data(base64Encoded: cleanedCertStr), let certificate = SecCertificateCreateWithData(nil, certData as CFData), let publicKey = SecCertificateCopyKey(certificate) else { throw encryptionError } // 先保留你的算法,后续需要和Android端对齐 let algorithm: SecKeyAlgorithm = .rsaEncryptionOAEPSHA256AESGCM guard SecKeyIsAlgorithmSupported(publicKey, .encrypt, algorithm) else { throw encryptionError } guard let plainTextData = text.data(using: .utf8) else { throw encryptionError } guard let cipherTextData = SecKeyCreateEncryptedData( publicKey, algorithm, plainTextData as CFData, nil) as Data? else { throw encryptionError } // 关键步骤:将二进制加密结果转成Base64字符串 return cipherTextData.base64EncodedString() }
如果你的调用方必须接收Data类型,也可以返回Data(base64Encoded: cipherTextData.base64EncodedString()),但返回字符串更符合跨平台数据交互的常规做法。
2. 确保加密算法与Android端完全对齐
你的Swift代码使用的是rsaEncryptionOAEPSHA256AESGCM(OAEP填充结合AES-GCM的混合加密),但Android团队只给出了公钥提取逻辑,没有展示加密实现。你需要和他们确认:
- 加密时使用的填充模式:是
RSA/ECB/PKCS1Padding(传统PKCS#1 v1.5填充)还是RSA/ECB/OAEPWithSHA-256AndMGF1Padding? - 如果Android用的是PKCS#1 v1.5填充,你需要把Swift的算法改成
.rsaEncryptionPKCS1,否则两端加密逻辑不兼容,即使编码正确也无法互相解密。
举个例子,如果Android的加密代码是这样的:
fun encrypt(text: String, publicKey: PublicKey): String { val cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding") cipher.init(Cipher.ENCRYPT_MODE, publicKey) val encryptedBytes = cipher.doFinal(text.toByteArray(Charsets.UTF_8)) return Base64.encodeToString(encryptedBytes, Base64.DEFAULT) }
那你Swift里的算法就要替换成:
let algorithm: SecKeyAlgorithm = .rsaEncryptionPKCS1
3. 确认PEM证书的处理逻辑正确
你提到PEM文件是去除首尾标识的字符串,这里要注意:
- 原始PEM证书中的换行符也需要完全移除,否则
Data(base64Encoded:)会解码失败。比如原始PEM是:
-----BEGIN CERTIFICATE----- MIICdzCCAX+gAwIBAgIUY... ... -----END CERTIFICATE-----
你需要去掉首尾的-----BEGIN CERTIFICATE-----和-----END CERTIFICATE-----,同时删除中间所有的换行符,得到一个连续的Base64字符串,才能正确解码成证书数据。
总结
- 给加密后的二进制数据做Base64编码,直接解决乱码问题;
- 和Android团队确认加密算法(填充模式),保证两端逻辑一致;
- 清理PEM证书字符串的换行符,避免证书解码失败。
内容的提问来源于stack exchange,提问作者Fernando Ivan Perez Ruiz
相关产品推荐
相关产品推荐

