I have the following method, which I would like to port to a CommonCrypto-based approach, but I am completely stuck. Any help is highly appreciated.
- (NSString*) decryptCiscoPassword:(NSString*) encPassword
{
NSUInteger i, k = 0;
NSData *rawData = nil;
int rawInt, rawDataLength = [encPassword length] >> 1;
const char *encString = [encPassword cStringUsingEncoding:NSUTF8StringEncoding];
const char *tmpString;
unsigned char *rawDataBytes = (unsigned char*) malloc(rawDataLength*sizeof(unsigned char));
for(i = 0; i < [encPassword length]; i = i+2)
{
tmpString = &encString[i];
sscanf(tmpString,"%2x",&rawInt);
rawDataBytes[k++] = (unsigned char) rawInt;
}
rawData = [NSData dataWithBytesNoCopy:rawDataBytes length:rawDataLength freeWhenDone:YES];
/* now let's start the decryption */
NSString *returnString = nil;
/* --- calculate 3DES-Key --- */
DES_cblock desKey1, desKey2, desKey3;
unsigned char tempHash[20];
[rawData getBytes:tempHash length:20];
tempHash[19]++;
unsigned char hashV1[20];
CC_SHA1(tempHash,20,hashV1);
unsigned char hashV2[20];
tempHash[19] += 2;
CC_SHA1(tempHash,20,hashV2);
memcpy(&desKey1, hashV1, 8);
memcpy(&desKey2, &hashV1[8], 8);
memcpy(&desKey3, &hashV1[16], 4);
memcpy(&desKey3[4], hashV2, 4);
/* --- Decryption (8 byte blockSize, 24 byte Keylength) --- */
DES_cblock iv;
[rawData getBytes:iv length:8];
NSInteger length = [rawData length];
unsigned char *rawDataChar = (unsigned char*) malloc(length * sizeof(unsigned char));
[rawData getBytes:rawDataChar length:length];
NSInteger blockCount = (length - 40) / 8;
if(blockCount < 1)
{
free(rawDataChar);
return nil; // encPassword is no valid DES-encrypted password!
}
NSUInteger pwLength = blockCount*8;
char* output = (char*) malloc(pwLength*sizeof(char));
DES_key_schedule key_schedule1, key_schedule2, key_schedule3;
DES_set_key_unchecked(&desKey1, &key_schedule1); // generate key_schedule
DES_set_key_unchecked(&desKey2, &key_schedule2); // generate key_schedule
DES_set_key_unchecked(&desKey3, &key_schedule3); // generate key_schedule
DES_ede3_cbc_encrypt((unsigned char*)&rawDataChar[40],(unsigned char*)output, pwLength,&key_schedule1,&key_schedule2,&key_schedule3,&iv,0);
unsigned char len = output[pwLength-1];
/* create null-terminated c-string */
output[pwLength-len] = 0;
/* rescue decrypted string */
returnString = @(output);
/* free allocated memory */
free(rawDataChar);
free(output);
return returnString;
}
I already found the CommonCrypto function
CCCryptorStatus CCCrypt(CCOperation op, CCAlgorithm alg, CCOptions options, const void *key, size_t keyLength, const void *iv, const void *dataIn, size_t dataInLength, void *dataOut, size_t dataOutAvailable, size_t *dataOutMoved);
but I am not sure on how to port the OpenSSL parameters that I derive in my original method to the parameters required by CCCrypt(...)
.
I solved the task by implementing the attached replacement method. Thanks again for all the helpful and inspiring comments.
NSString* CSDecryptCiscoPassword(NSString* encPassword)
{
// convert to C
NSUInteger rawDataLength = [encPassword length] >> 1;
const char *encString = [encPassword cStringUsingEncoding:NSUTF8StringEncoding];
// convert hex to bytes
NSUInteger k = 0;
unsigned char rawDataBytes[rawDataLength];
for(NSUInteger i = 0; i < [encPassword length]; i = i+2)
{
const char *tmpString = &encString[i];
int rawInt;
sscanf(tmpString,"%2x",&rawInt);
rawDataBytes[k++] = (unsigned char) rawInt;
}
const char *h1 = (const char*)rawDataBytes;
const char *h4 = (const char*)rawDataBytes + 20;
const char *enc = (const char*)rawDataBytes + 40;
unsigned char ht[20], h2[20], h3[20], key[24];
const char *iv = h1;
if (rawDataLength < 48)
return nil;
rawDataLength -= 40;
memcpy(ht, h1, 20);
ht[19]++;
CC_SHA1(ht, 20, h2);
ht[19] += 2;
CC_SHA1(ht, 20, h3);
memcpy(key, h2, 20);
memcpy(key+20, h3, 4);
CC_SHA1(enc, rawDataLength, ht);
if (memcmp(h4, ht, 20) != 0)
return nil;
size_t outLength = 0;
NSMutableData *outputData = [NSMutableData dataWithLength:(rawDataLength+kCCBlockSize3DES)];
CCCryptorStatus result = CCCrypt(kCCDecrypt, // operation
kCCAlgorithm3DES, // Algorithm
0, // options
key, // key
24, // keylength
iv,// iv
enc, // dataIn
rawDataLength, // dataInLength,
outputData.mutableBytes, // dataOut
outputData.length, // dataOutAvailable
&outLength); // dataOutMoved
NSString* outString = [[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding];
return [outString autorelease];
}