Reputation: 20368
I am trying to use DES
encryption to encrypt passwords (Don't ask why DES, I know it's less secure). I am doing it for the first time in iOS, thus had to rely on another post about how to do it.
When I run the encryption it returns null, same with decrypting an already encrypted string(I used an online tool to encrypt). When I put a breakpoint to see what is going on, it stopped at CCCrypt
mentioning EXC_BAD_ACCESS (Code 2)
.
I tried using different CCOptions, but it returns the same thing always. Any hint what's going wrong? Is iv string required?
I have used the following NSString category to encrypt or decrypt Strings -
#import "NSString+DES.h"
@implementation NSString(DES)
- (NSString*) encryptDES: (NSString *) key
{
const void *vplainText;
size_t plainTextBufferSize;
plainTextBufferSize = [self length];
vplainText = (const void *) [self UTF8String];
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t *movedBytes;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
// memset((void *) iv, 0x0, (size_t) sizeof(iv));
//NSString *initVec = @"init Vec";
const void *vkey = (const void *) [key UTF8String];
//const void *vinitVec = (const void *) [initVec UTF8String];
ccStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmDES,
kCCOptionPKCS7Padding | kCCOptionECBMode,
vkey,
kCCKeySizeDES,
NULL,
vplainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
movedBytes);
NSString *result;
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
result = [myData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return result;
}
- (NSString *) decryptDES: (NSString *) key
{
const void *vplainText;
size_t plainTextBufferSize;
plainTextBufferSize = [self length];
vplainText = (const void *) [self UTF8String];
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t *movedBytes;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
// memset((void *) iv, 0x0, (size_t) sizeof(iv));
//NSString *initVec = @"init Vec";
const void *vkey = (const void *) [key UTF8String];
//const void *vinitVec = (const void *) [initVec UTF8String];
ccStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmDES,
kCCOptionPKCS7Padding | kCCOptionECBMode,
vkey, //"123456789012345678901234", //key
kCCKeySizeDES,
NULL,// vinitVec, //"init Vec", //iv,
vplainText, //"Your Name", //plainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
movedBytes);
NSString *result;
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
result = [myData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return result;
}
@end
Update:
I have checked few more places and changed the code a little bit, the encryption works but doesn't get decrypted with correct value.
For example when I use YourName
as string and 12345
as the key, I get Fu2sK61e7l5rkXRhAKjPWA==
as the encrypted code, but the decryption returns +54qWCYTB5LkdARDZjAow==
and not YourName
.
Updated Code:
#import "NSString+DES.h"
@implementation NSString(DES)
- (NSString*) encryptDES: (NSString *) key
{
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSData *stringData = [self dataUsingEncoding:NSUTF8StringEncoding];
size_t numBytesEncrypted = 0;
size_t bufferSize = stringData.length + kCCBlockSizeDES;
void *buffer = malloc(bufferSize);
CCCryptorStatus result = CCCrypt( kCCEncrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding,
keyData.bytes, kCCKeySizeDES,
NULL,
stringData.bytes, stringData.length,
buffer, bufferSize,
&numBytesEncrypted);
NSData *output = [NSData dataWithBytes:buffer length:numBytesEncrypted];
free(buffer);
if( result == kCCSuccess )
{
NSString *resultStr = [output base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return resultStr;
} else {
NSLog(@"Failed DES encrypt...");
return nil;
}
}
- (NSString *) decryptDES: (NSString *) key
{
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSData *stringData = [[NSData alloc] initWithBase64EncodedString:self options:0];
size_t numBytesEncrypted = 0;
size_t bufferSize = stringData.length + kCCBlockSizeDES;
void *buffer = malloc(bufferSize);
CCCryptorStatus result = CCCrypt( kCCDecrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding,
keyData.bytes, kCCKeySizeDES,
NULL,
stringData.bytes, stringData.length,
buffer, bufferSize,
&numBytesEncrypted);
NSData *output = [NSData dataWithBytes:buffer length:numBytesEncrypted];
free(buffer);
if( result == kCCSuccess )
{
NSString *resultStr = [output base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return resultStr;
} else {
NSLog(@"Failed DES decrypt...");
return nil;
}
}
@end
Upvotes: 4
Views: 588
Reputation: 112873
There seems to be general confusion about the algorithm, DES or 3DES, a mix is being used but the key is 3DES (24-bytes). The key needs to be changed to 8-bytes. The block size constant should also be changed to kCCBlockSizeDES
but that does not cause an error since it is the same value.
For the method:
- (NSString *) decryptDES: (NSString *) key
The bad access error is caused because no storage is allocated for movedBytes
, just a pointer. Change the declaration to:
size_t movedBytes;
Change the reference to movedBytes
in CCCrypt
to &movedBytes
.
Test output for encryption:
string: "Your Name"
key: "12345678"movedBytes: 16
myData: 136142f6 6cd98e01 af1eef46 28d36499
result: E2FC9mzZjgGvHu9GKNNkmQ==
Notes from comments by request:
ECB mode does not use an iv.
The key needs to be exactly 8-bytes for DES, if it is to short the result will be undefined. In the updated code the key is 5-bytes but the length is given as 8-bytes (kCCKeySizeDES
) so the three missing key bytes will be whatever bytes follow keyData
.
The updated answer did not specify ECB mode, the default is CBC mode. Add kCCOptionECBMode
.
In decrypt do not use Base64 encode, convert the data to a NSString
:
NSString * resultStr = [[NSString alloc] initWithData:output encoding:NSUTF8StringEncoding];
If using an online encryption that uses the php mcrypt function the last block of the data will be incorrect because mcrypt does not support PKCS#7 padding, it uses non-standard and insecure null padding.
Upvotes: 1