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

Android与iOS Triple DES加密结果不一致问题求助

解决Android与iOS TripleDES加密结果不一致的问题

我帮你梳理了Android端的TripleDES加密逻辑,咱们一步步对齐iOS端的实现,就能搞定结果不一致的问题。

先明确Android端的核心加密逻辑

从你给出的代码片段,能拆解出几个关键步骤:

  • 密钥处理流程:
    1. 将密钥字符串以UTF-8编码转为字节数组
    2. 对该数组做MD5哈希,得到16字节的摘要
    3. 把16字节摘要扩展为24字节的3DES密钥:通过循环将前8字节复制到16-23的位置(这是3DES兼容16字节密钥的标准操作,重复前8字节作为第三组密钥)
  • 待确认的细节:
    你没贴全Cipher初始化代码,需要确认Android端用的加密模式(比如ECB/CBC)和填充方式(大概率是PKCS5Padding),还有最终加密结果是转成Base64还是十六进制字符串。

iOS端对应实现(基于CommonCrypto)

下面是完全对齐Android逻辑的iOS代码,你可以根据实际情况调整模式和输出格式:

#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonDigest.h>

// 加密方法:输入明文NSString,输出加密后的字符串(对齐Android输出格式)
+ (NSString *)tripleDESEncryptString:(NSString *)plainStr withSecretKey:(NSString *)secretKey {
    // 1. 明文转UTF-8字节数组,对齐Android的编码方式
    NSData *plainData = [plainStr dataUsingEncoding:NSUTF8StringEncoding];
    if (!plainData) return nil;
    
    // 2. 处理密钥:UTF-8编码 -> MD5摘要 -> 扩展为24字节
    NSData *keyRawData = [secretKey dataUsingEncoding:NSUTF8StringEncoding];
    unsigned char md5Digest[CC_MD5_DIGEST_LENGTH];
    CC_MD5(keyRawData.bytes, (CC_LONG)keyRawData.length, md5Digest);
    
    // 将16字节MD5摘要扩展为24字节:复制前8字节到末尾
    NSMutableData *desKeyData = [NSMutableData dataWithBytes:md5Digest length:CC_MD5_DIGEST_LENGTH];
    unsigned char *keyBytes = (unsigned char *)desKeyData.mutableBytes;
    for (int j = 0; j < 8; j++) {
        keyBytes[16 + j] = keyBytes[j];
    }
    
    // 3. 执行加密:对齐Android的模式和填充
    // 假设Android用的是ECB模式+PKCS5Padding(和iOS的PKCS7Padding等价,因为块大小是8字节)
    size_t bufferSize = plainData.length + kCCBlockSize3DES;
    void *buffer = malloc(bufferSize);
    size_t encryptedLength = 0;
    
    CCCryptorStatus status = CCCrypt(kCCEncrypt,
                                     kCCAlgorithm3DES,
                                     kCCOptionECBMode | kCCOptionPKCS7Padding,
                                     desKeyData.bytes,
                                     kCCKeySize3DES,
                                     NULL, // ECB模式不需要IV
                                     plainData.bytes,
                                     plainData.length,
                                     buffer,
                                     bufferSize,
                                     &encryptedLength);
    
    if (status != kCCSuccess) {
        free(buffer);
        NSLog(@"加密失败:%d", status);
        return nil;
    }
    
    NSData *encryptedData = [NSData dataWithBytesNoCopy:buffer length:encryptedLength];
    // 4. 转成和Android一致的输出格式:如果Android返回Base64就用这个
    NSString *encryptedStr = [encryptedData base64EncodedStringWithOptions:0];
    // 如果是十六进制输出,替换成下面的代码:
    // NSString *encryptedStr = [self hexStringFromData:encryptedData];
    return encryptedStr;
}

// 可选:NSData转十六进制字符串的工具方法
+ (NSString *)hexStringFromData:(NSData *)data {
    NSMutableString *hexStr = [NSMutableString stringWithCapacity:data.length * 2];
    const unsigned char *bytes = data.bytes;
    for (NSUInteger i = 0; i < data.length; i++) {
        [hexStr appendFormat:@"%02x", bytes[i]];
    }
    return hexStr;
}

关键注意事项(一定要核对)

  • 加密模式对齐:如果Android用的是CBC模式,你必须同步使用相同的IV(初始化向量)。比如Android如果用了固定的全0IV,iOS端也要传入全0的IV数据;如果IV是从密钥派生的,要完全复刻派生逻辑。
  • 编码一致性:所有字符串转字节的操作必须用UTF-8,iOS不要用默认的ASCII编码,否则会导致明文/密钥的字节数组不一致。
  • 输出格式统一:Android返回Base64,iOS就转Base64;Android返回十六进制,iOS就转十六进制,别搞混了。
  • 密钥扩展细节:Android里的循环是把前8字节复制到16-23位,不是补0,这个细节一定要在iOS代码里实现,否则密钥会不一样。

如果还是有差异,建议把两端的密钥字节数组、明文字节数组、加密后的原始字节数组都转成十六进制对比,就能快速定位哪一步出了问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:48:39