Расшифровка Objective-C RC4

Я новичок в Objective-C, но я опытный разработчик (С#), но я не могу понять это:

У меня есть строка, зашифрованная RC4, и мне нужно расшифровать ее с помощью Objective-C на iPad (iOS 5.0). Я просмотрел всю сеть в поисках рабочего примера, но мне не удалось найти пример, который работает от начала до конца. Приведенный ниже код не только не возвращает правильно расшифрованную строку, но и возвращает что-то другое при каждом выполнении, что заставляет меня думать, что указатель где-то высвобождается.

Примечание. Не знаю, имеет ли это значение, но строка была зашифрована с помощью http://archive.plugins.jquery.com/project/RC4, а затем сохранен в виде текста в базе данных Sqlite, к которой я сейчас обращаюсь из Objective-C (знаю, архитектура звучит беспорядочно, но я не могу изменить это в данный момент.)

Используемый мной код (взято из шифрование RC4 - CommonCrypto (Objective-C) против PHP):

    + (NSString*)decryptData:(NSData*) dataToDecrypt
    {
        const void *vplainText;
        size_t plainTextBufferSize;


        plainTextBufferSize = [dataToDecrypt length];
        vplainText = [dataToDecrypt bytes];

        CCCryptorStatus ccStatus;
        uint8_t *bufferPtr = NULL;
        size_t bufferPtrSize = 0;
        size_t movedBytes = 0;

        bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
        bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
        memset((void *)bufferPtr, 0x0, bufferPtrSize);

        NSString *key = @"theKeyIUsedtoEncryptInTheFirstPlace";
        const void *vkey = (const void *) [key UTF8String];

        size_t keyLength = [[key dataUsingEncoding:NSUTF8StringEncoding] length]; 
        ccStatus = CCCrypt(kCCDecrypt,
                           kCCAlgorithmRC4,
                           0,
                           vkey,
                           kCCKeySizeDES,
                           nil,
                           vplainText,
                           plainTextBufferSize,
                           (void *)bufferPtr,
                           bufferPtrSize,
                           &movedBytes);
        if (ccStatus == kCCSuccess) NSLog(@"SUCCESS");
        /*else*/ if (ccStatus == kCCParamError) return @"PARAM ERROR";
        else if (ccStatus == kCCBufferTooSmall) return @"BUFFER TOO SMALL";
        else if (ccStatus == kCCMemoryFailure) return @"MEMORY FAILURE";
        else if (ccStatus == kCCAlignmentError) return @"ALIGNMENT";
        else if (ccStatus == kCCDecodeError) return @"DECODE ERROR";
        else if (ccStatus == kCCUnimplemented) return @"UNIMPLEMENTED";

        NSString *result = [[ NSString alloc ] initWithData: [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes] encoding:NSASCIIStringEncoding];
        NSLog(@"%@", result);
        return result;
    }

person Greg M.    schedule 09.01.2012    source источник


Ответы (3)


Используйте эту функцию для шифрования и дешифрования. (Просто введите закодированную строку с тем же ключом еще раз, чтобы декодировать ее).

-(NSString*) rc4Key:(NSString*) key str:(NSString*) str
{    
    int j = 0;
    unichar res[str.length];
    const unichar* buffer = res;
    unsigned char s[256];
    for (int i = 0; i < 256; i++) 
    {
        s[i] = i;
    }
    for (int i = 0; i < 256; i++) 
    {
        j = (j + s[i] + [key characterAtIndex:(i % key.length)]) % 256;

        swap(s[i], s[j]);
    }

    int i = j = 0;

    for (int y = 0; y < str.length; y++) 
    {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        swap(s[i], s[j]);

        unsigned char f = [str characterAtIndex:y] ^ s[ (s[i] + s[j]) % 256];
        res[y] = f;
    }
    return [NSString stringWithCharacters:buffer length:str.length];
}
person user1036272    schedule 02.07.2012

Я вижу пару ссылок на DES в вашем коде (kCCKeySizeDES, kCCBlockSize3DES). Это кажется неправильным - как минимум, kCCKeySizeDES следует заменить на keyLength.

Если это не решит проблему, я бы рассмотрел возможные проблемы с кодировкой текста. Данные в SQLite могут быть двоичными данными в кодировке UTF8, и в этом случае вам, вероятно, придется «декодировать» их путем преобразования из UTF8 в ISO8859-1.

person Community    schedule 09.01.2012
comment
Я изменил размер ключа на keyLength, но я не думаю, что он даже использует kCBlockSize3DES, поскольку RC4 не использует блоки. И я не думаю, что кто-либо из них объяснил бы, почему я каждый раз получаю разные ответы (и кодировка не влияет на это). Любые другие предложения? У вас есть блок кода, который я мог бы попробовать? - person Greg M.; 12.01.2012

Реализация RC4 переведена с .net:

+(NSString*)RC4:(NSString *)data key:(NSString *)key
{
    id x;
    int y = 0;
    int i = 0;
    int j = 0;
    NSMutableArray *box = [[NSMutableArray alloc] initWithCapacity:256];
    NSString *result = @"";

    for (i = 0; i < 256; i++) {
        [box addObject:[NSNumber numberWithInt:i]];
    }

    for (i = 0; i < 256; i++) {
        j = ((int)[key characterAtIndex:(i % key.length)] + [[box objectAtIndex:i] intValue] + j) % 256;
        x = [box objectAtIndex:i];
        [box setObject:[box objectAtIndex:j] atIndexedSubscript:i];
        [box setObject:x atIndexedSubscript:j];
    }

    for (i = 0; i < data.length; i++) {
       y = i % 256;
       j = ([[box objectAtIndex:y] intValue] + j) % 256;
       x = [box objectAtIndex:y];
       [box setObject:[box objectAtIndex:j] atIndexedSubscript:y];
       [box setObject:x atIndexedSubscript:j];

       NSString *c = [NSString stringWithFormat:@"%c", ([data characterAtIndex:i] ^     (char)[[box objectAtIndex:([[box objectAtIndex:y] intValue] + [[box objectAtIndex:j] intValue]) % 256] intValue])];

       result = [result stringByAppendingString:c];

    }

    return result;
}
person Bogdan Carmanus    schedule 26.08.2014