iOS中的三重DES解密

时间:2016-12-19 18:21:22

标签: ios encryption

我目前正在iOS上使用以下三重DES解密:

    NSString* plainText = @"My Text";
    NSString* keyText = @"cf6f1ed3bf0a156e";

    NSData *plainData = [plainText dataUsingEncoding:NSUTF8StringEncoding];
    NSData *keyData = [keyText dataUsingEncoding:NSUTF8StringEncoding];

    size_t bufferSize = plainData.length + kCCBlockSize3DES;
    NSMutableData *cypherData = [NSMutableData dataWithLength:bufferSize];
    size_t movedBytes = 0;

    CCCryptorStatus ccStatus;
    ccStatus = CCCrypt(kCCDecrypt,
            kCCAlgorithm3DES,
            kCCOptionECBMode,
            keyData.bytes,
            kCCBlockSize3DES,
            NULL,
            plainData.bytes,
            plainData.length,
            cypherData.mutableBytes,
            cypherData.length,
            &movedBytes);

    cypherData.length = movedBytes;

    if( ccStatus == kCCSuccess ) {
        NSLog(@"Data: %@",cypherData);
        NSLog(@"Data encoded string: %@",[NSString stringWithUTF8String:[cypherData bytes]]);
        NSLog(@"Data encoded: %@",[[NSString alloc] initWithData:cypherData encoding:NSUTF8StringEncoding]);
    } else {
        NSLog(@"Failed DES decrypt ...");
        return nil;
    }

但是,我一直在控制台中获得以下内容:

  

数据:   数据编码字符串:(null)   数据编码:( null)

有关为何发生这种情况的任何想法?任何人都可以看到此代码存在任何问题吗?

2 个答案:

答案 0 :(得分:3)

您的密钥长度为16个字节。 3DES需要一个24字节长的密钥(感谢Zaph进行纠正;还注意到你只读了8个字节)。这可能不会导致此错误,但意味着密钥不是您认为的那样。

字符串中的一系列十六进制数字只是UTF-8值。 “00”不是0x00,0x00。它是0x30,0x30。

你在(null)获得NSLog(@"Data encoded string: %@",[NSString stringWithUTF8String:[cypherData bytes]]); 的原因是:

[NSData base64EncodedStringWithOptions:]

加密输出不太可能是合法的UTF-8字符串。如果要将随机数据编码为字符串,则需要使用十六进制编码或Base64编码等编码。 Base64是内置的,您可以使用In [14]: s = pd.Series(pd.timedelta_range(start='1 days', end='12 days', freq='3000T')) In [15]: s Out[15]: 0 1 days 00:00:00 1 3 days 02:00:00 2 5 days 04:00:00 3 7 days 06:00:00 4 9 days 08:00:00 5 11 days 10:00:00 dtype: timedelta64[ns] In [16]: s.dt.days Out[16]: 0 1 1 3 2 5 3 7 4 9 5 11 dtype: int64 对其进行编码。

答案 1 :(得分:2)

将失败消息更改为:

NSLog(@"Failed DES decrypt, status: %d", ccStatus);

您会看到-4300状态并在CommonCryptoError.h中查找以查找:
kCCParamError = -4300
@constant kCCParamError Illegal parameter value.

如果您不忽略它们,状态错误可能是您的朋友。

  1. 您正在指定3DES,其密钥长度应为24字节,您提供的是16字节。您可能最好更改为kCCAlgorithmDESkCCBlockSizeDES(请参阅下一点)。但密钥可能是十六进制编码,需要解码为8字节。

  2. 在调用中,第5个参数为size_t keyLength,但您提供的是kCCBlockSize3DES,即8个字节。键和块大小不一定相同。

  3. 默认情况下没有填充,这意味着要加密的数据必须是块大小的精确倍数(8字节)。将另一个字节添加到输入数据或指定kCCOptionPKCS7Padding作为选项。

  4. 通常,不可能直接在字符串中表示加密结果,特别是UTF-8表示 - 存在不可显示的字节值。因此,如果您需要编码Base64或十六进制的字符串,则通常会使用。

  5. 注意:密钥可能是16字节,并且需要双密钥3DES,在这种情况下,复制并将前8个字节附加到密钥以生成24字节3DES密钥。你需要掌握算法,关键和选项。

    此示例代码有效,但既不是最佳的也不是安全的,而是让您前进的起点:

    您可以通过提供24字节密钥并将kCCAlgorithmDES更改为kCCAlgorithm3DES并将kCCKeySizeDES更改为kCCKeySize3DES

    来将此更改为3DES
    NSString* plainText = @"My Text-";
    NSString* keyText = @"cf6f1ed3";
    
    NSData *plainData = [plainText dataUsingEncoding:NSUTF8StringEncoding];
    NSData *keyData = [keyText dataUsingEncoding:NSUTF8StringEncoding];
    
    size_t bufferSize = plainData.length + kCCBlockSizeDES;
    NSMutableData *cypherData = [NSMutableData dataWithLength:bufferSize];
    size_t movedBytes = 0;
    
    CCCryptorStatus ccStatus;
    ccStatus = CCCrypt(kCCDecrypt,
                       kCCAlgorithmDES,
                       kCCOptionECBMode,
                       keyData.bytes,
                       kCCKeySizeDES,
                       NULL,
                       plainData.bytes,
                       plainData.length,
                       cypherData.mutableBytes,
                       cypherData.length,
                       &movedBytes);
    
    cypherData.length = movedBytes;
    
    if( ccStatus == kCCSuccess ) {
        NSLog(@"Data: %@"encoded,cypherData);
    } else {
        NSLog(@"Failed DES decrypt, status: %d", ccStatus);
    }
    

    但出于安全原因,请使用随机IV的AES,如果可能的话使用RNCryptor,它将为您处理所有令人讨厌但重要的细节。