Reputation: 369
I'm having a problem using the CCCrypt function to simply encrypt/decrypt a chunk of data.
My platform is iOS 8 in Xcode 6.
What I'm doing is, I convert a test string to NSData format and pass it into a wrapper function I made. The return of that function is the encrypted data. I take that encrypted data and then pass it back into the function specifying that it should be decrypted.
I wrapped the use of the encryption/decryption function in a loop so I can see the inconsistent behavior more closely.
The Implementation
NSString* unencryptedString = @"Testtest";
NSData* unencryptedData = [NSData dataWithBytes:(void*)[unencryptedString UTF8String] length:[unencryptedString length]];
NSData* encryptedData = nil;
NSData* decryptedData = nil;
for(int i=0;i<100;i++)
{
encryptedData = [NSData tripleDesEncrypt:YES Data:unencryptedData error:&err];
decryptedData = [NSData tripleDesEncrypt:NO Data:encryptedData error:&err];
NSLog(@"unencrypted: %@, encrypted: %s\n\ndecrypted: %s", unencryptedString, encryptedData.bytes, decryptedData.bytes);
if(err)
NSLog(@"error: %@", err);
}
The Function
+(NSData*)tripleDesEncrypt:(BOOL)encrypt
Data:(NSData *)inputData
error:(NSError **)error
{
NSString* tripleDesKeyString = @"ABCd@Efghijklmno";
NSData* tripleDesKeyData = [tripleDesKeyString dataUsingEncoding:NSUTF8StringEncoding];
const void* tripleDesKey = [tripleDesKeyData bytes];
NSString* ivKeyString = @"012345678901234567890123";
NSData* keyData = [ivKeyString dataUsingEncoding:NSUTF8StringEncoding];
const void* ivKey = [keyData bytes];
NSAssert(keyData.length == kCCKeySize3DES, @"tripleDesEncrypt; the keyData is an invalid size");
NSNumber* pOptions = [NSNumber numberWithInt:kCCOptionPKCS7Padding];
int options = [pOptions intValue];
size_t dataMoved;
unsigned encryptionBufferLen = inputData.length + kCCBlockSize3DES;
void* encryptedBuffer = malloc(encryptionBufferLen);
memset(encryptedBuffer, 0, encryptionBufferLen);
CCCryptorStatus
result = CCCrypt(encrypt ? kCCEncrypt : kCCDecrypt, // operation
kCCAlgorithm3DES, // Algorithm
options, // options
tripleDesKey, // key
tripleDesKeyData.length, // keylength
ivKey,// iv
inputData.bytes, // dataIn
inputData.length, // dataInLength,
encryptedBuffer, // dataOut
encryptionBufferLen, // dataOutAvailable
&dataMoved); // dataOutMoved
NSData* outputData = [NSData dataWithBytes:encryptedBuffer length:dataMoved];
free(encryptedBuffer);
return outputData;
}
The Output
(I'll only run a few iterations of the output to show the weird differences.)
unencrypted: Testtest, encrypted: jgüb -A7‘œåÅKX
decrypted: ¿Ïh5¥√‚qN;1»Í
unencrypted: Testtest, encrypted: ¥⁄˘qÓırS{ÿœ•
decrypted: Æ˛ {íÒ⁄ñè–%4¢‚g
unencrypted: Testtest, encrypted: jgüb -A7‘œåÅKX
decrypted: Testtest∞¸yå`j/private/tmp/com.apple.CoreSimulator.SimDevice.47124028-EC86-4CC0-8CA2-7DCDED3994B1.launchd_sim/syslogsock
unencrypted: Testtest, encrypted: /Âò◊9ƒ˘=m]˚†%À
decrypted: u‹z©tÙÁ∑<%ˇπØ•
unencrypted: Testtest, encrypted: jgüb -A7‘œåÅKX
decrypted: ¿Ïh5¥√‚qN;1»Í
unencrypted: Testtest, encrypted: jgüb -A7‘œåÅKX
decrypted: Testtest
Upvotes: 2
Views: 305
Reputation: 1592
Your key is only 16 bytes long. 3DES keys need to be 24 bytes long. So what is happening is that whatever random 8 bytes happen to be in memory after your tripleDesKey
get used as the rest of key. Who knows what those bytes actually belong to, and their value could very well change in between the encryption call to tripleDesEncrypt
and the decryption call. Different key = different encryption. That would produce the cases where your decryption didn't give back the original plaintext.
(BTW, I don't know why the NAssert
on the key length isn't firing. Might you be compiling in release mode, or similar?)
Solution: increase the length of your key to 24 bytes.
As for the garbage you see at the end of the plaintext after decryption: How are you printing the result? The decrypted plaintext won't have a trailing null char, so if you're using something like printf
then you will need to put a null char at the end of the plainext before printing it. Otherwise the system will happily output the characters after the end of your plaintext until it happens reaches a null char.
Upvotes: 2