Reputation: 3270
I'm currently using the following for Triple DES decryption on iOS:
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;
}
However, I keep getting the following in the console:
Data: Data encoded string:(null) Data encoded: (null)
Any ideas as to why this is happening? Can anyone see any possible issues with this code?
Upvotes: 8
Views: 1802
Reputation: 112865
Change the failure message to:
NSLog(@"Failed DES decrypt, status: %d", ccStatus);
You will see a -4300
status and look that up in CommonCryptoError.h
to find:
kCCParamError = -4300
@constant kCCParamError Illegal parameter value.
Status errors can be your friend if you don't ignore them. 😀
You are specifying 3DES which should have a key length of 24-bytes, you are supplying 16-bytes. You are probably better off changing to kCCAlgorithmDES
and kCCBlockSizeDES
(see next point). But the key may be hex encoded and needs to be decoded to 8-bytes.
In the call the 5th parameter is size_t keyLength
but you are supplying kCCBlockSize3DES
which is 8-bytes. Key and block size are not necessarily the same size.
No padding is the default and that means that the data to be encrypted must be an exact multiple of the block size (8-bytes). Either add another byte to the input data or specify kCCOptionPKCS7Padding
as an option.
In general it is not possible to express the result of encryption directly in a character string, particularly not a UTF-8 representation—there are byte values that are not displayable. For this reason if you need a character string encoding either Base64 or hexadecimal are generally used.
Note: There is a possibility the key is 16-bytes and two-key 3DES is needed, in that case duplicate and append the first 8-bytes to the key to make is a 24-byte 3DES key. You need to come to grips with the algorithm, key and options.
This example code works but is neither optimal nor secure but a starting point to get you going:
You can change this to 3DES by supplying a 24-byte key and changing kCCAlgorithmDES
to kCCAlgorithm3DES
and kCCKeySizeDES
to 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);
}
But for security reasons use AES with a random IV, if possible use RNCryptor, it will take care of all the nasty but important details for you.
Upvotes: 2
Reputation: 299565
Your key is 16 bytes long. 3DES takes a key that is 24 bytes long (thanks Zaph for correcting; also noting you're only reading 8 bytes of that). This may not be causing this error, but means the key isn't what you think it is.
A series of hex digits in a string are just UTF-8 values. "00" is not 0x00, 0x00. It's 0x30, 0x30.
The reason you're getting (null)
here is this:
NSLog(@"Data encoded string: %@",[NSString stringWithUTF8String:[cypherData bytes]]);
Cryptographic output is very unlikely to be a legal UTF-8 string. If you want to encode random data as a string, you need an encoding like hex encoding or Base64 encoding. Base64 is built in and you can use [NSData base64EncodedStringWithOptions:]
to encode it.
Upvotes: 3