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

Swift中无法将Base64解密数据转换为字符串的问题排查

AES128解密后无法转成UTF8字符串的问题排查与修复

核心问题分析

你的Swift代码解密后无法生成UTF8字符串,本质是解密过程参数不匹配导致输出无效二进制数据,具体问题如下:

1. 密钥与IV的长度/内容不匹配

  • 密钥长度错误:AES128要求密钥为16字节,但你Swift代码中硬编码的keyData = "qwertyuiopasdfghjklzxcvabc"长度远超16字节,CCCrypt会自动截断前16字节使用,这和Java端的keyAES大概率不一致。
  • IV长度不足:AES-CBC模式要求IV长度等于块大小(16字节),你Swift里的ivData = "appnameivdata"仅13字节,会直接导致CCCrypt参数错误,解密结果完全无效。
  • 内容不一致:Swift中的密钥和IV必须与Java端的keyAES、IvAES完全相同,包括大小写、UTF-8编码格式。

2. AES加密模式与填充方式未对齐

Java的encryptAES虽未给出实现,但通常默认是AES/CBC/PKCS5Padding(PKCS5与PKCS7填充在AES中兼容),你的Swift代码用kCCOptionPKCS7Padding是正确的,但需确保Java端也是CBC模式(ECB模式无需IV但安全性极低,一般不会使用)。

3. 冗余步骤与潜在数据污染

你怀疑的String(data: data, encoding: .utf8)步骤本身无问题,但可优化为直接用Data(base64Encoded: data),避免字符串转码时的潜在污染(如多余换行、空格)。

修复方案

步骤1:修正密钥与IV的长度和内容

确保Swift中的密钥和IV与Java端完全一致:

// 替换为Java端的keyAES字符串,必须是16字节(UTF-8编码)
let keyData = "你的Java密钥keyAES".data(using: .utf8)!
// 替换为Java端的IvAES字符串,必须是16字节(UTF-8编码)
let ivData = "你的Java向量IvAES".data(using: .utf8)!

注意:若Java端密钥/IV非16字节,则说明不是AES128,需对应调整Swift中的keyLength(如AES256对应32字节)。

步骤2:添加参数合法性校验

在testCrypt方法中加入密钥和IV的长度检查:

guard ivData.count == kCCBlockSizeAES128 else {
    print("IV长度必须为16字节")
    return Data()
}
guard keyData.count == keyLength else {
    print("密钥长度必须为\(keyLength)字节")
    return Data()
}

步骤3:优化Base64解码逻辑

直接从文件数据解码Base64,跳过字符串转码步骤:

// 替换原有的dataStr和encrypted解码逻辑
guard let encrypted = Data(base64Encoded: data, options: .ignoreUnknownCharacters) else {
    print("unable decode base64")
    return
}

步骤4:完善错误处理

根据CCCrypt返回码明确错误类型:

switch cryptStatus {
case kCCSuccess:
    cryptData.removeSubrange(numberBytesEncrypted..<cryptData.count)
case kCCParamError:
    print("错误:参数无效(密钥/IV长度错误)")
    cryptData = Data()
case kCCBufferTooSmall:
    print("错误:输出缓冲区太小")
    cryptData = Data()
case kCCMemoryFailure:
    print("错误:内存分配失败")
    cryptData = Data()
default:
    print("错误:未知错误码\(cryptStatus)")
    cryptData = Data()
}

完整修正后的testCrypt示例

static func testCrypt(data: Data, operation: EncrptyOperation) -> Data {
    let cryptLength = data.count + kCCBlockSizeAES128
    var cryptOperation: CCOperation = operation == .Encrypt ? kCCEncrypt : kCCDecrypt
    var cryptData = Data(count: cryptLength)
    
    let keyLength = kCCKeySizeAES128
    let options = CCOptions(kCCOptionPKCS7Padding)
    // 替换为Java端的真实密钥和IV(示例为16字节)
    let keyData = "qwertyuiopasdfgh".data(using: .utf8)!
    let ivData = "1234567890abcdef".data(using: .utf8)!
    
    // 参数校验
    guard ivData.count == kCCBlockSizeAES128 else {
        print("IV长度必须为16字节")
        return Data()
    }
    guard keyData.count == keyLength else {
        print("密钥长度必须为\(keyLength)字节")
        return Data()
    }
    
    var numberBytesEncrypted: size_t = 0
    let cryptStatus = cryptData.withUnsafeMutableBytes { cryptBytes in
        data.withUnsafeBytes { dataBytes in
            ivData.withUnsafeBytes { ivBytes in
                keyData.withUnsafeBytes { keyBytes in
                    CCCrypt(cryptOperation,
                            CCAlgorithm(kCCAlgorithmAES128), options,
                            keyBytes.baseAddress,
                            keyLength,
                            ivBytes.baseAddress,
                            dataBytes.baseAddress,
                            data.count,
                            cryptBytes.baseAddress,
                            cryptLength,
                            &numberBytesEncrypted)
                }
            }
        }
    }
    
    switch cryptStatus {
    case kCCSuccess:
        cryptData.removeSubrange(numberBytesEncrypted..<cryptData.count)
    case kCCParamError:
        print("错误:参数无效(密钥/IV长度错误)")
        cryptData = Data()
    case kCCBufferTooSmall:
        print("错误:输出缓冲区太小")
        cryptData = Data()
    case kCCMemoryFailure:
        print("错误:内存分配失败")
        cryptData = Data()
    default:
        print("错误:未知错误码\(cryptStatus)")
        cryptData = Data()
    }
    return cryptData
}

额外验证建议

  1. 对比Java加密后的Base64字符串解码结果与Swift中encrypted数据,确认Base64解码正确。
  2. 使用本地离线AES解密工具验证密钥、IV、模式的正确性,确保解密后能得到明文。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 04:30:46