0

我有以下方法,我想将其移植到基于 CommonCrypto 的方法,但我完全卡住了。非常感谢任何帮助。

- (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;

}

我已经找到了 CommonCrypto 函数

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);

但我不确定如何将我在原始方法中派生的 OpenSSL 参数移植到CCCrypt(...).

4

1 回答 1

0

我通过实施附加的替换方法解决了这个任务。再次感谢所有有用和鼓舞人心的评论。

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];
}
于 2014-08-20T18:12:39.943 回答