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

KMM项目iOS端CCCrypt解密AES报错4301问题排查

问题排查与解决方案

错误码4301说明

状态码4301对应kCCDecodeError,核心原因是解密时的参数、数据格式与加密端(PHP/Android)不匹配,或CCCrypt调用参数配置错误。

核心排查步骤

1. 核对加密参数一致性

确保iOS端的AES配置与Android/PHP完全对齐:

  • 加密模式:Android用CBC则iOS必须设kCCModeCBC,不能用ECB或其他模式;
  • 填充方式:Android的PKCS5Padding与iOS的kCCOptionPKCS7Padding等价(块大小16位时无差异),若PHP/Android用NoPadding,iOS需设kCCOptionPKCS7Padding为0,且加密数据长度必须是16字节的整数倍;
  • 密钥长度:AES-128对应16字节密钥,AES-256对应32字节,需与服务端生成逻辑一致,避免密钥截断/填充差异。

2. 验证密钥、IV的字节转换逻辑

  • 确认密钥、IV的编码方式(如UTF-8)与Android端完全相同,不能混用ASCII、UTF-16等编码;
  • 若密钥是字符串转字节,需保证两端转换规则一致(比如PHP用utf8_encode($key),iOS用[key dataUsingEncoding:NSUTF8StringEncoding])。

3. 检查加密数据完整性

即使Base64解码无报错,也要验证解码后的字节数组长度:

  • 用PKCS7填充时,数据长度必须是16字节的整数倍;
  • 若服务端加密后添加了额外校验(如HMAC),需先剥离校验部分再解密。

修正后的Objective-C解密示例

如果必须保留Objective-C实现,以下是符合标准AES-CBC+PKCS7填充的正确调用:

+ (NSData *)aesCBCDecrypt:(NSData *)encryptedData withKey:(NSData *)key iv:(NSData *)iv {
    NSUInteger dataLength = encryptedData.length;
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    
    size_t bytesDecrypted = 0;
    CCCryptorStatus status = CCCrypt(
        kCCDecrypt,
        kCCAlgorithmAES,
        kCCOptionPKCS7Padding,
        key.bytes, key.length,
        iv.bytes,
        encryptedData.bytes, encryptedData.length,
        buffer, bufferSize,
        &bytesDecrypted
    );
    
    if (status == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:bytesDecrypted];
    }
    free(buffer);
    return nil;
}

注意:key和iv必须是NSData类型,且长度分别符合对应AES规格(16/24/32字节)、16字节。

更优替代方案:KMM统一加密逻辑

避免跨语言调用的参数差异,直接用Kotlin Multiplatform的加密库实现两端统一解密:

1. 添加依赖

在项目根build.gradle.kts中引入:

sourceSets {
    val commonMain by getting {
        dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-crypto-core:0.3.0")
        }
    }
}

2. 统一解密代码

import kotlinx.crypto.ciphers.Cipher
import kotlinx.crypto.ciphers.CipherMode
import kotlinx.crypto.ciphers.Padding
import kotlinx.crypto.ciphers.aes.AesCipher
import kotlinx.crypto.core.SecretKey
import kotlinx.crypto.core.toSecretKey

fun decryptAesCbc(encryptedBytes: ByteArray, keyBytes: ByteArray, ivBytes: ByteArray): ByteArray {
    val secretKey = keyBytes.toSecretKey(AesCipher)
    val cipher = Cipher.getInstance(AesCipher, CipherMode.CBC, Padding.PKCS7)
    cipher.init(Cipher.Operation.DECRYPT, secretKey, ivBytes)
    return cipher.doFinal(encryptedBytes)
}

这段代码可直接在Android和iOS端复用,彻底消除两端参数不一致的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 14:15:13