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

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字符串,才能正确解码成证书数据。

总结

  1. 给加密后的二进制数据做Base64编码,直接解决乱码问题;
  2. 和Android团队确认加密算法(填充模式),保证两端逻辑一致;
  3. 清理PEM证书字符串的换行符,避免证书解码失败。

内容的提问来源于stack exchange,提问作者Fernando Ivan Perez Ruiz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 18:35:27