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

Swift使用RSA/ECB/OAEPWithSHA-256AndMGF1Padding加密出现填充错误求助

RSA加密解密填充错误问题排查与修复

问题场景

后端提供RSA公钥,需使用RSA/ECB/OAEPWithSHA-256AndMGF1Padding算法加密数据后发送至服务器,但当前Swift实现加密后,后端解密时报错:解密时填充错误(原英文错误:Padding error in decryption)。

原实现代码:

static func encrypt(string: String, publicKey: String?) -> String? {
        guard let publicKey = publicKey else { return nil }
        
        let keyString = publicKey.replacingOccurrences(of: "-----BEGIN RSA PUBLIC KEY-----\n", with: "").replacingOccurrences(of: "\n-----END RSA PUBLIC KEY-----", with: "")
        guard let data = Data(base64Encoded: keyString) else { return nil }
        
        var attributes: CFDictionary {
            return [kSecAttrKeyType         : kSecAttrKeyTypeRSA,
                    kSecAttrKeyClass        : kSecAttrKeyClassPublic,
                    kSecAttrKeySizeInBits   : 2048,
                    kSecReturnPersistentRef : true] as CFDictionary
        }
        
        var error: Unmanaged<CFError>? = nil
        guard let secKey = SecKeyCreateWithData(data as CFData, attributes, &error) else {
            print(error.debugDescription)
            return nil
        }
        return encrypt(string: string, publicKey: secKey)
    }
static func encrypt(string: String, publicKey: SecKey) -> String? {
            let bufferData = string.data(using: .utf8)!
            
            var error: Unmanaged<CFError>?
            guard let encryptedData = SecKeyCreateEncryptedData(
                publicKey,
                .rsaEncryptionOAEPSHA256, // Specify OAEP with SHA-256 padding
                bufferData as CFData,
                &error
            ) as Data? else { return nil }
            return encryptedData.base64EncodedString()
        }

问题原因与修复方案

1. 公钥格式处理不鲁棒

原代码仅替换固定换行的头尾标记,若公钥中的换行符为\r\n或无换行,会导致残留无效字符,影响密钥解析。

修复:统一去掉头尾标记,并修剪所有空白字符(包括换行、空格):

let keyString = publicKey
    .replacingOccurrences(of: "-----BEGIN RSA PUBLIC KEY-----", with: "")
    .replacingOccurrences(of: "-----END RSA PUBLIC KEY-----", with: "")
    .trimmingCharacters(in: .whitespacesAndNewlines)

2. MGF1哈希算法不匹配

RSA/ECB/OAEPWithSHA-256AndMGF1Padding要求MGF1掩码生成函数使用SHA-256,但Swift默认的.rsaEncryptionOAEPSHA256仅指定了加密哈希为SHA-256,MGF1默认用SHA-1,与后端算法不一致导致填充错误。

修复:显式指定MGF1哈希算法为SHA-256:

static func encrypt(string: String, publicKey: SecKey) -> String? {
    guard let bufferData = string.data(using: .utf8) else { return nil }
    
    // 配置OAEP参数:加密哈希和MGF1哈希均为SHA-256
    let oaepParams = [
        kSecKeyEncryptionOAEPHashAttribute: kSecDigestSHA256,
        kSecKeyEncryptionOAEPEncodingMGF1Attribute: kSecDigestSHA256
    ] as CFDictionary
    
    var error: Unmanaged<CFError>?
    guard let encryptedData = SecKeyCreateEncryptedData(
        publicKey,
        .rsaEncryptionOAEPSHA256,
        bufferData as CFData,
        oaepParams,
        &error
    ) as Data? else {
        print(error?.takeRetainedValue() ?? "加密失败")
        return nil
    }
    return encryptedData.base64EncodedString()
}

3. 冗余密钥属性干扰

原代码中kSecReturnPersistentRef : true属于密钥持久化属性,临时创建加密密钥时无需设置,可能导致密钥初始化异常。

修复:移除该属性,简化密钥属性字典:

var attributes: CFDictionary {
    return [
        kSecAttrKeyType: kSecAttrKeyTypeRSA,
        kSecAttrKeyClass: kSecAttrKeyClassPublic,
        kSecAttrKeySizeInBits: 2048
    ] as CFDictionary
}

完整修复后代码

static func encrypt(string: String, publicKey: String?) -> String? {
    guard let publicKey = publicKey else { return nil }
    
    // 鲁棒处理公钥格式
    let keyString = publicKey
        .replacingOccurrences(of: "-----BEGIN RSA PUBLIC KEY-----", with: "")
        .replacingOccurrences(of: "-----END RSA PUBLIC KEY-----", with: "")
        .trimmingCharacters(in: .whitespacesAndNewlines)
    
    guard let data = Data(base64Encoded: keyString) else { return nil }
    
    // 简化密钥属性
    var attributes: CFDictionary {
        return [
            kSecAttrKeyType: kSecAttrKeyTypeRSA,
            kSecAttrKeyClass: kSecAttrKeyClassPublic,
            kSecAttrKeySizeInBits: 2048
        ] as CFDictionary
    }
    
    var error: Unmanaged<CFError>? = nil
    guard let secKey = SecKeyCreateWithData(data as CFData, attributes, &error) else {
        print(error?.takeRetainedValue() ?? "公钥解析失败")
        return nil
    }
    return encrypt(string: string, publicKey: secKey)
}

static func encrypt(string: String, publicKey: SecKey) -> String? {
    guard let bufferData = string.data(using: .utf8) else { return nil }
    
    // 指定MGF1哈希为SHA-256
    let oaepParams = [
        kSecKeyEncryptionOAEPHashAttribute: kSecDigestSHA256,
        kSecKeyEncryptionOAEPEncodingMGF1Attribute: kSecDigestSHA256
    ] as CFDictionary
    
    var error: Unmanaged<CFError>?
    guard let encryptedData = SecKeyCreateEncryptedData(
        publicKey,
        .rsaEncryptionOAEPSHA256,
        bufferData as CFData,
        oaepParams,
        &error
    ) as Data? else {
        print(error?.takeRetainedValue() ?? "加密失败")
        return nil
    }
    return encryptedData.base64EncodedString()
}

内容的提问来源于stack exchange,提问作者Axtamov O'lmas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 17:26:09