我目前正在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)
有关为何发生这种情况的任何想法?任何人都可以看到此代码存在任何问题吗?
答案 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.
如果您不忽略它们,状态错误可能是您的朋友。
您正在指定3DES,其密钥长度应为24字节,您提供的是16字节。您可能最好更改为kCCAlgorithmDES
和kCCBlockSizeDES
(请参阅下一点)。但密钥可能是十六进制编码,需要解码为8字节。
在调用中,第5个参数为size_t keyLength
,但您提供的是kCCBlockSize3DES
,即8个字节。键和块大小不一定相同。
默认情况下没有填充,这意味着要加密的数据必须是块大小的精确倍数(8字节)。将另一个字节添加到输入数据或指定kCCOptionPKCS7Padding
作为选项。
通常,不可能直接在字符串中表示加密结果,特别是UTF-8表示 - 存在不可显示的字节值。因此,如果您需要编码Base64或十六进制的字符串,则通常会使用。
注意:密钥可能是16字节,并且需要双密钥3DES,在这种情况下,复制并将前8个字节附加到密钥以生成24字节3DES密钥。你需要掌握算法,关键和选项。
此示例代码有效,但既不是最佳的也不是安全的,而是让您前进的起点:
您可以通过提供24字节密钥并将kCCAlgorithmDES
更改为kCCAlgorithm3DES
并将kCCKeySizeDES
更改为kCCKeySize3DES
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,它将为您处理所有令人讨厌但重要的细节。